Ogni volta che costruiamo layout semplici o complessi utilizzando CSS Grid, di solito posizioniamo elementi con numeri di riga. I layout della griglia contengono linee della griglia che vengono automaticamente indicizzate con numeri di linea positivi e negativi (a meno che non ci sia nominarli esplicitamente). Posizionare gli elementi con i numeri di riga è un ottimo modo per disporre le cose, sebbene CSS Grid abbia numerosi modi per ottenere lo stesso risultato con un ingombro cognitivo sottodimensionato. Uno di questi modi è qualcosa che mi piace pensare come il metodo "ASCII".
Il metodo ASCII in breve
Il metodo si riduce all'utilizzo grid-template-areas
per posizionare gli elementi della griglia utilizzando aree con nome personalizzato a livello di contenitore della griglia anziché i numeri di riga.
Quando dichiariamo un elemento come contenitore della griglia utilizzando display: grid
, il contenitore della griglia, per impostazione predefinita, genera una traccia a colonna singola e righe che contengono sufficientemente gli elementi della griglia. Gli elementi figlio del contenitore che partecipano al layout della griglia vengono convertiti in elementi della griglia, indipendentemente dai loro display
proprietà.
Ad esempio, creiamo una griglia definendo in modo esplicito colonne e righe usando il grid-template-columns
ed grid-template-rows
proprietà.
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: repeat(3, 200px);
}
Questo piccolo frammento di CSS crea una griglia 3×2 in cui gli elementi della griglia occupano lo stesso spazio nelle colonne e dove la griglia contiene tre righe con una dimensione della traccia di 200px
.
Possiamo definire l'intero layout con aree della griglia denominate usando il grid-template-areas
proprietà. Secondo la spec, il valore iniziale di grid-template-areas
is none
.
grid-template-areas = none | <string>+
<string>+
sta elencando il gruppo di stringhe racchiuse tra virgolette. Ogni stringa è rappresentata come una cella e ogni stringa tra virgolette è rappresentata come una riga. Come questo:
grid-template-areas: "head head" "nav main" "foot foot";
Il valore di grid-template-areas
descrive il layout come avente quattro aree della griglia. Sono,
head
nav
main
foot
head
ed foot
si estende su due tracce di colonna e una traccia di riga. Il resto nav
ed main
ciascuna campata una traccia di colonna e una traccia di riga. Il valore di grid-template-areas
è molto simile a organizzare i caratteri ASCII e come ha suggerito Chris tempo fa, possiamo ottenere una visualizzazione della struttura complessiva del layout dal CSS stesso, che è il modo più semplice per capirlo.
OK, quindi abbiamo creato il nostro layout con quattro aree della griglia con nome: head
, nav
, main
, foot
.
Ora, iniziamo a posizionare gli elementi della griglia rispetto alle aree della griglia con nome anziché ai numeri di riga. Nello specifico, posizioniamo a header
elemento nell'area della griglia denominata head
e specificare l'area della griglia denominata head
nel header
elemento usando il grid-area
proprietà.
Vengono chiamate le aree della griglia con nome in un layout griglia identità. Quindi, quello che abbiamo appena fatto è stato creare un'identità personalizzata denominata head
che possiamo usare per posizionare gli oggetti in determinate tracce della griglia.
header { grid-area: head; }
Possiamo altri elementi HTML usando altri identificativi personalizzati:
nav { grid-area: nav; }
main { grid-area: main; }
footer { grid-area: foot; }
Scrittura dei valori dell'area denominata
Secondo Modulo layout griglia CSS Livello 1, tutte le stringhe devono essere definite con i seguenti token:
- Token della cella con nome: Questo rappresenta l'area della griglia denominata nella griglia. Per esempio,
head
è un token di cella denominato. - Token cella nullo: Ciò rappresenta l'area della griglia senza nome nel contenitore della griglia. Ad esempio, una cella vuota nella griglia è un token di cella nullo.
- Gettone cestino: Questo è un errore di sintassi, ad esempio una dichiarazione non valida. Ad esempio, un numero disparato di celle e righe rispetto al numero di elementi della griglia renderebbe una dichiarazione non valida.
In grid-template-area
, ogni stringa tra virgolette (le righe) deve avere lo stesso numero di celle e definire la griglia completa senza ignorare alcuna cella.
Possiamo ignorare una cella o lasciarla come an cella vuota usando il carattere di punto fermo (.
)
.grid {
display: grid;
grid-template-areas:
"head head"
"nav main"
"foot .";
}
Se ti sembra visivamente imbarazzante o sbilanciato, possiamo utilizzare più caratteri a punto fermo senza spazi bianchi che li separano:
.grid {
display: grid;
grid-template-areas:
"head head"
"nav main"
"foot ....";
}
Un token di cella con nome può estendersi su più celle della griglia, ma tali celle devono formare un layout rettangolare. In altre parole, non siamo in grado di creare layout a forma di "L" o "T", sebbene le specifiche lo facciano accenno al supporto per layout non rettangolari con regioni disconnesse in futuro.
ASCII è migliore del posizionamento basato su riga
Il posizionamento basato sulla linea è dove utilizziamo il grid-column
ed grid-row
proprietà per posizionare un elemento sulla griglia utilizzando i numeri di riga della griglia che vengono automaticamente indicizzati da un numero:
.grid-item {
grid-column: 1 / 3; /* start at grid column line 1 and span to line 3 */
}
Ma i numeri di riga degli elementi della griglia possono cambiare se il nostro layout cambia in un punto di interruzione. In questi casi, non è che possiamo fare affidamento sugli stessi numeri di riga che abbiamo utilizzato in uno specifico punto di interruzione. È qui che ci vuole un ingombro cognitivo aggiuntivo per comprendere il codice.
Ecco perché penso che un approccio basato su ASCII funzioni meglio. Possiamo ridefinire il layout per ogni punto di interruzione utilizzando grid-template-areas
all'interno del contenitore della griglia, che offre una comoda visuale su come apparirà il layout direttamente nel CSS: è come un codice autodocumentato!
.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! */
}
Possiamo effettivamente vedere i numeri di riga di una griglia e le aree della griglia in DevTools. In Firefox, ad esempio, vai al pannello Layout. Poi, sotto il Griglia scheda, individuare il “Impostazioni visualizzazione griglia” e abilitare il “Visualizza numero riga” ed “Visualizza nomi aree” opzioni.
Questo approccio ASCII che utilizza aree con nome richiede molto meno sforzo per visualizzare e trovare facilmente il posizionamento degli elementi.
Diamo un'occhiata al caso d'uso "universale".
Ogni volta che vedo un tutorial su aree della griglia con nome, l'esempio comune è generalmente un modello di layout contenente header
, main
, sidebar
e footer
le zone. Mi piace pensare a questo come al caso d'uso "universale" poiché lancia una rete così ampia.
È un ottimo esempio per illustrare come grid-template-areas
funziona, ma un'implementazione nella vita reale di solito prevede media query impostate per modificare il layout a determinate larghezze del viewport. Piuttosto che dover dichiarare nuovamente grid-area
su ogni elemento della griglia in ogni punto di interruzione per riposizionare tutto, possiamo usare grid-template-areas
per "rispondere" invece al punto di interruzione e ottenere una bella visuale del layout a ogni punto di interruzione nel processo!
Prima di definire il layout, assegniamo un ident a ciascun elemento utilizzando il grid-area
proprietà come stile di base.
header {
grid-area: head;
}
.left-side {
grid-area: left;
}
main {
grid-area: main;
}
.right-side {
grid-area: right;
}
footer {
grid-area: foot;
}
Ora definiamo nuovamente il layout come stile di base. Stiamo adottando un approccio mobile-first in modo che le cose si accumulino per impostazione predefinita:
.grid-container {
display: grid;
grid-template-areas:
"head"
"left"
"main"
"right"
"foot";
}
Ogni elemento della griglia è dimensioni automatiche in questa configurazione - che sembra un po' strana - così possiamo impostare min-height: 100vh
sul contenitore della griglia per darci più spazio con cui lavorare:
.grid-container {
display: grid;
grid-template-areas:
"head"
"left"
"main"
"right"
"foot";
min-height: 100vh;
}
Ora diciamo che vogliamo il main
elemento per sedersi a destra della pila left
ed right
barre laterali quando arriviamo a una larghezza del viewport leggermente più ampia. Ridichiariamo grid-template-areas
con un layout ASCII aggiornato per ottenere che:
@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";
}
}
Ho lanciato alcune colonne e dimensioni delle righe lì solo per l'estetica.
Man mano che il browser diventa ancora più ampio, potremmo voler cambiare di nuovo il layout, in modo che main
è inserito tra il left
ed right
barre laterali. Scriviamo il layout visivamente!
.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";
}
Utilizzo dei nomi di riga impliciti per maggiore flessibilità
Secondo le specifiche, grid-template-areas
genera automaticamente i nomi per le linee della griglia create dalle aree della griglia con nome. Chiamiamo queste linee della griglia con nome implicito perché sono nominate per noi gratuitamente senza alcun lavoro aggiuntivo.
Ogni area della griglia denominata ottiene quattro linee della griglia con nome implicito, due nella direzione della colonna e due nella direzione della riga, dove -start
ed -end
vengono aggiunti all'ident. Ad esempio, un'area della griglia denominata head
si head-start
ed head-end
linee in entrambe le direzioni per un totale di quattro linee della griglia con nome implicito.
Possiamo usare queste linee a nostro vantaggio! Ad esempio, se vogliamo che un elemento si sovrapponga a main
, left
e right
aree della nostra griglia. In precedenza, abbiamo parlato di come i layout devono essere rettangolari: non sono consentiti layout a forma di "T" e "L". Di conseguenza, non siamo in grado di utilizzare il metodo di layout visivo ASCII per posizionare l'overlay. Possiamo, tuttavia, usare i nostri nomi di riga impliciti usando lo stesso grid-area
proprietà sulla sovrapposizione che utilizziamo per posizionare gli altri elementi.
Lo sapevi grid-area
è una proprietà abbreviata, più o meno allo stesso modo margin
ed padding
sono proprietà abbreviate? Prende più valori allo stesso modo, ma invece di seguire una direzione "in senso orario" come, margin
— che va in ordine di margin-block-start
, margin-inline-end
, margin-block-end
e margin-inline-start
- grid-area
va così:
grid-area: block-start / inline-start / block-end / inline-end;
Ma stiamo parlando di righe e colonne, non di blocchi e direzioni inline, giusto? Ebbene, si corrispondono. L'asse delle righe corrisponde alla direzione del blocco e l'asse delle colonne corrisponde alla direzione inline:
grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;
Torniamo al posizionamento di quell'elemento sovrapposto come elemento della griglia nel nostro layout. Il grid-area
sarà utile per posizionare l'elemento usando le nostre linee della griglia con nome implicito:
.overlay {
grid-area: left-start / left-start / right-end / main-end;
}
Creazione di un sistema a griglia minimo
Quando ci concentriamo su layout come il caso d'uso "universale" che abbiamo appena visto, si è tentati di pensare alle aree della griglia in termini di un'area per elemento. Ma non deve funzionare così. Possiamo ripetere gli ident per riservare loro più spazio nel layout. Lo abbiamo visto quando abbiamo ripetuto il head
ed foot
idents nell'ultimo esempio:
.grid-container {
grid-template-areas:
"head head head"
"left main right"
"left main right"
"foot foot foot";
}
Notare che main
, left
e right
sono anche ripetuti ma nella direzione del blocco.
Dimentichiamoci dei layout a pagina intera e utilizziamo aree della griglia con nome su un componente. La griglia è altrettanto utile per i layout dei componenti quanto le pagine intere!
Ecco un componente eroe piuttosto standard che sfoggia una riga di immagini seguita da diversi blocchi di testo:
L'HTML è piuttosto semplice:
<div class="hero">
<div class="image">
<img src="..." alt="" />
</div>
<div class="text">
<!-- ... -->
</div>
</div>
Potremmo farlo per un layout impilato davvero veloce:
.hero {
grid-template-areas:
"image"
"text";
}
Ma poi dobbiamo raggiungerne alcuni padding
, max-width
o qualsiasi altra cosa per rendere l'area di testo più stretta della riga di immagini. Che ne dici di espandere il nostro layout ASCII in una griglia a quattro colonne invece ripetendo i nostri ident su entrambe le righe:
.hero {
display: grid;
grid-template-columns: repeat(4, 1fr); /* maintain equal sizing */
grid-template-areas:
"image image image image"
"text text text text";
}
Bene, ora possiamo posizionare i nostri elementi della griglia in quelle aree con nome:
.hero .image {
grid-area: image;
}
.hero .text {
grid-area: text;
}
Fin qui tutto bene: entrambe le file occupano l'intera larghezza. Possiamo usarlo come layout di base per piccoli schermi.
Ma forse vogliamo introdurre il testo più stretto quando la finestra raggiunge una larghezza maggiore. Possiamo usare ciò che sappiamo sul carattere del punto fermo per "saltare" le colonne. Diamo il text
ident salta la prima e l'ultima colonna in questo caso.
@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 .....";
}
}
Ora abbiamo la spaziatura che vogliamo:
Se il layout necessita di ulteriori modifiche a punti di interruzione ancora più grandi, possiamo aggiungere più colonne e procedere da lì:
.hero {
grid-template-columns: repeat(8, 1fr);
grid-template-areas:
"image image image image image image image image"
"..... text text text text text text .....";
}
Visualizzazione dello strumento di sviluppo:
Ricordi quando i layout a 12 e 16 colonne erano le cose più importanti nei framework CSS? Possiamo scalare rapidamente fino a questo e mantenere un bel layout ASCII visivo nel codice:
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 .....";
}
Diamo un'occhiata a qualcosa di più complesso
Abbiamo esaminato un esempio abbastanza generico e un esempio relativamente semplice. Possiamo ancora ottenere belle visualizzazioni di layout ASCII con layout più complessi.
Lavoriamo fino a questo:
Ho diviso questo in due elementi nell'HTML, a header
e main
:
<header>
<div class="logo"> ... </div>
<div class="menu"> ... </div>
</header>
<main>
<div class="image"> ... </div>
<h2> ... </h2>
<div class="image"> ... </div>
<div class="image"> ... </div>
</main>
Penso che flexbox sia più appropriato per il header
poiché possiamo distanziare facilmente i suoi elementi figlio in questo modo. Quindi, no grid
Là:
header {
display: flex;
justify-content: space-between;
/* etc. */
}
Ma grid
è adatto per il main
disposizione dell'elemento. Definiamo il layout e assegniamo gli ident agli elementi corrispondenti di cui abbiamo bisogno per posizionare il .text
e tre .image
elementi. Inizieremo con questo come linea di base per i piccoli schermi:
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
"image1 image1 ..... image2"
"texts texts texts texts"
"..... image3 image3 .....";
}
Puoi già vedere dove stiamo andando con questo, giusto? Il layout viene visualizzato per noi e possiamo posizionare gli elementi della griglia in posizione con gli ident personalizzati:
.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;
}
Questo è il nostro layout di base, quindi avventuriamoci in un punto di interruzione più ampio:
@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 ...... .";
}
}
Scommetto che sai esattamente come apparirà perché il layout è proprio lì nel codice!
Stesso affare se decidiamo di aumentare ulteriormente:
.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 ..... ..... ..... ..... ..... .";
}
Ecco la demo completa:
Sto usando il "negativo margin
hack” per far sì che la prima immagine si sovrapponga all'intestazione.
Concludendo
Sono curioso di sapere se qualcun altro sta usando grid-template-areas
per creare aree con nome a vantaggio di avere una visuale ASCII del layout della griglia. Avere questo come riferimento nel mio codice CSS ha aiutato a demistificare alcuni progetti altrimenti complessi che potrebbero essere stati ancora più complessi quando si trattava di numeri di riga.
Ma se non altro, definire i layout della griglia in questo modo ci insegna alcune cose interessanti su CSS Grid che abbiamo visto in questo post:
- Il
grid-template-areas
La proprietà ci consente di creare ident personalizzati - o "aree con nome" - e usarli per posizionare gli elementi della griglia utilizzando ilgrid-area
proprietà. - Ci sono tre tipi di "token" che
grid-template-areas
accetta come valori, inclusi i token delle celle con nome, i token delle celle null e i token delle celle del cestino. - Ogni riga definita in
grid-template-areas
ha bisogno dello stesso numero di celle. Ignorare una singola cella non crea un layout; è considerato un gettone spazzatura. - Possiamo ottenere un diagramma visivo simile a ASCII del layout della griglia nel file
grid-template-areas
valore della proprietà utilizzando gli spazi bianchi richiesti tra i token delle celle con nome durante la definizione del layout della griglia. - Assicurati che non ci siano spazi bianchi all'interno di un token di cella nullo (ad es
.....
). In caso contrario, un singolo spazio bianco tra i token di cella null crea celle vuote non necessarie, risultando in un layout non valido. - Possiamo ridefinire il layout in vari punti di interruzione riposizionando gli elementi della griglia utilizzando
grid-area
, quindi dichiarando nuovamente il layout congrid-template-areas
sul contenitore della griglia per aggiornare l'elenco delle tracce, se necessario. Non è necessario toccare gli elementi della griglia. - Le aree della griglia con nome personalizzato ottengono automaticamente quattro nomi di riga assegnati in modo implicito —
<custom-ident>-start
ed<custom-ident>-end
in entrambe le direzioni della colonna e della riga.