Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Media queries

A site is opened both on a phone 360 pixels wide and on a monitor 2500 pixels wide. Responsive layout adapts the page to any screen: it changes the number of columns, the sizes and the spacing. Its main tool is media queries.

The viewport tag

Without this tag a phone shows the page shrunk, as on a wide screen, and media queries do not fire. It is required in the <head> of every page:

<meta name="viewport" content="width=device-width, initial-scale=1">
<p>Now the page width equals the width of the device screen.</p>

The @media rule

A media query is an @media block with a condition in parentheses. The rules inside it apply only while the condition holds:

<style>
  .box { padding: 16px; background: lightskyblue; }
 
  @media (min-width: 500px) {
    .box { background: gold; }
  }
</style>
 
<div class="box">Narrow window — blue, wide — yellow</div>

The condition checks the width of the window the page is shown in. The example window is as wide as the text column. Narrow the browser window until the example is under 500 pixels wide — the block turns blue. The most convenient way is the device mode of the developer tools; there is a lesson on them at the end of the course.

min-width and max-width

ConditionWhen it fires
(min-width: 600px)The window is 600px wide or more
(max-width: 599px)The window is 599px wide or less
(600px <= width <= 900px)From 600 to 900 pixels — the new range syntax

The widths at which the layout changes are called breakpoints. Pick them by the content: where the layout starts to look bad.

Phone first

A handy approach is called mobile first: first write simple styles for a narrow screen, then extend them for a wide one in @media (min-width: ...):

<style>
  .cards { display: grid; gap: 8px; }
  .cards div { padding: 16px; background: lightskyblue; }
 
  @media (min-width: 500px) {
    .cards { grid-template-columns: 1fr 1fr 1fr; }
  }
</style>
 
<div class="cards">
  <div>One</div><div>Two</div><div>Three</div>
</div>

A wide window has three columns, a narrow one has one. The narrow version needed no media query at all.

Rebuilding the skeleton

A media query can change the whole grid template. On a phone the menu goes above the text, on a wide screen to the left of it:

<style>
  .page { display: grid; gap: 8px; grid-template-areas: "menu" "main"; }
  .page > * { padding: 8px; background: honeydew; }
  nav { grid-area: menu; }
  main { grid-area: main; }
 
  @media (min-width: 500px) {
    .page { grid-template-columns: 120px 1fr; grid-template-areas: "menu main"; }
  }
</style>
 
<div class="page">
  <nav>Menu</nav>
  <main>The page content</main>
</div>

Other conditions

Media queries check more than width. Conditions are joined with the word and:

ConditionWhat it checks
(orientation: landscape)The screen is turned horizontally
(hover: hover)There is a mouse, elements can be hovered
(prefers-color-scheme: dark)The system uses a dark theme
(prefers-reduced-motion: reduce)The user asked for less animation
printThe page is being printed: @media print

For example, @media (min-width: 500px) and (hover: hover) fires only on a wide screen with a mouse.

Common mistake

A media query does not raise specificity — the strength of a selector. If a normal rule stands below the media query, it overrides it, and nothing changes at any width:

<style>
  @media (min-width: 300px) {
    .box { background: gold; }
  }
  .box { padding: 16px; background: lightskyblue; }
</style>
 
<div class="box">Always blue: the rule below won</div>

Write media queries after the main styles of the same element.

Thanks for reading!

Donate to the site — we work hard for you.