One container = one job
A section container should handle overall structure. A wrapper inside it should handle the layout of repeated items. Each card or item should handle its own internal content.
Responsive design ensures that a website looks good and functions correctly on all devices — desktops, tablets, and mobile phones. It uses flexible layouts, scalable units, and media queries to adapt content to different screen sizes.
Desktop:
What should stay in a row?
Tablet:
What starts to feel cramped?
Mobile:
What should stack?
What should become one column?
Always:
content first → layout second
Media queries apply CSS rules only when certain conditions are met, such as screen width. They are the foundation of responsive design.
A breakpoint is not:
"pick random widths"
A breakpoint is:
"the layout starts to feel wrong here"
Two approaches:
Mobile-first → write for small screens first, scale up with min-width
Desktop-first → write for large screens first, scale down with max-width
Mobile-first is recommended.
It forces you to start with what matters most.
| Approach | Query | Description |
|---|---|---|
| Mobile-first | @media (min-width: 600px) | Applies styles when screen is 600px or wider |
| Mobile-first | @media (min-width: 768px) | Applies styles at tablet width and above |
| Mobile-first | @media (min-width: 1024px) | Applies styles at desktop width and above |
| Desktop-first | @media (max-width: 768px) | Applies styles to tablets and smaller |
| Desktop-first | @media (max-width: 480px) | Applies styles to mobile only |
Mobile-first example (min-width):
/* default — mobile */
.container {
flex-direction: column;
}
/* tablet and up */
@media (min-width: 600px) {
.container {
flex-direction: row;
}
}
Desktop-first example (max-width):
/* default — desktop */
.container {
flex-direction: row;
}
@media (max-width: 600px) {
.container {
flex-direction: column;
}
}
Responsive units scale with the screen size, making layouts more flexible and adaptive.
% → based on parent
vw → based on viewport width
vh → based on viewport height
rem → based on root font size
Rule:
avoid relying on fixed px for everything
| Unit | Description | Example |
|---|---|---|
| % | Percentage of the parent element. | width: 50%; |
| vw | Viewport width (1vw = 1% of screen width). | font-size: 5vw; |
| vh | Viewport height (1vh = 1% of screen height). | height: 50vh; |
| rem | Scales with root font size. | padding: 2rem; |
| clamp() | Sets a min, preferred, and max value. | font-size: clamp(1rem, 2vw, 2rem); |
Useful:
font-size: clamp(1rem, 2vw, 2rem);
Flexbox provides a flexible layout model that adapts naturally to different screen sizes. It is ideal for navigation bars, card layouts, and content alignment.
flex-direction: row; flex-direction: column;
Main axis → left ↔ right Main axis → top ↕ bottom
Cross axis → top ↕ bottom Cross axis → left ↔ right
Desktop:
[ item ][ item ][ item ]
Mobile:
[ item ]
[ item ]
[ item ]
| Property | Description | Example |
|---|---|---|
| display: flex | Enables flexbox layout. | div { display: flex; } |
| flex-wrap | Allows items to wrap onto new lines. | flex-wrap: wrap; |
| justify-content | Controls horizontal alignment. | justify-content: space-between; |
| align-items | Controls vertical alignment. | align-items: center; |
| flex-direction | Controls the direction of items. | flex-direction: column; |
Use justify-content to control alignment along the main axis in flexbox. justify-content
CSS Grid is a powerful layout system that allows you to create complex, responsive two-dimensional layouts with ease.
Important: display: grid; does not automatically create multiple columns.
Default = 1 column If I do not define columns, items stack vertically.
Grid item sizing:
Grid items stretch to fill their grid area by default.
2 columns = each item has less space
1 column = each item has more space
If a child gets wider on mobile, it is usually because the grid track became wider.
Grid alignment: justify-items → parent controls all grid children justify-self → one child controls itself Rule: Use the parent for default behaviour. Use the child only for exceptions.
Desktop:
[ 1 ][ 2 ][ 3 ]
Tablet:
[ 1 ][ 2 ]
[ 3 ]
Mobile:
[ 1 ]
[ 2 ]
[ 3 ]
| Property | Description | Example |
|---|---|---|
| display: grid | Enables grid layout. | div { display: grid; } |
| grid-template-columns | Defines column structure. | grid-template-columns: 1fr 1fr; |
| grid-template-rows |
Defines rows structure.
It's a space for the separator. |
grid-template-rows: 1fr 1fr; |
| grid-area | Shorthand to place an item by row and column in one line: row-start / col-start / row-end / col-end. Can also name an area defined in grid-template-areas. | grid-area: 1 / 1 / 3 / 3; |
| gap | Controls spacing between grid items. One value sets both. Two values set row then column — use a space not a comma: gap: 10px 5px not gap: 10px, 5px | gap: 20px; gap: 10px 5px; |
| repeat() | Repeats column or row patterns. | grid-template-columns: repeat(3, 1fr); |
| minmax() | Sets a size range for grid tracks. | minmax(200px, 1fr) |
Useful pattern:
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
A section container should handle overall structure. A wrapper inside it should handle the layout of repeated items. Each card or item should handle its own internal content.
Use
align-self
when one flex child needs different cross-axis alignment from its
siblings.
Example use cases:
max-width
limits how large something can become
width: 100%
makes an element fill its parent
If you want exactly 3 cards per row, a percentage-based width is often a better choice than max-width alone.
Test the layout and see where it actually breaks. The true breakpoint is the point where the design stops fitting comfortably.
For galleries and repeated cards:
These layout patterns are frequently used to create responsive websites that adapt smoothly across devices.
Gallery / cards:
Desktop → 3 across
Tablet → 2 across
Mobile → 1 across
Text + image:
Desktop → side by side
Mobile → stacked
Navigation:
Desktop → row
Mobile → wrap / stack / simplify
| Pattern | Description | Example |
|---|---|---|
| Stacking Columns | Columns become rows on smaller screens. | @media (max-width: 768px) { flex-direction: column; } |
| Responsive Navigation | Nav collapses or stacks on mobile. | @media (max-width: 600px) { nav a { display: block; } } |
| Fluid Typography | Text scales with viewport size. | font-size: clamp(1rem, 2vw, 2rem); |
| Auto-Fit Grid | Grid items fill available space. | grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); |
Images are part of responsive layout too. If an image looks wrong, check the container first, then check how the image fits inside it.
Container first
Image second
If image looks too small:
→ maybe too many columns
If image looks awkward:
→ check crop area / fit / container width
| Idea | Description | Example |
|---|---|---|
| Fluid width | Image scales with its container. | width: 100%; |
| Keep ratio | Avoid distortion when resizing. | height: auto; |
| Crop intentionally | Control how the image fills a box. | object-fit: cover; |
| Choose visible area | Keep the important part of the image in view. | object-position: center; |
Layout breaking?
→ what should stack?
Tablet awkward?
→ it may need its own layout decision
Gallery looks too tight?
→ reduce columns
Images look wrong?
→ check the container first
Responsive not working?
→ check breakpoint width
Desktop works but mobile doesn't?
→ reduce, stack, simplify