10/12/2021
CSS Grid: Enkelhed og Kraft til Moderne Webdesign
CSS Grid har revolutioneret den måde, vi tænker og bygger layouts til internettet. Det har ikke kun ført til mere robust kode ved at erstatte tidligere 'hacks', men har i nogle tilfælde elimineret behovet for at stole på specifikke løsninger for forskellige skærmstørrelser og viewports. Det fantastiske ved denne æra inden for webudvikling er, at vi kan opnå mere med færre kodelinjer. I denne artikel vil vi dykke ned i CSS Grids kraft ved at opbygge et par almindelige responsive navigationslayouts. Det er nemmere, end du måske tror, og da CSS Grid er bygget med responsivitet i tankerne, kræver det mindre kode end at skrive media queries overalt.

Layout 1: Hero Content og Liste af Artikler
Vi starter med et almindeligt website-layout: En fuld-bredde hero-sektion med et gitter af kort nedenunder. Begge elementer vil reagere på vinduesresizing og tilpasse sig automatisk. Selvom dette måske ser ud som meget kode ved første øjekast, er den responsive adfærd opnået med kun seks linjer CSS Grid-kode, og uden en eneste @media-regel. Lad os nedbryde koden for at se, hvad der sker.
Hero Sektionen
Lad os se på koden for .hero elementet:
<section class="hero"> <h1>You thirsty?</h1> <article> <p>Explore local breweries with just one click and stirred by starlight across the centuries light years great turbulent clouds circumnavigated paroxysm of global death.</p> <a href="#breweries">Browse Breweries</a> </article> </section> .hero { /* Photo by mnm.all on Unsplash */ background: url('https://images.unsplash.com/photo-1518176258769-f227c798150e') center; background-size: cover; padding: 4rem 2rem; /* Grid styles */ display: grid; align-items: center; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); } Vi har en række baggrundsstil, der muliggør øl-baggrunden, lidt polstring for at adskille indholdet fra skærmens kant, og derefter tre linjer med grid-stilarter:
- Den første linje (
display: grid;) ændrer.heroelementets adfærd til at være en grid-container. Det betyder, at elementerne inde i.heronu er grid-emner. - Den anden linje (
align-items: center;) centrerer lodret kolonnerne i vores grid. - Disse to linjer gør dog intet alene, før vi definerer kolonnerne i vores grid. Og det er her, den tredje linje kommer ind. Der sker meget i denne ene egenskab, så lad os tage det trin for trin.
repeat() Funktionen
Generelt definerer vi normalt kolonner og rækker i CSS Grid ved at tilføje værdien for hver 'track' efter at have defineret egenskaben, således:
.element { /* Dette vil resultere i fire kolonner, hver på 1fr */ grid-template-columns: 1fr 1fr 1fr 1fr; /* Dette vil resultere i to rækker, hver på 300px */ grid-template-rows: 300px 300px; } Det er ret kedeligt. Vi kan bruge repeat() funktionen til at gøre det mindre ordrigt og lettere at følge. Funktionen tager to parametre:
- Antallet af gange værdien skal gentages.
- Selve værdien.
Efter at have refaktoreret vores kode til at bruge repeat(), bør vi forvente de samme resultater fra disse kodelinjer:
.element { /* dette er det samme som grid-template-columns: 1fr 1fr 1fr 1fr; */ grid-template-columns: repeat(4, 1fr); /* dette er det samme som grid-template-rows: 300px 300px; */ grid-template-rows: repeat(2, 300px); } Meget renere, ikke?
minmax() Funktionen
Ovenstående eksempler definerer eksplicit størrelser for 'tracks' (1fr og 300px). Det kan fungere i nogle scenarier, men for vores øl-eksempel her har vi brug for at kunne beregne 'track'ens størrelse automatisk baseret på viewportens bredde og automatisk justere antallet af viste kolonner. For at kunne gøre dette definerer vi et interval af værdier ved hjælp af minmax() funktionen. Hvad definerer vi? Du har sandsynligvis allerede gættet: Den *minimale* og *maksimale* værdi, vi ønsker, disse kolonner skal kunne skaleres til.
I hero-sektionen for vores øl-eksempel ovenfor satte vi vores minmax() egenskab til at være 240px som minimumsstørrelse og 1fr som maksimum. fr-enheder, hvis du aldrig har hørt om dem, står for 'fractional units' (brøkdele af en enhed). Ingen kan forklare dem bedre end Jen Simmons i denne video og Robin Rendle i dette indlæg.
Dette resulterer i, at vores 'tracks' er 1fr, når der er masser af plads i vores viewport (kendt som desktop-opløsninger), og 240px, når der ikke er nok plads til begge kolonner (som på mobile enheder). Derfor vokser de pænt, når vi gør vores browser bredere, da de tager den resterende plads og ligeligt fordeler den på de eksisterende kolonner. Nu, lad os gå til det sidste puslespil!
auto-fit Nøgleordet
auto-fit nøgleordet giver os mulighed for at ombryde vores kolonner i rækker, når der ikke er nok plads i vores viewport til at passe minimumsværdien på 240px uden at indholdet flyder over. Sara Soueidan skrev en fremragende artikel om automatisk skalering af kolonner ved hjælp af auto-fill og auto-fit nøgleordene, hvis du vil dykke dybere ned i, hvad der sker under motorhjelmen. Nu, med den sidste kode på plads, bør vi kunne opnå dette resultat:
Kolonnen ombrydes automatisk, når der ikke er nok plads i viewporten.
Artikel Listen
Nu hvor vi grundigt har gennemgået adfærden af elementerne i vores hero-sektion, vil de første to linjer CSS-kode for øl-listen nedenunder sandsynligvis allerede virke bekendte for dig:
.breweries > ul { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); grid-gap: 1rem; } Det er rigtigt! Vi bruger den nøjagtig samme tilgang: På første linje definerer vi vores grid, på anden linje skalerer vi vores 'tracks' ved hjælp af den samme magiske one-liner, og på tredje linje sætter vi en afstand mellem disse kolonner. Intet nyt under solen, og det virkelig smarte ved dette er, at vores kode er robust nok til at justere antallet af 'tracks' og deres størrelser i henhold til antallet af elementer, vi har inde i vores uordnede liste.
Gitteret reagerer på ændringen i antallet af 'tracks' og tilpasser layoutet.
Det var alt! Et fuldt responsivt website-layout, der kun bruger seks linjer CSS-kode. Ikke dårligt, vel? Sørg for at tjekke kildekoden og lege med dette eksempel på CodePen.
Layout 2: Fuld-bredde Billedgalleri
I dette næste eksempel vil vi udnytte kraften i vores nyindlærte kombination af repeat(), auto-fit og minmax() til at skabe dette responsive billedgalleri. Vi vil også skalere vores 'tracks' ved hjælp af grid-column og grid-row, og lære om den praktiske egenskab/værdi-kombination af grid-auto-flow: dense;, som giver os mulighed for at ændre standardadfærden for elementer, der ikke passer ind i vores eksplicitte 'tracks': I stedet for at ombryde sig i nye rækker eller kolonner, får vi dem til at passe ind i de ubrugte pladser i vores grid. Lad os komme i gang med kodningen!
Grid Opsætning
Gitteret er oprettet ved hjælp af vores velkendte display: grid; egenskab, hvor kolonner defineres ved hjælp af repeat(), auto-fit og minmax(). Vi har også tilføjet en række rækker med en repeat() funktion og defineret en afstand til vores billeder ved hjælp af grid-gap. Men den nye spiller her er grid-auto-flow: dense;. Vi kommer til den om et øjeblik.
.gallery > .gallery__list { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); grid-template-rows: repeat(6, 200px); grid-gap: 1rem; grid-auto-flow: dense; } /* Dette vil skabe 2x billeder for hver 4. element */ .gallery > .gallery__list > li:nth-child(4n) { grid-column: span 2; /* Fylder to kolonner */ grid-row: span 2; /* Fylder to rækker */ } /* Dette vil skabe 3x billeder for hver 8. element */ .gallery > .gallery__list > li:nth-child(8n) { grid-column: span 3; /* Fylder tre kolonner */ grid-row: span 3; /* Fylder tre rækker */ } .gallery > .gallery__list > li > figure > img { width: 100%; height: 100%; object-fit: cover; } Vi har også skabt et gentagelsesmønster ved hjælp af nth-child() pseudo-selektoren til at sætte forskellige størrelser for vores 'tracks' ved hjælp af grid-column og grid-row. Bemærk her, at vi bruger span nøgleordet til at lade det valgte element optage mere end én kolonne eller række.
Endelig sikrer vi, at vores billeder dækker hele området af deres container, uanset om de er 1x, 2x eller 3x, ved hjælp af object-fit: cover;. Hvis du aldrig har hørt om object-fit, fungerer det ret ligesom background-image, men med HTML <img> tags.
grid-auto-flow: dense;
Det virkelige scoop her er grid-auto-flow: dense;. Se hvad der sker, når vi fjerner det fra vores kode:
Fjernelse af grid-auto-flow: dense; fører til inkonsistent placering af elementerne i gitteret.
Ser du de huller i vores smukt udformede gitter? Det skyldes, at nogle af elementerne i det optager 2x eller 3x pladser, og når der ikke er nok plads i vores 'tracks' til at passe dem, vil de ombrydes i en ny række, da det er standardadfærden. Ved at ændre det fra row til dense fortæller vi gitteret, at det skal fylde eventuelle huller, vi måtte have, med elementer, der kan passe ind i dem, uanset deres kildeorden i DOM'en.
Derfor kan denne teknik være særligt nyttig til ting som billedgallerier, men er måske ikke egnet til andre brugsscenarier, hvor du måske har brug for at bevare rækkefølgen af markup. Leg gerne rundt med CodePen demoen for at se forskellene på, hvor elementerne placeres.
Layout 3: Trello-stil Kortlayout
Nu til den sidste demo, hvor vi udnytter muligheden for at indlejre grids for at genskabe dette Trello Board. Vi vil oprette et grid, der indeholder vores fire forskellige kolonner, og inden i dem vil vi oprette et underordnet grid til vores kort. Selvom dette eksempel ikke udforsker nye egenskaber eller revolutionerende metoder, hjælper det os med at forstå, hvor nemt det er at bygge komplekse layouts med få linjer CSS-kode. Denne demo har en masse ekstra kode til at opnå Trello-layoutets styling, så vi vil udelukkende fokusere på grid-stilarterne.
Kolonnerne
For at oprette de fire kolonner bruger vi display: grid; på containeren og bruger vores magiske one-liner til vores grid-template-columns. Vi definerer også en afstand mellem dem og bruger align-items: flex-start; for at sikre, at vores kolonner ikke strækker sig til bunden af skærmen.
.column__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); grid-gap: .5rem; align-items: flex-start; } /* Kommenter disse linjer ud, hvis du ønsker den standard Trello-adfærd i stedet for kolonne-ombrydning */ /* .column__list { grid-auto-flow: column; grid-auto-columns: minmax(260px, 1fr); } */ Nu er den originale Trello ikke responsiv som standard: Hvis du ændrer størrelsen på din browser på et Trello Board, vil du ende med en vandret scroll på dine kolonner i stedet for at ombryde dem i en ny række. Vi følger ikke denne adfærd her, da vi ønsker at bygge responsive layouts, men hvis du er nysgerrig og ønsker at efterligne Trello's funktionalitet, kan du opnå det ved at tilføje to ekstra linjer CSS-kode.
Vi lærte om grid-auto-flow i vores forrige demo og opdagede, at det giver os mulighed for at kontrollere, hvordan auto-placeringsalgoritmen fungerer, og hvordan implicitte elementer skal tilføjes i gitterets flow. Standardadfærden er row, hvilket betyder, at ethvert ekstra element, der ikke passer ind i vores grid, vil ombrydes til en ny linje. Vi ændrede det til dense i vores forrige demo, og vi vil ændre det til column i denne: På den måde vil enhver ny kolonne, der tilføjes her, ende i en implicit kolonne og have en vandret scroll. Vi definerer også en bredde for disse auto-genererede kolonner med grid-auto-columns egenskaben.
Ændring af grid-auto-flow egenskaben vil få denne demo til at opføre sig som den virkelige Trello.
Kortene
For kort-gitteret bruger vi en lignende tilgang. Vi bruger display: grid; på containeren. Vi definerer ingen kolonner her, da vi ikke ønsker nogen, og vi bruger grid-template-rows: auto; for at undgå, at alle kort får samme højde - vi ønsker, at nogle af dem skal være større og andre mindre, baseret på typen af indhold, der tilføjes til dem.
.card__list { display: grid; grid-template-rows: auto; grid-gap: .5rem; margin: .5rem 0; } Og igen, det var alt! To linjer mere til at sætte en afstand og en margin på kortene, og vi er færdige! Alt andet i Pen'en er standard CSS for at opnå Trello-looket og -følelsen.
Så er det slut... er media queries døde?
Før i tiden, da vi byggede layouts ved hjælp af display: inline-block; eller floats, gav media queries meget mening for at ændre størrelsen på vores elementer, efterhånden som viewporten blev mindre. Men nu, med de utroligt kraftfulde layouts, vi kan skabe med et par CSS-linjer, kan du føle dig fristet til at tro, at media queries er fortabt. Jeg er stærkt uenig i det: Jeg mener, at vi bør ændre den måde, vi tænker på dem, og derfor bruge dem anderledes.
Som Rachel Andrew udtalte for omkring et år siden, bør vi bruge media queries til at rette vores layout, når det går i stykker, i stedet for at målrette enheder: Der er så mange derude! Med fremkomsten af Media Queries Level 4 og 5 kan vi ikke kun registrere skærmstørrelser nu, men også pointer-typer. Som et resultat kan vi dykke ned i en brugers systempræferencer og tilpasse vores kode til dem, der foretrækker reduceret bevægelse, eller om vi skal bruge inverterede farver. Det betyder, at media queries ikke er døde; tværtimod vil jeg sige, at det er en spændende tid at bruge media queries, men vi skal lære at bruge dem rigtigt. I mellemtiden vil opbygning af robuste layouts ved hjælp af moderne teknikker som Flexbox eller CSS Grid spare dig en masse tid, kode og hovedpine.
Ofte Stillede Spørgsmål
Er CSS Grid svært at lære?
CSS Grid er generelt anset for at være ret intuitivt, især sammenlignet med ældre metoder til layout. Funktioner som repeat(), minmax() og auto-fit gør det muligt at skabe komplekse, responsive designs med relativt få kodelinjer.
Hvad er forskellen på auto-fit og auto-fill?
Begge nøgleord bruges med repeat() til at skabe et dynamisk antal kolonner. auto-fill vil fylde gitteret med så mange kolonner som muligt, selvom de er tomme. auto-fit vil derimod kun skabe det antal kolonner, der er nødvendigt for at fylde den tilgængelige plads, og vil derefter strække dem for at udfylde eventuelle tomme rum.
Kan jeg stadig bruge Media Queries med CSS Grid?
Absolut! Mens CSS Grid reducerer behovet for media queries til grundlæggende layoutjusteringer, er de stadig værdifulde til finjusteringer, tilpasning af typografi, ændring af farver eller tilpasning baseret på brugerpræferencer (som reduceret bevægelse). De supplerer hinanden snarere end at erstatte hinanden fuldstændigt.
Hvad er 'fr'-enheden?
fr står for 'fractional unit' (brøkdel af en enhed). Den bruges til at dele den tilgængelige plads i gitteret ligeligt mellem de elementer, der bruger fr-enheden. Hvis du har to kolonner, der begge bruger 1fr, vil de dele pladsen 50/50.
Hvornår skal jeg bruge grid-auto-flow: dense;?
grid-auto-flow: dense; er nyttigt, når du ønsker at minimere tomme pladser i dit grid ved at pakke elementer tættere sammen. Det er især effektivt til billedgallerier eller lignende visuelle layouts, hvor rækkefølgen af elementer ikke er kritisk. Vær forsigtig med at bruge det i layouts, hvor den semantiske rækkefølge af indhold er vigtig.
Sammenligning: CSS Grid vs. Ældre Metoder
| Funktion | CSS Grid | Floats/Inline-block |
|---|---|---|
| Layout Kompleksitet | Meget enkel, intuitiv | Kompliceret, kræver clearfix hacks |
| Responsivitet | Indbygget, nem at implementere | Kræver mange media queries |
| Kodelinjer | Færre, mere vedligeholdelsesvenlig | Flere, mere fejlbehæftet |
| Fleksibilitet | Høj, understøtter 2D-layouts | Begrænset, primært 1D |
| Browser Support | Moderne browsere (god support) | Bred support (ældre metoder fungerer også) |
Konklusionen er klar: CSS Grid tilbyder en markant forbedring i forhold til ældre metoder til web-layout. Det gør det nemmere, hurtigere og mere effektivt at skabe moderne, responsive websteder.
Hvis du vil læse andre artikler, der ligner CSS Grid: Enkelhed og Kraft, kan du besøge kategorien Teknologi.
