Media queries

När flexbox inte räcker

Sidebar-receptet från Tema 2 är elegant: det hanterar mobilvyn automatiskt med flex-wrap: wrap, utan en enda media query. Så vill vi helst bygga. En layout som löser sig själv är robustare än en med tre brytpunkter.

Men ibland går det inte. Vad händer när du vill att ett kortgrid ska gå från tre kolumner på desktop till en kolumn på mobil? Eller att en knapp ska dölja sig på smal skärm men visas på bred? Det kan flex-wrap inte avgöra.

Det kan media queries. En media query är ett villkor i CSS: om skärmen är minst X bred, aktivera de här reglerna. Det är en if-sats, fast i CSS. Lär dig den som det den är: verktyget för undantagen, inte förstahandsvalet.

Syntaxen

En media query skrivs med @media följt av villkoret, sedan ett CSS-block:

@media (min-width: 48rem) {
    .kortgrid {
        display: flex;
        gap: 1.5rem;
    }
}

Villkoret är i parentesen. CSS-reglerna är i klammerparenteserna. När villkoret är falskt ignoreras hela blocket, som om det inte existerade.

De två villkor du kommer att använda mest är spegelbilder av varandra. min-width är sant när skärmen är minst så bred, det är så du lägger till regler för större skärmar. max-width är sant upp till en bredd, det är så du begränsar regler till mindre skärmar.

Du kan skriva en media query för vilket element som helst, precis som vanlig CSS:

.card {
    width: 100%;
}

@media (min-width: 48rem) {
    .card {
        flex: 1;
    }
}

Standardregeln gäller alltid: kortet tar full bredd. Media queryn lägger till flex: 1 först när skärmen är minst 48rem bred, och då delar korten på raden.

Mobile-first kontra desktop-first

Det finns två sätt att tänka på responsiv CSS. Båda ger fungerande resultat, men i omvänd ordning.

Desktop-first, börja med det breda och begränsa på smalt:

.card {
    flex: 1;
}

@media (max-width: 48rem) {
    .card {
        width: 100%;
    }
}

Här är tre kolumner standard, och undantaget tvingar ner korten till en kolumn på smal skärm.

Mobile-first, börja med det smala och bygg ut på brett:

.card {
    width: 100%;
}

@media (min-width: 48rem) {
    .card {
        flex: 1;
    }
}

Här är en kolumn standard, och tillägget låter korten dela på raden först när det finns plats.

Uttrycket mobile first myntades av designern Luke Wroblewski i ett blogginlägg 2009, i samma veva som Ethan Marcottes artikel Responsive Web Design i A List Apart gav den responsiva webben sitt namn. Wroblewskis poäng var inte teknisk utan strategisk: när du börjar med den minsta skärmen tvingas du bestämma vad som är viktigast. Det som inte får plats på en mobilskärm är ofta sådant sidan aldrig behövde. Sedan bygger du ut när utrymmet växer, i stället för att i efterhand försöka trycka ihop en desktoplayout i en smal spalt.

Det är därför mobile-first är rätt approach, och det syns i koden: mobilstilen är din standard utan villkor, desktop är tillägget. Det ger nästan alltid enklare och renare CSS. Du lägger till komplexitet när du har mer utrymme, inte tvärtom.

Det är också anledningen till att hamburgermenyn i Tema 4 är skriven mobile-first: navigeringen är synlig som standard, och det är bara när JS är aktivt på smal skärm som den döljs.

Välj brytpunkter efter innehållet

En vanlig missuppfattning är att det finns “rätta” brytpunkter kopplade till specifika enheter, som 375px för iPhone och 768px för iPad. Det stämmer inte. Enheter förändras hela tiden och din layout ska fungera på alla skärmar.

Rätt fråga är: vid vilken bredd börjar min layout se dålig ut? Öppna DevTools, dra i handtaget och observera. När innehållet blir trångt eller konstigt, det är din brytpunkt.

Tre vanliga referenspunkter som utgångspunkt:

NamnBreddI rem
Smal mobil~480px~30rem
Bred mobil / liten tablet~768px~48rem
Desktop~1024px~64rem

Skriv brytpunkterna i rem. Ärligt talat är branschen inte enig här, du kommer att se px i många kodbaser, och skillnaden är mindre än den låter eftersom webbläsarens zoom påverkar båda likadant. Men det finns ett fall där valet märks: en användare som höjt webbläsarens textstorlek. Med brytpunkter i rem växer tröskeln med texten, så mobil-layouten med sina korta rader tar över tidigare. Med px står brytpunkten still, och användaren får en trång desktoplayout med stor text. Samma regel som i förra området alltså: mått som har med text och läsbarhet att göra skrivs relativt.

Media queries är inte det enda sättet att hantera responsivitet. Sidebar-receptet, flex-wrap och min-width på flex-items löser ofta problemet renare. Använd media queries när du behöver fundamentalt olika layouter, inte för varje liten justering.

Pröva i DevTools: Se media queries aktiveras live

  1. Öppna din sida och tryck F12.
  2. Klicka på mobilikonen (Toggle device toolbar) högst upp i DevTools-panelen.
  3. Ta tag i det grå handtaget i kanten av viewport och dra det långsamt.
  4. Öppna fliken Styles och titta på din CSS när bredden passerar en brytpunkt. Ser du hur @media-regeln tänds och de regler den skriver över stryks igenom?
  5. Högerklicka på ett element som påverkas av en media query och välj Inspektera. I Styles-panelen visas @media-regler indragna och märkta med den bredd de aktiveras vid.

Uppgift: Bygg ett responsivt kortgrid

  1. Skapa en HTML-sida med tre <article class="card"> inuti en <div class="card-grid">. Ge varje kort en rubrik och en kort textrad.
  2. Styla korten: vit bakgrund, padding: 1.5rem, en tunn border och en lätt box-shadow.
  3. Mobil som standard, ingen media query ännu. .card-grid ska inte ha någon flex-regel. Korten staplas naturligt i en kolumn.
  4. Lägg till en @media (min-width: 48rem)-regel. Inuti den: sätt display: flex och gap: 1.5rem.card-grid, och flex: 1.card.
  5. Testa i DevTools: dra handtaget och se brytpunkten. Var sker layoutbytet?
  6. Justera: dra handtaget tills kortens text börjar se trång ut. Är din brytpunkt på rätt ställe, eller behöver du flytta den?

Vad händer om…

Placera din @media-regel före den vanliga regeln i CSS-filen. CSS läses uppifrån och ned och den sista matchande regeln vinner. En @media-regel har ingen särskild prioritet, den är bara CSS med ett villkor. Byt ordning och testa på en bred skärm. Vad händer med layouten?

Motivera & reflektera

Skriv i din readme.md varför du valde just din brytpunkt. Utgick du från innehållet eller från en enhet, och hur märkte du att det var rätt ställe? Beskriv också varför mobile-first gav dig enklare CSS än om du börjat från desktop.

Nästa nivå

Media queries byter layout i hopp: allt är staplat, sedan plötsligt tre kolumner. Prova en teknik som skalar mjukt i stället, helt utan brytpunkter: sätt font-size: clamp(1rem, 0.5rem + 2vw, 1.5rem) på en rubrik och dra i DevTools-handtaget. Texten växer nu flytande mellan ett golv och ett tak. När räcker clamp() och flex-wrap för att slippa media queries helt, och när behöver du dem ändå? Att veta vilken teknik som passar vilket problem är det som skiljer en responsiv sida från en som bara har några brytpunkter.