CSS for layout: Flexbox, Grid and responsiveness
Lesson 4 of 8
4CSS for layout: Flexbox, Grid and responsiveness
The big pictureWithout layout CSS, every element drops below the one before it in a long column. This lesson gives you the two tools that cover 95% of web layouts, Flexbox and Grid, then makes your page adapt by itself from a small phone to a wide screen.
What the picture shows: From a column of boxes to a full page: Flex lines the bar's items up in a row, Grid splits the cards into columns, and a media query changes the layout when the screen widens.
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
Imagine arranging books. Flexbox is one shelf: you line books up side by side, decide whether they start from one end or spread with equal gaps, and when the shelf fills you move to the one below. Grid is a bookcase of cubbies: you divide the wall into rows and columns and put each book in its cubby. Responsiveness means the bookcase rearranges itself: in a narrow room (a phone) one column, in a wide room (a desktop) three.
Flex is one-dimensional: a main axis (flex-direction) governed by justify-content, a cross axis governed by align-items, flex: 1 distributes spare space (flex-grow/flex-shrink/flex-basis), and flex-wrap breaks the row. Grid is two-dimensional: grid-template-columns tracks with the fr unit, minmax() and repeat(auto-fit, ...) for grids that respond without queries, and grid-template-areas for a named layout. Responsiveness: meta viewport, then mobile first with @media (min-width), clamp() for fluid sizes, and container queries @container for components that respond to their container rather than the screen. Custom properties (--name) inherit, are read with var(), and change inside prefers-color-scheme. Logical properties (inline/block) follow writing-mode and dir. transition animates animatable properties, respecting prefers-reduced-motion.
Before You Start
🖌️CSS from zero
You know selectors, the box and specificity.
🧱Semantic HTML
You write a page with header, nav and main.
The Core Idea
1Flexbox: one tidy row
Write display: flex on the parent and it lines up its direct children in a row. Then three properties cover you most of the time: gap for the space between children, justify-content for how they spread along the row (space-between pushes the first to the start and the last to the end), and align-items for vertical alignment (center centres them). And the most famous CSS trick: centring anything in a box with two lines.
A nav bar and centring with Flex
Change justify-content in .nav to center, then flex-start. Then delete display: flex from .nav and watch the bar collapse into a column.
Notice that "start" on an Arabic page is the right: Flex follows the page direction automatically. flex-direction: column makes the axis vertical, flex-wrap: wrap lets items drop to a new line when space runs out, and flex: 1 on a child makes it take all the remaining space (like a search box that stretches).
2Grid: a mesh of rows and columns
display: grid with grid-template-columns divides the parent into columns. The fr unit means "a share of the remaining space": 1fr 2fr is two columns, the second twice the first. And the magic line repeat(auto-fit, minmax(160px, 1fr)) means: "fit as many columns of at least 160 as you can and share the rest equally", so the grid responds on its own with no query at all.
A menu grid that responds by itself
Drag the preview's bottom corner or shrink your browser window: the columns change on their own. Then change 140px to 250px.
For a whole page layout, name the regions with grid-template-areas and put each element in its region with grid-area. The drawing is almost the code itself:
.page {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-areas:
"head head"
"side main"
"foot foot";
gap: 16px;
}
header { grid-area: head; }
aside { grid-area: side; }
main { grid-area: main; }
footer { grid-area: foot; }3When Flex and when Grid?
One question settles it: are you controlling one dimension or two? A row of buttons, a nav bar, stacked items in a card, centring: Flex. A product grid, a photo gallery, a page with rows and columns: Grid. In practice you combine them: Grid for the page and the grid, Flex inside each card.
Grid for the grid, Flex inside the card
Notice the three buttons line up even though the names differ in length. Delete the margin-block-start: auto line to see the difference.
4Responsive design: mobile first
More than half of web visits come from phones. Mobile first means writing CSS for the small screen as the base, then adding changes for larger screens inside @media (min-width: 768px) { ... }. Do not forget the <meta name="viewport" content="width=device-width, initial-scale=1"> line in the head, or the phone shows your page zoomed out as if it were a desktop.
A page that turns from one column into two
Shrink your browser window until the preview is narrow: the sidebar column drops below. And clamp() grows and shrinks the heading smoothly between two limits.
5Variables and dark mode
A CSS variable is a name starting with two dashes, --brand, defined once (usually on :root, the whole page) and read with var(--brand) anywhere. Change its value in one place and the whole site changes. With @media (prefers-color-scheme: dark) you change the variables when the user's device is in dark mode, and get a complete dark mode in a few lines.
Dark mode from four variables
Press the button to switch mode. It uses one line of JavaScript you will understand in the DOM lesson. Change --brand in light mode to any other colour.
6Direction: one page for Arabic and English
margin-left always means "left", but in Arabic you usually want "the start of the line", which is the right. Logical properties solve this: inline is the line direction and block the direction lines stack in, with start/end for its beginning and end. So margin-inline-start is a margin on the right in Arabic and on the left in English, automatically from dir, with no second stylesheet.
The same rule in both directions
Notice .note is right in both directions, while .old is right only in English.
The short table: left/right become inline-start/inline-end, top/bottom become block-start/block-end, and text-align: left becomes text-align: start. The Darb platform itself is written this way so it works in Arabic and English.
7States and transitions: a page that feels alive
A good button changes when the mouse is over it (:hover), when pressed (:active), and when keyboard focus reaches it (:focus-visible). transition makes the change smooth instead of a jump: you say which property moves and over how long. Respect people who prefer less motion with prefers-reduced-motion.
A button with states and a smooth transition
Change .15s to 1s to watch the motion slowly.
outline: none because it is "ugly". Keyboard users get lost and cannot tell where they are. If you want to change it, design a clear replacement with :focus-visible; do not delete it.Worked example
Project: a complete responsive café page. The semantic structure from the HTML lesson, the bar with Flex, the menu with Grid and auto-fit, the cards as a Flex column with the button at the bottom, variables for colours, and logical properties for direction. Edit it freely, then copy it into your file:
The full café page
Change --brand to change the whole café's identity, and shrink the window to watch the cards move to one column.
Myth vs Reality
| Myth | Reality |
|---|---|
| Grid is newer, so always use it instead of Flex. | Both are here to stay: Flex for one dimension, Grid for two, and you often combine them. |
| Arabic needs a separate stylesheet. | Logical properties and dir cover most of the page. |
| Responsive means writing one version for phones and one for desktops. | One page with rules that adapt, and many of them (auto-fit, clamp) respond with no query at all. |
Where you meet it at work
🛒Online shops
Product grids are Grid, and each product card is Flex.
📱Sites that work on every device
One page serving phone, tablet and desktop.
🌐Bilingual sites
Logical properties flip the page between Arabic and English.
Test your understanding
#buy and .btn give a button two colours. Which wins?
Specificity counts before source order, and an id outranks a class.
You want a card grid whose columns adapt to width with no media query. What do you write?
auto-fit with minmax fits as many columns as the width allows.
Which property stays correct in both Arabic and English?
inline-start means "start of the line" in any writing direction.
You want to centre an element horizontally and vertically in a box. Quickest way?
Flex on the parent centres the child on both axes in two lines.
In "mobile first", what goes inside @media?
The base is for the small screen, and the query adds what changes as it widens.
Quick review cards
Check Your Understanding
When Flex and when Grid?
Flex for items in one row or column distributed by content; Grid when you control rows and columns together.
Why do we need meta viewport?
Without it the phone renders the page as if on a 980-pixel desktop and shrinks it, so media queries do not behave as you expect.
How do CSS variables help dark mode?
You change the variables in one place inside prefers-color-scheme and every element follows.
Why is !important a warning sign?
It breaks the natural cascade and forces a stronger !important later. The fix is lower specificity.
Resources for this lesson
Grouped by type. Start with the official docs for precision, or an article or video for the explanation.
Official docs1
Tools2
Done with this lesson?
Sign in to save your progress.