Wanneer we eenvoudige of complexe lay-outs bouwen met behulp van CSS Grid, plaatsen we items meestal met regelnummers. Rasterlay-outs bevatten rasterlijnen die automatisch worden geïndexeerd met positieve en negatieve regelnummers (tenzij we noem ze expliciet). Items met regelnummers positioneren is een prima manier om dingen op een rijtje te zetten, hoewel CSS Grid talloze manieren heeft om hetzelfde te bereiken met een ondermaatse cognitieve last. Een van die manieren is iets wat ik graag beschouw als de "ASCII"-methode.
De ASCII-methode in een notendop
De methode komt neer op het gebruik van grid-template-areas
om rasteritems te positioneren met behulp van aangepaste benoemde gebieden op het niveau van de rastercontainer in plaats van regelnummers.
Wanneer we een element declareren als een rastercontainer met display: grid
, genereert de rastercontainer standaard een spoor met één kolom en rijen die de rasteritems voldoende bevatten. De onderliggende elementen van de container die deelnemen aan de rasterlay-out worden geconverteerd naar rasteritems, ongeacht hun display
eigendom.
Laten we bijvoorbeeld een raster maken door kolommen en rijen expliciet te definiëren met behulp van de grid-template-columns
en grid-template-rows
eigenschappen.
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: repeat(3, 200px);
}
Dit kleine CSS-fragment maakt een raster van 3 × 2 waarin de rasteritems evenveel ruimte innemen in de kolommen, en waar het raster drie rijen bevat met een spoorgrootte van 200px
.
We kunnen de volledige lay-out definiëren met benoemde rastergebieden met de grid-template-areas
eigendom. Volgens de spec, de beginwaarde van grid-template-areas
is none
.
grid-template-areas = none | +
+
is een lijst van de groep strings tussen een aanhalingsteken. Elke tekenreeks wordt weergegeven als een cel en elke tekenreeks tussen aanhalingstekens wordt weergegeven als een rij. Soortgelijk:
grid-template-areas: "head head" "nav main" "foot foot";
De waarde van grid-template-areas
beschrijft de lay-out als vier rastergebieden. Zij zijn,
head
nav
main
foot
head
en foot
overspannen twee kolomsporen en één rijspoor. De resterende nav
en main
elk omvat één kolomspoor en één rijspoor. De waarde van grid-template-areas
lijkt veel op het rangschikken van ASCII-tekens, en als Chris stelde voor: een tijdje terug kunnen we een visualisatie van de algehele structuur van de lay-out krijgen van de CSS zelf, wat de meest probleemloze manier is om het te begrijpen.
OK, dus we hebben onze lay-out gemaakt met vier benoemde rastergebieden: head
, nav
, main
, foot
.
Laten we nu beginnen met het plaatsen van de rasteritems tegen benoemde rastergebieden in plaats van regelnummers. Laten we in het bijzonder een header
element in het benoemde rastergebied head
en specificeer het benoemde rastergebied head
in de header
element met behulp van de grid-area
eigendom.
Benoemde rastergebieden in een rasterlay-out heten identiteiten. Dus wat we net deden, was een aangepaste ident maken met de naam head
die we kunnen gebruiken om items in bepaalde rastersporen te plaatsen.
header { grid-area: head; }
We kunnen andere HTML-elementen gebruiken met andere aangepaste idents:
nav { grid-area: nav; }
main { grid-area: main; }
footer { grid-area: foot; }
Benoemde gebiedswaarden schrijven
Think CSS-rasterlay-outmodule niveau 1, moeten alle tekenreeksen worden gedefinieerd onder de volgende tokens:
- Genoemd celtoken: Dit vertegenwoordigt het genoemde rastergebied in het raster. Bijvoorbeeld,
head
is een benoemde celtoken. - Null-cel-token: Dit vertegenwoordigt het naamloze rastergebied in de rastercontainer. Een lege cel in het raster is bijvoorbeeld een nulceltoken.
- Prullenbak token: Dit is een syntaxisfout, zoals een ongeldige declaratie. Een ongelijksoortig aantal cellen en rijen vergeleken met het aantal rasteritems zou bijvoorbeeld een aangifte ongeldig maken.
In grid-template-area
, moet elke string tussen aanhalingstekens (de rijen) hetzelfde aantal cellen hebben en het volledige raster definiëren zonder een cel te negeren.
We kunnen een cel negeren of laten staan als een lege cel met behulp van de punt (.
)
.grid {
display: grid;
grid-template-areas:
"head head"
"nav main"
"foot .";
}
Als u dat visueel onhandig of onevenwichtig vindt, kunnen we meerdere punttekens gebruiken zonder spaties die ze scheiden:
.grid {
display: grid;
grid-template-areas:
"head head"
"nav main"
"foot ....";
}
Een benoemd celtoken kan meerdere rastercellen omvatten, maar die cellen moeten een rechthoekige lay-out vormen. Met andere woorden, we kunnen geen "L"- of "T"-vormige lay-outs maken, hoewel de specificatie dat wel doet hint naar ondersteuning voor niet-rechthoekige lay-outs met niet-verbonden regio's in de toekomst.
ASCII is beter dan lijngebaseerde plaatsing
Op lijn gebaseerde plaatsing is waar we de . gebruiken grid-column
en grid-row
eigenschappen om een element op het raster te positioneren met behulp van rasterlijnnummers die automatisch worden geïndexeerd door een nummer:
.grid-item {
grid-column: 1 / 3; /* start at grid column line 1 and span to line 3 */
}
Maar de regelnummers van rasteritems kunnen veranderen als onze lay-out op een breekpunt verandert. In die gevallen is het niet zo dat we kunnen vertrouwen op dezelfde regelnummers die we op een specifiek breekpunt hebben gebruikt. Dit is waar het extra cognitieve last vereist om de code te begrijpen.
Daarom denk ik dat een op ASCII gebaseerde aanpak het beste werkt. We kunnen de lay-out voor elk breekpunt opnieuw definiëren met behulp van grid-template-areas
binnen de rastercontainer, die een handig beeld biedt van hoe de lay-out er direct in de CSS uit zal zien - het is als zelfgedocumenteerde code!
.grid {
grid-template-areas:
"head head"
"nav main"
"foot ...."; /* much easier way to see the grid! */
}
.grid-item {
grid-area: foot; /* much easier to place the item! */
}
We kunnen de regelnummers en rastergebieden van een raster in DevTools zien. Ga in Firefox bijvoorbeeld naar het paneel Lay-out. Dan, onder de Raster tabblad, zoek de "Instellingen rasterweergave" en schakel de “Regelnummer weergeven” en “Weergave gebiedsnamen” opties.
Deze ASCII-aanpak met benoemde gebieden vereist veel minder inspanning om de plaatsing van elementen te visualiseren en gemakkelijk te vinden.
Laten we eens kijken naar de "universele" use case
Telkens wanneer ik een tutorial over benoemde rastergebieden zie, is het algemene voorbeeld over het algemeen een lay-outpatroon met: header
, main
, sidebar
en footer
gebieden. Ik beschouw dit graag als de "universele" use-case, omdat het zo'n breed net werpt.
Het is een geweldig voorbeeld om te illustreren hoe grid-template-areas
werkt, maar een real-life implementatie omvat meestal mediaquery's die zijn ingesteld om de lay-out bij bepaalde viewport-breedten te wijzigen. In plaats van opnieuw te moeten declareren grid-area
op elk rasteritem bij elk breekpunt om alles opnieuw te positioneren, kunnen we gebruiken grid-template-areas
om in plaats daarvan te "reageren" op het breekpunt - en een mooi beeld te krijgen van de lay-out op elk breekpunt in het proces!
Laten we, voordat we de lay-out definiëren, een ident toewijzen aan elk element met behulp van de grid-area
eigenschap als basisstijl.
header {
grid-area: head;
}
.left-side {
grid-area: left;
}
main {
grid-area: main;
}
.right-side {
grid-area: right;
}
footer {
grid-area: foot;
}
Laten we nu de lay-out opnieuw definiëren als een basisstijl. We gaan voor een mobile-first-aanpak, zodat dingen standaard worden gestapeld:
.grid-container {
display: grid;
grid-template-areas:
"head"
"left"
"main"
"right"
"foot";
}
Elk rasteritem is automatisch formaat in deze configuratie — die een beetje raar lijkt — zodat we kunnen instellen min-height: 100vh
op de rastercontainer om ons meer ruimte te geven om mee te werken:
.grid-container {
display: grid;
grid-template-areas:
"head"
"left"
"main"
"right"
"foot";
min-height: 100vh;
}
Laten we nu zeggen dat we de main
element om rechts van de gestapelde te zitten left
en right
zijbalken als we bij een iets bredere viewport-breedte komen. We verklaren opnieuw: grid-template-areas
met een bijgewerkte ASCII-lay-out om dat te krijgen:
@media (min-width: 800px) {
.parent {
grid-template-columns: 0.5fr 1fr;
grid-template-rows: 100px 1fr 1fr 100px;
grid-template-areas:
"head head"
"left main"
"right main"
"foot foot";
}
}
Ik gooide er wat kolom- en rij-afmetingen in, puur voor esthetiek.
Naarmate de browser nog breder wordt, willen we misschien de lay-out opnieuw wijzigen, zodat main
zit ingeklemd tussen de left
en right
zijbalken. Laten we de lay-out visueel schrijven!
.grid-container {
grid-template-columns: 200px 1fr 200px; /* again, just for sizing */
grid-template-areas:
"head head head"
"left main right"
"left main right"
"foot foot foot";
}
Gebruikmaken van impliciete regelnamen voor flexibiliteit
Volgens de specificaties, grid-template-areas
genereert automatisch namen voor de rasterlijnen die zijn gemaakt door benoemde rastergebieden. We noemen deze impliciet genoemde rasterlijnen omdat ze gratis naar ons worden genoemd zonder extra werk.
Elk benoemd rastergebied krijgt vier impliciet benoemde rasterlijnen, twee in de kolomrichting en twee in de rijrichting, waarbij -start
en -end
worden toegevoegd aan de ident. Bijvoorbeeld een rastergebied met de naam head
krijgt head-start
en head-end
lijnen in beide richtingen voor een totaal van vier impliciet genoemde rasterlijnen.
We kunnen deze lijnen in ons voordeel gebruiken! Als we bijvoorbeeld willen dat een element de main
, left
en right
gebieden van ons netwerk. Eerder hebben we het gehad over hoe lay-outs rechthoekig moeten zijn - geen "T" en "L" -vormige lay-outs toegestaan. Daarom kunnen we de visuele indelingsmethode ASCII niet gebruiken om de overlay te plaatsen. We kunnen echter onze impliciete regelnamen gebruiken met dezelfde grid-area
eigenschap op de overlay die we gebruiken om de andere elementen te positioneren.
Wist je dat grid-area
is een steno-eigenschap, ongeveer op dezelfde manier dat margin
en padding
zijn steno-eigenschappen? Het heeft meerdere waarden op dezelfde manier nodig, maar in plaats van een "met de klok mee" richting te volgen, zoals, margin
- wat in volgorde van gaat margin-block-start
, margin-inline-end
, margin-block-end
en margin-inline-start
- grid-area
gaat zoals dit:
grid-area: block-start / inline-start / block-end / inline-end;
Maar we hebben het over rijen en kolommen, niet over blok- en inline-richtingen, toch? Nou, ze komen overeen met elkaar. De rij-as komt overeen met de blokrichting en de kolomas komt overeen met de inline-richting:
grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;
Terug naar het positioneren van dat overlay-element als een rasteritem in onze lay-out. De grid-area
eigenschap zal handig zijn om het element te positioneren met behulp van onze impliciet genoemde rasterlijnen:
.overlay {
grid-area: left-start / left-start / right-end / main-end;
}
Een minimaal rastersysteem creëren
Wanneer we ons concentreren op lay-outs zoals de "universele" use case die we zojuist hebben gezien, is het verleidelijk om rastergebieden te zien in termen van één gebied per element. Maar zo hoeft het niet te werken. We kunnen idents herhalen om er meer ruimte voor te reserveren in de layout. Dat zagen we toen we de head
en foot
idents in het laatste voorbeeld:
.grid-container {
grid-template-areas:
"head head head"
"left main right"
"left main right"
"foot foot foot";
}
Let erop dat main
, left
en right
worden ook herhaald, maar in de richting van het blok.
Laten we de lay-outs van volledige pagina's vergeten en benoemde rastergebieden op een component gebruiken. Raster is net zo goed voor componentlay-outs als volledige pagina's!
Hier is een vrij standaard heldencomponent met een rij afbeeldingen gevolgd door verschillende tekstblokken:
De HTML is vrij eenvoudig:
We zouden dit kunnen doen voor een echt snel gestapelde lay-out:
.hero {
grid-template-areas:
"image"
"text";
}
Maar dan moeten we er wat uithalen padding
, max-width
of wat dan ook om het tekstgebied smaller te maken dan de rij afbeeldingen. Wat dacht je ervan om onze ASCII-lay-out uit te breiden tot een raster met vier kolommen in plaats daarvan door onze idents op beide rijen te herhalen:
.hero {
display: grid;
grid-template-columns: repeat(4, 1fr); /* maintain equal sizing */
grid-template-areas:
"image image image image"
"text text text text";
}
Oké, nu kunnen we onze rasteritems in die benoemde gebieden plaatsen:
.hero .image {
grid-area: image;
}
.hero .text {
grid-area: text;
}
Tot nu toe, zo goed - beide rijen nemen de volledige breedte in beslag. We kunnen dat gebruiken als onze basislay-out voor kleine schermen.
Maar misschien willen we de smallere tekst introduceren wanneer de viewport een grotere breedte bereikt. We kunnen wat we weten over het punt-teken gebruiken om kolommen over te slaan. Laten we de text
ident slaat in dit geval de eerste en laatste kolom over.
@media (min-width: 800px) {
main {
grid-template-columns: repeat(6, 1fr); /* increase to six columns */
grid-template-areas:
"image image image image image image"
"..... text text text text .....";
}
}
Nu hebben we de gewenste afstand:
Als de lay-out extra moet worden aangepast op nog grotere breekpunten, kunnen we meer kolommen toevoegen en van daaruit verder gaan:
.hero {
grid-template-columns: repeat(8, 1fr);
grid-template-areas:
"image image image image image image image image"
"..... text text text text text text .....";
}
Visualisatie van dev-tool:
Weet je nog dat lay-outs met 12 kolommen en 16 kolommen de grote dingen waren in CSS-frameworks? We kunnen daar snel naar opschalen en een mooie visuele ASCII-lay-out in de code behouden:
main {
grid-template-columns: repeat(12, 1fr);
grid-template-areas:
"image image image image image image image image image image image image"
"..... text text text text text text text text text text .....";
}
Laten we naar iets complexers kijken
We hebben gekeken naar een vrij algemeen voorbeeld en een relatief eenvoudig voorbeeld. We kunnen nog steeds mooie ASCII-lay-outvisualisaties krijgen met complexere lay-outs.
Laten we hier naartoe werken:
Ik heb dit opgesplitst in twee elementen in de HTML, a header
en main
:
...
...
...
...
...
Ik denk dat flexbox meer geschikt is voor de header
omdat we de onderliggende elementen op die manier gemakkelijk kunnen uit elkaar plaatsen. Dus nee grid
er:
header {
display: flex;
justify-content: space-between;
/* etc. */
}
Maar grid
is zeer geschikt voor de main
lay-out van het element. Laten we de lay-out definiëren en de idents toewijzen aan de corresponderende elementen die we nodig hebben om de . te positioneren .text
en drie .image
elementen. We beginnen met dit als onze basislijn voor kleine schermen:
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
"image1 image1 ..... image2"
"texts texts texts texts"
"..... image3 image3 .....";
}
Je kunt al zien waar we hiermee naartoe gaan, toch? De lay-out wordt voor ons gevisualiseerd en we kunnen de rasteritems op hun plaats laten vallen met de aangepaste idents:
.image:nth-child(1) {
grid-area: image1;
}
.image:nth-last-child(2) {
grid-area: image2;
}
.image:nth-last-child(1) {
grid-area: image3;
}
h2 {
grid-area: texts;
}
Dat is onze basislay-out, dus laten we ons wagen aan een breder breekpunt:
@media (min-width: 800px) {
.grid {
grid-template-columns: repeat(8, 1fr);
grid-template-areas:
". image1 image1 ...... ...... ...... image2 ."
". texts texts texts texts texts image2 ."
". ..... image3 image3 image3 image3 ...... .";
}
}
Ik wed dat je precies weet hoe dat eruit zal zien, want de lay-out staat precies in de code!
Dezelfde deal als we besluiten nog verder op te schalen:
.grid {
grid-template-columns: repeat(12, 1fr);
grid-template-areas:
". image1 image1 ..... ..... ..... ..... ..... ..... ..... ..... ."
". texts texts texts texts texts texts texts texts texts image2 ."
". ..... image3 image3 image3 image3 ..... ..... ..... ..... ..... .";
}
Hier is de volledige demo:
Ik gebruik de "negatieve" margin
hack" om ervoor te zorgen dat de eerste afbeelding de kop overlapt.
Afsluiten
Ik ben benieuwd of iemand anders het gebruikt grid-template-areas
om benoemde gebieden te maken met het voordeel van een ASCII-visual van de rasterlay-out. Het hebben van dat als referentie in mijn CSS-code heeft geholpen bij het demystificeren van een aantal anders complexe ontwerpen die misschien nog complexer waren bij het omgaan met regelnummers.
Maar als er niets anders is, leert het definiëren van rasterlay-outs op deze manier ons een aantal interessante dingen over CSS Grid die we in dit bericht hebben gezien:
- De
grid-template-areas
eigenschap stelt ons in staat om aangepaste idents - of "benoemde gebieden" - te maken en deze te gebruiken om rasteritems te positioneren met behulp van degrid-area
eigendom. - Er zijn drie soorten "tokens" die:
grid-template-areas
accepteert als waarden, inclusief benoemde celtokens, null-celtokens en prullenbakceltokens. - Elke rij die is gedefinieerd in
grid-template-areas
hetzelfde aantal cellen nodig. Het negeren van een enkele cel creëert geen lay-out; het wordt beschouwd als een prullenbak. - We kunnen een visueel ASCII-achtig diagram van de rasterlay-out krijgen in de
grid-template-areas
eigenschapswaarde door de vereiste witruimten tussen benoemde celtokens te gebruiken bij het definiëren van de rasterlay-out. - Zorg ervoor dat er geen witruimte is in een null-celtoken (bijv
.....
). Anders creëert een enkele witruimte tussen null-celtokens onnodige lege cellen, wat resulteert in een ongeldige lay-out. - We kunnen de lay-out op verschillende breekpunten opnieuw definiëren door de rasteritems opnieuw te positioneren met
grid-area
, en vervolgens de lay-out opnieuw declareren metgrid-template-areas
op de rastercontainer om de tracklist indien nodig bij te werken. Het is niet nodig om de rasteritems aan te raken. - Aangepaste benoemde rastergebieden krijgen automatisch vier impliciet toegewezen lijnnamen —
-start
en-end
in zowel de kolom- als de rijrichting.