Your page reads well at whatever width you have been testing it at, but nothing in your CSS has ever asked how wide that is. This lesson introduces media queries: CSS rules that only apply within a range of screen widths. It also introduces mobile-first design. You write your base rule for a small screen with no condition at all. Then you add a media query that changes the layout once there is more room. Every sandbox on this page, including your own exercise below, has DESKTOP and PHONE buttons above its preview. Use them to check your work at both sizes as you go.
The concept
Here is your page as it stands. Run it, then click PHONE in the preview toolbar:
▸WHAT'S ALREADY IN THIS PAGE
New here? This starter already carries the standard HTML frame. You do not need to change it to do the exercise — each piece is taught in its own lesson.
<!DOCTYPE html>— Tells the browser to use modern rendering rules. Taught in lesson 2.<html> … </html>— The root element that wraps the whole document. Taught in lesson 2.lang="en"— Sets the page's language. Taught in lesson 6.<head>— Holds information about the page; nothing in it is drawn on screen. Taught in lesson 2.<meta charset="UTF-8" />— Sets how the browser decodes the text. Taught in lesson 6.<title>— Sets the browser-tab text. Taught in lesson 2.<body>— Holds everything a visitor actually sees. Taught in lesson 2.
The "where you left off" demos show the placeholder version of the page. Your own page, with your real content, is safe in the exercise below.
Your nav and your Skills cards still show as a row at every width, phone included. Nothing in your CSS distinguishes one screen size from another yet. Here is that same idea, stripped down to three plain cards. Run it, then click PHONE.
The cards stay in a row no matter how narrow the screen gets. Each one is squeezed into less space, because nothing here mentions screen width at all. display: flex says nothing about how wide the screen is, only how the items inside the row should behave once there is a row.
Now run this version, and click PHONE, then DESKTOP.
On PHONE, the same three cards stack, one on top of another. Each one gets the full width of the screen instead of a third of it. On DESKTOP, they return to a row. The only change from the last demo is flex-direction: column written as the plain rule with no condition, plus one new block: @media (min-width: 500px). That block switches the same property to row once the screen is at least 500 pixels wide. The column rule is the mobile-first default. It applies everywhere, phone included, until a wider screen earns the row.
Apply the same pattern to your real nav. Run it, then toggle PHONE and DESKTOP.
Your About, Skills, and Contact links stack on a narrow screen and line up in a row on a wide one. It is the same flex-direction: column plus @media (min-width: 500px) pattern.
Past 500 pixels, both rules apply to the nav, and they disagree. When two rules of equal weight disagree, the one later in the file wins. That is the cascading in CSS's name, and it is why the media block must sit at the end.
Your Skills cards take the same treatment. Run it, then toggle both buttons.
HTML, CSS, and JavaScript stack on PHONE, each card given the panel's full width, and return to a row on DESKTOP.
The syntax
A media query wraps ordinary CSS rules inside a condition about the screen.
@media (min-width: 500px) {
nav {
flex-direction: row;
}
}@media starts the block. The parentheses hold the condition: min-width: 500px matches once the space the page is displayed in is at least 500 pixels wide, and stays matched at every width above that. Here that space is the preview pane; on a real device it is the screen. Inside the braces, you write ordinary rules exactly as you would anywhere else in the file. Those rules apply only while the condition holds.
The mobile-first pattern writes the small-screen layout as the plain rule, with no media query at all. It reaches for @media (min-width: ...) only to add a different layout once the screen is wide enough to use it.
nav {
display: flex;
flex-direction: column;
}
@media (min-width: 500px) {
nav {
flex-direction: row;
}
}The first rule runs on every screen, narrow or wide. The second rule only takes over past 500 pixels. A narrow phone never has to satisfy the media query at all. It gets the plain rule, written with a small screen in mind from the start.
A minimal working example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Responsive basics</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="row">
<div class="card">One</div>
<div class="card">Two</div>
</div>
</body>
</html>.row {
display: flex;
flex-direction: column;
gap: 1rem;
}
@media (min-width: 500px) {
.row {
flex-direction: row;
}
}One column rule with no condition, and one media query that switches it to a row once the screen has the width to support one.
Common mistakes
You want a column on a narrow phone and a row on a wide screen. You write @media (max-width: 500px) around your row rule instead of @media (min-width: 500px). Toggle PHONE and DESKTOP. The result is backwards from what you intended. Run it:
PHONE shows a row, cramped into a screen that was supposed to get the simpler column layout. DESKTOP shows a column, wasting the width it has to work with. max-width: 500px matches screens at or narrower than 500 pixels, the opposite range from min-width: 500px. The row rule landed on the narrow screen instead of the wide one. Reading the condition as "widths up to here" versus "widths from here up" is the difference that matters.
Your media query has no visible effect, and the console shows no error at all. Count the braces. A media query needs two closing braces near the end: one for the rule inside it, one for @media itself. A missing outer brace can leave the next rule you write silently swallowed into the still-open block. It can also leave the media rule itself never properly closed. CSS never reports this with an error message. When a newly added rule seems to do nothing, and the property and selector both look right, recount the braces before anything else.
Try it yourself
Your nav and your Skills cards line up in a row at every screen width right now, phone included. Give them a layout that adapts instead. The nav sits in the header above the fold. After each Run that asks about the skill cards, scroll the preview to Skills if you do not see them yet.
- Run the starting code below. Toggle to PHONE. Confirm your nav links still line up in a row, exactly as they do on DESKTOP. Scroll the preview to Skills if you do not see it yet. Confirm your three skill cards still line up in a row too. Nothing adjusts for the narrower screen yet.
- In
styles.css, addflex-direction: column;to yournavrule. Run it. Toggle PHONE and DESKTOP. Confirm the nav links now stack vertically at both sizes. A plain rule with no media query applies everywhere. - At the end of
styles.css, add a new block:@media (min-width: 500px) { nav { flex-direction: row; } }. Run it. Toggle DESKTOP. Confirm the nav returns to a row. Toggle PHONE. Confirm it still stacks, since the screen does not reach 500 pixels. - Add
flex-direction: column;to your.skill-rowrule, and add.skill-row { flex-direction: row; }inside the same media query block from step 3. Run it. Toggle PHONE. Scroll to Skills. Confirm your three skill cards now stack one under another. Toggle DESKTOP. Confirm they return to a row. - Break it on purpose: change
@media (min-width: 500px)to@media (max-width: 500px), leaving everything inside it the same. Run it. Toggle PHONE. Confirm the nav shows as a row, cramped into the narrow screen. Scroll to Skills. Confirm the cards show as a row too. Toggle DESKTOP. Confirm they now show as a stacked column instead, the opposite of both of the last two steps. - Fix it: change
max-widthback tomin-width. Run it. Toggle PHONE and DESKTOP. Confirm the column-on-narrow, row-on-wide behavior returns for the nav. Scroll to Skills and confirm the cards match.
▸WHAT'S ALREADY IN THIS PAGE
New here? This starter already carries the standard HTML frame. You do not need to change it to do the exercise — each piece is taught in its own lesson.
<!DOCTYPE html>— Tells the browser to use modern rendering rules. Taught in lesson 2.<html> … </html>— The root element that wraps the whole document. Taught in lesson 2.lang="en"— Sets the page's language. Taught in lesson 6.<head>— Holds information about the page; nothing in it is drawn on screen. Taught in lesson 2.<meta charset="UTF-8" />— Sets how the browser decodes the text. Taught in lesson 6.<title>— Sets the browser-tab text. Taught in lesson 2.<body>— Holds everything a visitor actually sees. Taught in lesson 2.
Your nav and your Skills cards now adapt to the screen instead of staying identical at every width. That is the last piece Act II set out to teach. Your page has structure, a chosen palette, considered spacing, and a layout that holds up on a phone. The checkpoint ahead looks at everything Act II added. It also names honestly what still has not changed: the page has no way yet to respond to anything a visitor does.