"Mobile-first" means the base styles describe the small screen, and media queries add complexity as the space grows. It is not only a phrase in a tutorial — it changes the shape of the CSS, and it is usually less code than the other way round.
Why is it less code?
Because the small screen is the hardest case. If you build for a phone first, the base CSS handles the narrowest layout, and each query only has to add what is missing.
/* mobile first: the base is one column, and the query adds the second */
.layout {
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
}
@media (min-width: 48rem) {
.layout {
grid-template-columns: 16rem 1fr;
}
}
The other way round, you start with the two-column layout and have to undo it at every width, which means a second set of rules for everything the single-column version got for free.
/* desktop first: the same result, but with an override block */
.layout {
display: grid;
grid-template-columns: 16rem 1fr;
gap: 1.5rem;
}
@media (max-width: 47.99rem) {
.layout {
grid-template-columns: 1fr; /* undo the columns */
}
.sidebar { display: none; } /* undo the sidebar */
}
Notice how much more the desktop-first version has to say. The overrides are not just about layout: anything that was shown on the wide screen and has to disappear on the narrow one is an extra rule that the mobile-first version never needed, because it was never shown in the first place.
Why does it avoid specificity problems?
Because the cascade is used in the direction it was designed for. Each media query comes later in the stylesheet, so it wins on source order when the specificity is the same — and no rule needs to be made artificially specific to beat another one.
/* mobile first: equal specificity, later wins */
.card { padding: 1rem; }
@media (min-width: 48rem) { .card { padding: 1.5rem; } }
/* the trap: fighting specificity with !important */
@media (max-width: 47.99rem) {
.page .card { padding: 1rem !important; }
}
With mobile-first styles, the natural order of the stylesheet is also the natural order of the cascade. Nothing has to be overridden, so nothing has to be escalated, so the stylesheet stays flat and readable.
What does the mobile-first model give you?
Four things, in rough order of usefulness. The base CSS describes the simplest case, which is the easiest to reason about. The queries add features, one screen size at a time, so you can see what each one is for. The stylesheet is smaller, because nothing is undone. And the mental model matches how the page is actually used — most traffic on a content site is on a phone, and the narrow layout is the one that has to be right.
mobile first
base: one column, everything visible, no hover
48rem: sidebar appears
64rem: three columns of cards
80rem: wider measure, more whitespace
desktop first
base: three columns, sidebar, hover effects
overrides: hide the sidebar, single column, remove hover
The "no hover" part is worth emphasising. Hover styles only exist on a wide screen, and a touch device has no hover state at all, so any interaction that depends on hover is broken on a phone. Writing the base styles without hover, and adding it in a query that also matches a pointer, makes that explicit.
.card { background: #fff; }
@media (hover: hover) and (pointer: fine) {
.card:hover { background: #f7f7f7; }
}
What is the pitfall?
That "mobile-first" gets interpreted as "ignore everything bigger than a phone". The base styles still have to be a complete, usable design — they are not a stripped-down placeholder that the queries fill in later. If the base version is missing the navigation entirely and a query adds it, then the site is broken for anyone whose query never matches, which includes a browser that does not understand the syntax.
The second pitfall is the opposite: writing the base styles for the smallest phone you can imagine and then finding that a large phone in landscape still looks wrong. The base should be the narrowest case that still works, and the queries should cover the ways the space grows.
How do you write mobile-first media queries?
Mobile-first is a way of writing the queries, not just a philosophy. The base rules describe the narrow screen, and each media query adds what is needed when there is more room. The query you write is therefore a min-width query - "from this width and up" - rather than a max-width query.
/* the base: a single column, comfortable on a phone */
.layout {
display: grid;
gap: 1.5rem;
}
/* from tablet width, two columns */
@media (min-width: 45rem) {
.layout {
grid-template-columns: 1fr 1fr;
}
}
/* from desktop width, three columns plus a sidebar */
@media (min-width: 70rem) {
.layout {
grid-template-columns: 16rem 1fr 1fr;
}
}Read that as a series of additions. The first rule is what everybody gets. The second adds a second column to anyone with enough room. The third adds a third column and a sidebar, and it does not undo the second - it just adds to it. No rule anywhere has to say "and below this width, go back to one column", because nothing was ever set that way.
That is where the reduction in code comes from. A desktop-first stylesheet needs a base rule for wide screens and then an override for every narrow one, and each override has to remember what the wide layout looked like. A mobile-first stylesheet has one base rule and a series of purely additive changes, and you can read it from the top as a description of how the page grows.
Two things to watch. The rem in the query is deliberate - a min-width: 45rem query responds to the user's font size as well as the window, while 45em would be relative to the root font size of the element the query is evaluated against. And the breakpoints should be the ones the content needs, not the ones a device catalogue lists; the next section is about finding them.
Quick reference
- Mobile-first means the base styles are the small-screen styles and the queries add complexity.
- It is usually less code, because nothing has to be undone.
- It uses the cascade in its natural direction, so no specificity escalation is needed.
- The base CSS must be a complete design, not a placeholder.
- Add hover styles inside a
(hover: hover)query, because touch screens have no hover state. - Choose breakpoints by narrowing the window, not by listing device widths.
Try it yourself: take a stylesheet you have written desktop-first and rewrite it mobile-first, moving the wide-screen rules into a query and deleting the overrides. Count the lines before and after. Then narrow the window and confirm the page is still complete and usable at every width, not just at the widths you designed for.