Media Queries and User Preferences
A single layout rarely suits every screen: three cards side by side look right on a laptop and cramped on a phone. And some visitors have told their device something about themselves, such as "I prefer a dark screen" or "animation makes me unwell". A media query is a condition in CSS: apply these rules only when the screen is at least this wide, or only when the person has asked for a dark screen. The first kind reshapes the layout. The second kind listens to the person.
A thermostat works on the same idea. It holds instructions written in advance, "heat when it drops below 19 degrees", and reads the room to decide which apply. A stylesheet with media queries is written once, and the browser checks the conditions on each device, and again whenever they change.
Width Queries and Breakpoints
A media query wraps ordinary rules inside an @media block with a condition in brackets. The rules inside apply only while the condition is true. The most common condition is a minimum width, which fits the mobile-first habit from the last topic: the default rules are for narrow screens, and the query adds to them when there is room.
@media (min-width: 40rem) {
body {
font-size: 1.125rem;
}
}
This query makes the body text slightly larger on any screen at least 40 rem wide. Drag the edge of the window across that width and the text size changes the moment you cross it. Inside a media query, a rem means the browser's default text size, usually 16 pixels, so 40 rem is normally 640 pixels. If a reader has set a larger default text size, the breakpoint moves with it, which is what they would want.
The width where a layout changes is called a breakpoint. It is tempting to pick breakpoints from device names, a phone width, a tablet width, a laptop width. Devices change every year, though, and there are thousands of sizes. The better method is to ask the content: widen the window slowly in device mode, and put a breakpoint where the layout starts to look wrong, such as lines grown too long or cards squashed too narrow.
The Site at Two Widths
In Chapter 4 the site's project grid got three columns on every screen, which is too wide for a phone screen. Mobile-first, the fix is to make one column the default and add the three columns only when the screen is wide enough. Replace the .project-grid rule in css/style.css with these two.
.project-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-l);
}
@media (min-width: 40rem) {
.project-grid {
grid-template-columns: repeat(3, 1fr);
}
}
On a phone, the Projects page now shows the three cards in a single column, one under another, each the full width of the screen. From 40 rem up, the query switches on and the same cards sit side by side in three columns, as before. In DevTools' Styles pane, the rule inside the query is shown with its @media condition above it, and it disappears from the list when the window is narrower than the breakpoint.
A Dark Theme from One Small Block
Most operating systems let people choose a light or dark appearance. The media feature prefers-color-scheme reads that choice: it is dark when the person has chosen a dark appearance and light otherwise.
In Chapter 3 the site put its colours into custom properties on :root, the design tokens. That is what makes the dark theme small. Every rule already uses the tokens, such as var(--color-text), so redefining the tokens inside a query changes every colour on every page at once.
@media (prefers-color-scheme: dark) {
:root {
--color-text: #e6e6e6;
--color-bg: #121212;
--color-accent: #8ab4f8;
}
}
Put this block after the :root block from Chapter 3. Both use the same selector, so the later one wins whenever its condition is true, the ordering rule of the cascade. With the computer set to dark, the whole site turns to light grey text on a near-black background, with a lighter blue for links and accents, and no other rule changes. With the computer set to light, the query does not apply and the site looks as it did. The spacing and font tokens are left out on purpose: they do not change with the theme.
Chapter 9 adds a button that lets a visitor override this choice for the site alone. It builds on this block.
Reduced Motion
For some people, movement on a screen causes real dizziness, nausea or headaches. This is common among people with vestibular disorders, which affect the inner ear's sense of balance. Operating systems have a setting to reduce motion, and the media feature prefers-reduced-motion reads it. Its value is reduce when the setting is on.
The site has no animation yet, so this example is a fragment. A transition makes a change happen gradually instead of at once, and here a card glides upwards slightly when the pointer is over it.
.card {
transition: transform 0.2s;
}
.card:hover {
transform: translateY(-4px);
}
@media (prefers-reduced-motion: reduce) {
.card {
transition: none;
}
}
For most visitors, hovering over a card makes it rise four pixels over a fifth of a second. For a visitor who has asked for reduced motion, the query removes the transition, and the card moves at once instead of gliding. The rule of thumb: any animation that moves things across the screen, and smooth scrolling, should be switched off or toned down under reduce.
To test both preferences without changing your computer's settings, open the DevTools Command Menu with Ctrl+Shift+P on Windows or Cmd+Shift+P on macOS, type "rendering", and choose Show Rendering. The Rendering panel has a setting to emulate prefers-color-scheme and one for prefers-reduced-motion. Switch them and the page responds at once.
Other Media Features
A few more are worth knowing by name. The hover and pointer features describe the input device. A query asking whether the main pointer can hover is true for a mouse and false for a finger on a touch screen, and one asking whether the pointer is coarse, meaning imprecise, is true for a finger. And a print query, written @media print, holds rules for printing, such as hiding the navigation from a printed page.
- "Breakpoints are the phone, tablet and desktop sizes." Device sizes change every year. The content tells you where it breaks: widen the window and put the breakpoint where the layout starts to look wrong.
- "Dark mode means writing a second stylesheet." With colour tokens it is one small block that redefines three custom properties. Every rule that uses them follows.
- "Motion preferences are a niche concern." For people with vestibular disorders, movement on screen can cause real sickness. Honouring the setting costs a few lines.
- The site now respects both the screen it is on and the person using it, without a second version of anything.
- Tokens plus one query are the whole dark theme. The theme switch in Chapter 9 is built on the same block.
Knowledge Check
What is the best way to choose where a breakpoint goes?
- Use the widths of the most popular phones and tablets
- Widen the window and see where the content looks wrong
- Add one every hundred pixels so every size is covered
- Use the three standard widths that browsers support
What does the prefers-color-scheme media feature read?
- The colours already used in the site's own stylesheet
- How bright the room is, from the device's light sensor
- Whether the person's system is set to light or dark
- Whether it is daytime or night-time where the visitor is
Why does the dark theme need only one small block of CSS?
- The browser works out the dark colours by itself
- It copies every rule and changes each colour inside
- Dark mode removes all the colours and uses only grey
- Every rule uses the tokens, and only the tokens change
Who is prefers-reduced-motion mainly for?
- People whom movement on a screen can make ill
- People whose phones are too slow to animate things
- People who use a screen reader to hear pages
- People who want to save mobile data on the go
You got correct