SypherTecSypherTec
PART 2 · 12 OF 127 MIN READUPDATED 6 AUG 2026

Responsive Basics: Media Queries and Mobile-First Design

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:

WHERE YOU LEFT OFF · HTML
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.
Untitled
RUN TO SEE YOUR PAGE

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.

A ROW WITH NO MEDIA QUERY · HTML
Untitled
RUN TO SEE YOUR PAGE

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.

THE SAME CARDS, WRITTEN MOBILE-FIRST · HTML
Untitled
RUN TO SEE YOUR PAGE

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 REAL NAV, WRITTEN MOBILE-FIRST · HTML
Untitled
RUN TO SEE YOUR PAGE

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.

YOUR REAL SKILLS LIST, WRITTEN MOBILE-FIRST · HTML
Untitled
RUN TO SEE YOUR PAGE

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

index.html
<!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>
styles.css
.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:

THE SAME PATTERN, WITH THE CONDITION BACKWARDS · HTML
Untitled
RUN TO SEE YOUR PAGE

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.

  1. 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.
  2. In styles.css, add flex-direction: column; to your nav rule. 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.
  3. 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.
  4. Add flex-direction: column; to your .skill-row rule, 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.
  5. 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.
  6. Fix it: change max-width back to min-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.
TRY IT YOURSELF · HTML
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.
Untitled
RUN TO SEE YOUR PAGE

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.

QUIZ · 3 QUESTIONSCheck what stuckStart the quiz
PART 2 · 12 OF 12