Reference guide · html-css-js · Published 2026-08-15 · 3 min read
Responsive HTML: viewport, media queries and fluid grids
Responsive HTML basics: viewport meta, media queries by layout need, breakpoint choice and fluid flex and grid layouts.
- ·Viewport and media
- ·Pick breakpoints
- ·Fluid flex grid
The viewport meta tag comes first
The most common responsive bug is a page that renders at desktop width on a phone and forces sideways scrolling. The cause is the missing viewport tag: without it the browser assumes a fixed 980px canvas and zooms out.
<meta name="viewport" content="width=device-width, initial-scale=1">
width=device-width sizes the layout to the device, and initial-scale=1 maps one CSS pixel to one device pixel. The HTML head structure article explains where this tag sits and the surrounding head tags.
Media queries change style, not markup
A media query switches CSS at a width condition.
.card { display: grid; grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) {
.card { grid-template-columns: 1fr; }
}
The three parts: max-width or min-width, the breakpoint value, and the rules inside. Write min-width queries for a mobile-first direction, and keep a desktop stylesheet for the wide end, or use max-width for a desktop-first set of narrower overrides. Either works, so pick one per file and stay consistent.
Write queries around layout needs, not devices. There is no iPhone pixel perfect target; the query that fixes a "two cards squeeze at the same time" boundary is the correct breakpoint for that page. Common practical anchors are 480px for a single column, 768px for tablet, 1024px for desktop, but the copy length on your own content decides.
Fluid width layout
Structure the page so it does not need a query: fluid grids stretch instead of asking where the viewport is.
main, header, footer {
width: 100%;
max-width: 1120px;
margin-inline: auto;
}
.two-col { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
width: 100%; max-width: 1120px; margin-inline: auto centers a container at every width and never clips on tiny phones. repeat(auto-fit, minmax(260px, 1fr)) creates columns that collapse themselves at narrow widths, which removes a media query per component.
Images and type that scale
- Pictures:
max-width: 100%; height: auto;on every image keeps it in its column. - Text:
clamp(16px, 1rem + 0.5vw, 22px)sets a font size that scales within safe bounds instead of a line length that breaks. - List them per breakpoint if the columns and rows actually change: font size on its own does not need a breakpoint.
- Fluid images, the srcset and sizes attributes, are the responsive images article.
Breakpoint choice, practical
Three facts settle most breakpoint debates: test at 360, 768, 1024, and 1440. In DevTools, the easiest check is a drag on the width handle, and the "container" panel in the device toolbar shows each breakpoint boundary.
The golden rule: one query per layout change point, set breakpoints where the content actually runs out of room, not where the marketing deck says.
A media-query snippet to copy
/* Mobile first: base styles scale up */
body { font-size: 16px; }
@media (min-width: 768px) {
body { font-size: 17px; }
.posts { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 1024px) {
.site-header { position: sticky; top: 0; }
}
Verify
Resize the window and the DevTools width bar, check that the layout reflows, no horizontal scrollbar appears at 360px, no two-column break at the boundary, and the nav is not squashed. The horizontal scrollbar is the number one ticket: it hides outside the fold and shows a cut-off page at every narrow tab. Fix it by finding the fixed-width element; overflow-x: hidden is the band-aid, not the cause.
The responsive-html axis sits under LCP too, because the image pipeline and the head structure decide download order before media queries enter.