Category: reference
Responsive Design Patterns — CSS ที่ใช้จริงบน Static Site
Pattern สำหรับ responsive layout บน CSS ล้วนๆ ที่ใช้ได้จริง ครอบคลุม fluid typography, container queries, intrinsic grid และ mobile-first approach
สารบัญ
Mobile-First คืออะไร
เขียน CSS สำหรับ mobile ก่อน แล้ว override สำหรับ screen ใหญ่ขึ้นด้วย min-width:
/* base: mobile */
.grid {
display: flex;
flex-direction: column;
gap: 1rem;
}
/* tablet+ */
@media (min-width: 640px) {
.grid {
flex-direction: row;
flex-wrap: wrap;
}
}
/* desktop+ */
@media (min-width: 1024px) {
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
}
ตรงข้ามกับ desktop-first (เริ่มจาก desktop แล้ว override ด้วย max-width) ซึ่งมักทำให้ mobile code ซับซ้อน
Fluid Typography ด้วย clamp()
ปรับขนาดตัวอักษรตาม viewport อัตโนมัติ โดยไม่ต้องใช้ breakpoint:
h1 {
/* min: 1.5rem, preferred: 4vw, max: 2.5rem */
font-size: clamp(1.5rem, 4vw, 2.5rem);
}
.section-title {
font-size: clamp(1.1rem, 2.5vw, 1.75rem);
}
.section-description {
font-size: clamp(0.9rem, 1.5vw, 1.1rem);
}
clamp(MIN, PREFERRED, MAX) ทำให้ไม่เล็กเกินหรือใหญ่เกิน
Intrinsic Grid (Auto-fill)
Grid ที่ปรับ columns อัตโนมัติโดยไม่ต้อง media query:
.grid-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1rem;
}
auto-fill + minmax(280px, 1fr) หมายถึง “ใส่ให้มากที่สุดเท่าที่จะได้ โดยแต่ละ column กว้างอย่างน้อย 280px”
เหมาะมากสำหรับ card grid ที่ไม่รู้ว่าจะมีกี่ card
Container Queries (CSS ล่าสุด)
ตอบสนองต่อขนาดของ container ไม่ใช่ viewport — รองรับ browser ทุกตัวที่ modern แล้ว:
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: flex;
flex-direction: row;
}
}
ต่างจาก media query ที่ดู viewport — container query ดูขนาดของ parent element เหมาะกับ reusable components
Fluid Spacing
.section {
padding-block: clamp(2rem, 5vw, 4rem);
}
.container {
width: min(1100px, 100% - 2rem);
margin-inline: auto;
}
min() เลือกค่าน้อยกว่า — ทำให้ container ไม่กว้างเกิน 1100px และมี padding 1rem ทั้งสองข้างบน mobile
Logical Properties
ใช้ block/inline แทน top/bottom/left/right สำหรับ i18n-ready layout:
/* แทน */
margin-top: 1rem;
margin-bottom: 1rem;
padding-left: 1.5rem;
padding-right: 1.5rem;
/* ใช้ */
margin-block: 1rem;
padding-inline: 1.5rem;
Stack Layout Pattern
เนื้อหาเรียงแนวตั้งที่มีระยะห่างสม่ำเสมอ โดยไม่ต้องแตะ margin บน child elements:
.stack > * + * {
margin-top: 1.5rem;
}
/* หรือใช้ flex gap */
.stack {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
Aspect Ratio
รักษาสัดส่วนของ element โดยไม่ต้องใช้ padding-top hack:
.hero-image {
aspect-ratio: 16 / 9;
width: 100%;
object-fit: cover;
}
.avatar {
width: 4rem;
aspect-ratio: 1;
border-radius: 50%;
}
Common Breakpoints
/* Mobile-first breakpoints */
/* xs: < 480px — default */
@media (min-width: 480px) { /* sm */ }
@media (min-width: 640px) { /* md */ }
@media (min-width: 768px) { /* lg */ }
@media (min-width: 1024px) { /* xl */ }
@media (min-width: 1280px) { /* 2xl */ }
Tailwind CSS ใช้ breakpoints ชุดนี้ — ถ้าเคยใช้ Tailwind จะคุ้นเคย
Debugging Responsive Issues
/* เปิด outline ทุก element เพื่อดู box model */
* {
outline: 1px solid red;
}
/* ดู overflow ที่ซ่อนอยู่ */
* {
overflow-x: hidden;
}
หรือใช้ Chrome DevTools → Toggle device toolbar (Ctrl+Shift+M) เพื่อทดสอบ breakpoints