The mobile-first article explains the core idea: write your base CSS for small screens, then use min-width media queries to add styles as the screen gets larger. You build up from a lean foundation instead of stripping a heavy desktop layout down. This workbook turns that into ten runnable examples, from the basic pattern to a complete responsive page. The rule to keep in mind throughout: the styles outside any media query are your mobile defaults, and every min-width block is an enhancement for bigger screens.
1. The core mobile-first pattern
This is the whole philosophy in one file. The base rule has no media query, so it applies everywhere, including the smallest phone. The min-width block then adds to it only once the screen reaches 768px.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <div class="panel">Base styles on mobile, more padding from 768px up.</div></body></html>
/* Mobile base: applies to every screen */.panel { background: #f0f4f8; padding: 1rem; font-family: sans-serif;}/* Enhancement: only from 768px and wider */@media (min-width: 768px) { .panel { padding: 2rem; background: #d9e2ec; }}
Notice you are only ever adding. The mobile rule stays untouched and the larger screen simply receives extra styling on top, which is what the guide means by “adding is cleaner than overriding.”
2. The viewport meta tag
Mobile-first CSS does nothing without this one line of HTML. Without the viewport meta tag, phones render the page at a wide virtual width and zoom out, so your mobile styles never trigger. With it, the page uses the device’s real width.
<html lang="en"><head> <meta charset="utf-8"> <!-- This line makes the browser use the device width --> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <p class="note">Remove the viewport tag and reload on a phone to see the difference.</p></body></html>
.note { font-family: sans-serif; padding: 1rem; background: #f0f4f8;}
width=device-width tells the browser to match the screen’s real width, and initial-scale=1 sets the starting zoom to 100 percent. This tag belongs in every responsive page you build.
3. A container that grows at breakpoints
On mobile the content should fill the screen. As the screen widens, you cap and centre it so lines do not become uncomfortably long. The base is full width; each breakpoint sets a larger maximum.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <div class="container"> <p>Full width on mobile, then capped and centred on larger screens.</p> </div></body></html>
body { font-family: sans-serif; }.container { width: 100%; /* mobile: fill the screen */ padding: 0 1rem; margin: 0 auto; /* centre once it has a max-width */}@media (min-width: 768px) { .container { max-width: 720px; }}@media (min-width: 1024px) { .container { max-width: 960px; }}
The container is fluid by default and only gains a fixed ceiling as space allows. This progression, full width then 720px then 960px, is the classic mobile-first container.
4. One column to a multi-column grid
Stacking content in a single column is the natural mobile layout. You add columns as the screen earns the room. The base grid has one column; breakpoints add a second and third.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <div class="grid"> <div class="card">One</div> <div class="card">Two</div> <div class="card">Three</div> <div class="card">Four</div> </div></body></html>
body { font-family: sans-serif; padding: 1rem; }.grid { display: grid; grid-template-columns: 1fr; /* mobile: single column */ gap: 1rem;}.card { background: #f0f4f8; padding: 1.5rem; border-radius: 6px; }@media (min-width: 600px) { .grid { grid-template-columns: repeat(2, 1fr); } /* two columns */}@media (min-width: 1024px) { .grid { grid-template-columns: repeat(3, 1fr); } /* three columns */}
Read top to bottom and the layout grows with the viewport. The single-column default means the smallest screens get the simplest, fastest layout with no overrides to undo.
5. A mobile-first navigation
Navigation stacks vertically on a phone, where horizontal space is scarce, and becomes a row on wider screens. The base is a vertical flex column; one breakpoint switches it to a row.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <nav class="nav"> <a href="#">Home</a> <a href="#">Articles</a> <a href="#">Shop</a> </nav></body></html>
.nav { display: flex; flex-direction: column; /* mobile: stacked links */ gap: 0.5rem; padding: 1rem; background: #11243a; font-family: sans-serif;}.nav a { color: #cfe0f1; text-decoration: none; }@media (min-width: 768px) { .nav { flex-direction: row; /* wider screens: horizontal */ gap: 1.5rem; }}
The stacked default gives big, easy tap targets on a phone. The row layout is the enhancement, applied only when there is width to support it.
6. Fluid typography that scales up
Text should be comfortable on a small screen first, then grow on larger ones. Set the base size for mobile with no media query, then bump it up at breakpoints using rem so everything scales consistently.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <h1 class="title">A heading that grows with the screen</h1> <p class="body">Body text stays readable on mobile and scales up on desktop.</p></body></html>
html { font-size: 100%; } /* 16px base that rem refers to */body { font-family: sans-serif; padding: 1rem; }.title { font-size: 1.5rem; } /* mobile heading */.body { font-size: 1rem; }@media (min-width: 768px) { .title { font-size: 2rem; }}@media (min-width: 1024px) { .title { font-size: 2.5rem; }}
Because the sizes are in rem, they all key off the root font size, so the whole scale stays in proportion. The mobile size is the default and each larger screen receives a bigger heading.
7. Relative units instead of fixed pixels
Mobile-first leans on flexible units so layouts adapt rather than break. Widths in percentages and images capped with max-width keep content inside any screen.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <div class="feature"> <div class="block">Block A</div> <div class="block">Block B</div> </div></body></html>
body { font-family: sans-serif; padding: 1rem; }.feature { display: flex; flex-wrap: wrap; gap: 1rem; }.block { width: 100%; /* mobile: each block full width */ background: #f0f4f8; padding: 1.5rem; border-radius: 6px;}img { max-width: 100%; height: auto; } /* images never overflow */@media (min-width: 768px) { .block { width: calc(50% - 0.5rem); } /* two across on larger screens */}
The blocks are full width by default and share the row only when space allows. Fixed pixel widths would force horizontal scrolling on a phone, which is exactly what relative units avoid.
8. Min-width versus max-width
This example shows why mobile-first prefers min-width. The desktop-first max-width approach makes the desktop layout the default and then overrides it for mobile, which means writing the rule twice. The mobile-first version states the mobile default once and adds the desktop layout on top.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <div class="row"> <div class="col">A</div> <div class="col">B</div> </div></body></html>
body { font-family: sans-serif; padding: 1rem; }.col { background: #f0f4f8; padding: 1.5rem; border-radius: 6px; }/* Desktop-first (for contrast, not used here):.row { display: flex; gap: 1rem; }@media (max-width: 767px) { .row { display: block; } // override back to stacked}*//* Mobile-first: default is stacked, add the row on top */.row { display: block; }.row .col + .col { margin-top: 1rem; }@media (min-width: 768px) { .row { display: flex; gap: 1rem; } .row .col + .col { margin-top: 0; }}
Both produce the same result, but the mobile-first version reads as a clean progression rather than a default followed by an undo. Over a whole stylesheet, that difference is what keeps the CSS maintainable.
9. Content priority with order
Designing for a small screen forces you to decide what matters most, and you can put it first. Here the main content appears above the sidebar on mobile, then sits beside it on desktop, without changing the HTML.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <div class="layout"> <aside class="sidebar">Sidebar</aside> <main class="main">Main content, shown first on mobile.</main> </div></body></html>
body { font-family: sans-serif; padding: 1rem; }.layout { display: flex; flex-direction: column; gap: 1rem; }.sidebar { background: #d9e2ec; padding: 1rem; border-radius: 6px; }.main { background: #f0f4f8; padding: 1rem; border-radius: 6px; }.main { order: -1; } /* mobile: main content first, before the sidebar */@media (min-width: 900px) { .layout { flex-direction: row; } .sidebar { flex: 0 0 220px; } .main { order: 0; flex: 1; } /* desktop: natural order, side by side */}
On a phone the reader sees the main content immediately, with the sidebar below. On desktop the sidebar returns to its place on the left. Prioritising content for the small screen is one of the quieter benefits of working mobile-first.
10. A complete mobile-first page
This final example combines the patterns into one small page: the viewport tag, a fluid container, a responsive nav, scaling type, and a grid that grows. It is a realistic skeleton you can build on.
<html lang="en"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"></head><body> <header class="bar"> <span class="brand">datalad</span> <nav class="nav"> <a href="#">Home</a> <a href="#">Articles</a> <a href="#">Shop</a> </nav> </header> <main class="container"> <h1 class="title">Mobile-first, all the way up</h1> <div class="grid"> <div class="card">One</div> <div class="card">Two</div> <div class="card">Three</div> </div> </main></body></html>
* { box-sizing: border-box; }body { margin: 0; font-family: sans-serif; }/* Header: stacked on mobile, row on larger screens */.bar { display: flex; flex-direction: column; gap: 0.5rem; padding: 1rem; background: #11243a;}.brand { color: #fff; font-weight: 700; }.nav { display: flex; flex-direction: column; gap: 0.5rem; }.nav a { color: #cfe0f1; text-decoration: none; }/* Container: fluid then capped */.container { width: 100%; padding: 1rem; margin: 0 auto; }/* Type and grid: mobile defaults */.title { font-size: 1.5rem; }.grid { display: grid; grid-template-columns: 1fr; gap: 1rem; }.card { background: #f0f4f8; padding: 1.5rem; border-radius: 6px; }@media (min-width: 768px) { .bar { flex-direction: row; justify-content: space-between; align-items: center; } .nav { flex-direction: row; gap: 1.5rem; } .container { max-width: 720px; } .title { font-size: 2rem; } .grid { grid-template-columns: repeat(2, 1fr); }}@media (min-width: 1024px) { .container { max-width: 960px; } .title { font-size: 2.5rem; } .grid { grid-template-columns: repeat(3, 1fr); }}
Read the stylesheet from top to bottom and you read the screen sizes from small to large: every base rule is the mobile experience, and each media query adds the next tier. That single direction, building up rather than tearing down, is the whole point of mobile-first, and it gives you a lean, fast foundation with a CSS file that stays easy to follow.
Work through these and you will have the complete mobile-first toolkit: the base-plus-enhancement pattern, the viewport tag that makes it work, fluid containers and grids, responsive navigation and type, relative units, the min-width advantage, and content prioritisation. The guide’s closing advice is worth repeating: test on real devices, not just a resized browser window, because phones and tablets surface things an emulator will miss.
See you soon.
[…] Mobile-First Design: 10 Code-Along Examples […]
[…] Mobile-First Design: 10 Code-Along Examples […]