Stile di celle vuote con contenuto generato e layout della griglia CSS

Pubblicato: 2022-03-10
Riepilogo rapido ↬ Vi siete mai chiesti come ottenere uno stile di celle della griglia vuote senza aggiungere elementi vuoti ridondanti? Bene, i contenuti generati dai CSS possono aiutarti a fare proprio questo.

Un problema comune per il layout della griglia è quando un nuovo arrivato al metodo di layout si chiede come modellare una cella della griglia che non contiene alcun contenuto. Nell'attuale specifica di livello 1, ciò non è possibile poiché non è possibile scegliere come target una cella della griglia o un'area della griglia vuota e applicare lo stile. Ciò significa che per applicare lo stile è necessario inserire un elemento.

In questo articolo, darò un'occhiata a come utilizzare il contenuto generato CSS per ottenere uno stile di celle vuote senza aggiungere elementi vuoti ridondanti e mostrerò alcuni casi d'uso in cui questa tecnica ha senso.

Dando un'occhiata più da vicino a BFC

Se hai mai creato un layout con CSS, probabilmente sai cos'è BFC. Capire perché funziona e come crearne uno è utile e può aiutarti a capire come funziona il layout in CSS. Leggi un articolo correlato →

Perché non possiamo già modellare aree vuote?

Il paragrafo di apertura della specifica della griglia dice:

“Questo modulo CSS definisce un sistema di layout bidimensionale basato su griglia, ottimizzato per la progettazione dell'interfaccia utente. Nel modello di layout della griglia, i figli di un contenitore della griglia possono essere posizionati in slot arbitrari in una griglia di layout predefinita flessibile o di dimensioni fisse.

La frase chiave qui è "figli di un contenitore a griglia". La specifica definisce la creazione di una griglia sull'elemento padre, in cui possono essere posizionati gli elementi figlio. Non definisce alcuno stile di quella griglia, nemmeno arrivando al punto di implementare qualcosa come la proprietà column-rule che abbiamo in Layout multicolonna. Stiliamo gli elementi figlio, e non la griglia stessa, il che ci lascia la necessità di avere un elemento di qualche tipo a cui applicare quello stile.

Altro dopo il salto! Continua a leggere sotto ↓

Utilizzo di elementi ridondanti come gancio per lo styling

Un modo per inserire qualcosa nello stile è inserire un elemento ridondante nel documento, ad esempio uno span o un div. Gli sviluppatori tendono a non apprezzare questa idea, nonostante abbiano aggiunto per anni ulteriori "riga wrapper" ridondanti per ottenere layout di griglia utilizzando float. Forse quell'elemento ovviamente vuoto è più sgradevole della ridondanza in qualche modo nascosta dell'elemento wrapper!

Gli elementi completamente vuoti diventano elementi della griglia e possono avere sfondi e bordi aggiunti proprio come un elemento che contiene contenuto, come dimostra questo esempio.

Guarda gli elementi Pen Empty che diventano Grid Items di Rachel Andrew (@rachelandrew) su CodePen.

Guarda gli elementi Pen Empty che diventano Grid Items di Rachel Andrew (@rachelandrew) su CodePen.

Eric Meyer, nel suo articolo A List Apart Faux Grid Tracks, sostiene che l'utilizzo dell'elemento b come elemento ridondante di scelta, poiché non conferisce alcun significato semantico, è breve e anche abbastanza ovvio nel markup come hook.

È improbabile che l'inserimento di alcuni elementi div o b aggiuntivi sia il più grande crimine contro un buon markup che tu abbia mai commesso, quindi non perderei il sonno scegliendo quell'approccio se necessario. Lo sviluppo Web molto spesso implica la scelta dell'approccio meno non ottimale per portare a termine il lavoro fino a quando non viene escogitata una soluzione migliore. Preferisco tuttavia mantenere il mio stile in un posto, se possibile, al sicuro nel foglio di stile. Se non altro, semplifica il riutilizzo degli stili, senza doversi preoccupare del markup aggiuntivo richiesto. È per questo motivo che tendo a guardare al contenuto generato, qualcosa che mi è molto familiare dal lavoro che ho fatto formattando i libri con i CSS, dove trascorri la maggior parte del tuo tempo lavorando con questa funzione.

Utilizzo del contenuto generato come gancio di stile

CSS Generated Content utilizza le pseudo-classi ::before e ::after CSS insieme alla proprietà content per inserire una sorta di contenuto nel documento. L'idea di inserire del contenuto potrebbe indurre a pensare che questo sia per inserire del testo e, sebbene ciò sia possibile, per i nostri scopi siamo interessati a inserire un elemento vuoto come figlio diretto del nostro Grid Container. Con un elemento inserito possiamo modellarlo.

Nell'esempio seguente ho un elemento contenitore, che diventerà il mio Grid Container, con un altro elemento annidato all'interno. Questo singolo figlio diretto diventerà un elemento della griglia. Ho definito una griglia a tre colonne e tre righe sul contenitore e quindi ho posizionato il singolo elemento usando le linee della griglia, quindi si trova nella cella della griglia centrale.

 <div class="grid"> <div class="item"></div> </div>
 .grid { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-gap: 10px; } .grid > * { border: 2px solid rgb(137,153,175); } .item { grid-column: 2; grid-row: 2; }

Se diamo un'occhiata a questo esempio, usando Firefox Grid Inspector per sovrapporre le linee della griglia, possiamo vedere come esistono le altre celle vuote della griglia, tuttavia, per aggiungere uno sfondo o un bordo dovremmo aggiungere un figlio aggiuntivo elementi. Che è esattamente ciò che consente il contenuto generato.

Un singolo elemento nella cella centrale di una griglia
Un unico elemento della griglia, con le tracce evidenziate con Firefox Grid Inspector

Nel mio CSS aggiungo una stringa vuota, ::before e ::after il mio Grid Container. Questi diventeranno immediatamente elementi della griglia e si estenderanno per riempire il loro contenitore. Quindi aggiungo lo stile di cui ho bisogno per le scatole, in questo caso aggiungendo un colore di sfondo, e le posizioni come farei con qualsiasi normale elemento della griglia.

 .grid::before { content: ""; background-color: rgb(214,232,182); grid-column: 3; grid-row: 1; } .grid::after { content: ""; background-color: rgb(214,232,182); grid-column: 1; grid-row: 3; } 
Un singolo elemento nella cella centrale di una griglia, con due elementi verdi negli angoli
Un singolo elemento della griglia e i due elementi che generano il contenuto

Nel documento abbiamo ancora un solo elemento figlio, gli elementi di stile ridondanti sono contenuti all'interno del CSS, il che sembra perfettamente ragionevole in quanto sono lì solo per scopi di stile.

Limitazioni dell'approccio ai contenuti generati

L'ovvio problema con questo approccio diventerà evidente se decidi di voler modellare anche le celle della griglia in alto a destra e in basso a sinistra. Puoi applicare solo una parte del contenuto generato nella parte superiore e una nella parte inferiore del contenitore, non sono consentiti più pseudo elementi ::before e ::after . Il metodo non funzionerà se vuoi crearti una scacchiera CSS Grid! Se ritieni di aver bisogno di fare molti stili di celle vuote, per il prossimo futuro, l'approccio "Filler B" spiegato sopra è probabilmente la soluzione migliore.

Il metodo del contenuto generato potrebbe anche confondere un futuro sviluppatore che lavora al tuo progetto. Poiché stiamo prendendo di mira il contenitore, se riutilizzi quella classe altrove porterà con te il contenuto generato, questo è utile se è quello che vuoi. Nel prossimo esempio, abbiamo aggiunto linee decorative su entrambi i lati di un'intestazione, sarebbe ragionevole che ogni istanza di un h1 avesse quelle linee. Tuttavia, sarebbe molto confuso se non fossi consapevole che sarebbe successo! Una riga di commento sopra le regole del contenitore aiuterà qui. Tendo a lavorare in questi giorni in una libreria di modelli, che aiuta davvero questi componenti in modo ordinato in un posto, rendendo più ovvio cosa succede quando una classe viene applicata a un elemento.

Intestazioni fantasiose

Uno dei miei trucchi per i contenuti generati preferiti è quello di definire lo stile delle intestazioni. In passato, dovevo respingere gli stili di intestazione che avrebbero richiesto wrapper aggiuntivi e tracce di posizionamento assoluto per essere raggiunti. Quando il contenuto proviene da un CMS, è spesso impossibile aggiungere quei wrapper ridondanti.

Con Griglia e contenuto generato, possiamo aggiungere una riga su entrambi i lati della nostra intestazione senza aggiungere alcun markup aggiuntivo. La linea crescerà e si ridurrà in base allo spazio disponibile e tornerà elegantemente a un'intestazione centrata semplice quando Grid non è disponibile nei browser.

Un'intestazione con righe su entrambi i lati, seguita da testo
Lo stile di intestazione che vogliamo ottenere

Il nostro markup è un semplice h1 .

 <h1>My heading</h1>

Nelle regole per h1 creo una griglia a tre colonne. Il valore di grid-template-columns fornisce una traccia di 1fr quindi una di auto e una traccia finale di 1fr . Le due tracce 1fr condivideranno lo spazio disponibile rimasto dopo che l'intestazione ha occupato lo spazio necessario per essere inserita nella traccia con dimensioni auto .

Ho aggiunto la proprietà text-align con un valore di center in modo che la mia intestazione venga inserita nei browser senza griglia.

 h1 { text-align: center; display: grid; grid-template-columns: 1fr auto 1fr; grid-gap: 20px; }

Ora aggiungiamo il nostro contenuto generato, per aggiungere una riga prima e dopo il testo dell'intestazione. Incorporo queste regole in una Feature Query, quindi non otteniamo alcun contenuto strano generato nei browser senza layout della griglia.

La riga stessa è un bordo sull'elemento generato.

 @supports (display: grid) { h1:before, h1:after { content: ""; align-self: center; border-top: 1px solid #999; } }

Questo è tutto ciò che devi fare! Puoi usare la stessa tecnica per aggiungere qualsiasi stile, o anche un'icona su entrambi i lati di un elemento, sopra o sotto l'elemento. Inserendo il tuo articolo in una traccia separata sai che non c'è alcuna possibilità che l'oggetto possa finire per sovrapporsi al testo dell'intestazione, il che tendeva a essere il problema quando si tentava di fare questo genere di cose con il posizionamento assoluto. Hai anche il vantaggio dei modi precisi in cui gli elementi possono essere allineati l'uno contro l'altro nella griglia.

Vedi l'esempio di intestazione Pen Generated Content di Rachel Andrew (@rachelandrew) su CodePen.

Vedi l'esempio di intestazione Pen Generated Content di Rachel Andrew (@rachelandrew) su CodePen.

Questo è un bell'esempio di un miglioramento possibile utilizzando il layout della griglia che potresti sfruttare anche se non sei ancora pronto per affrontare un'importante riprogettazione utilizzando la griglia. Ritorna molto bene a un'intestazione semplice, le persone con browser di supporto ottengono il tocco in più e tutti ottengono il contenuto. Un approccio simile è stato adottato da Eric Meyer, utilizzando il contenuto generato per aggiungere virgolette facilmente modificabili e posizionabili a un elemento blockquote.

Con queste piccole funzionalità, spesso non inizio a pensare che utilizzerò Grid Layout. È quando inizio a capire come implementare il mio progetto, mi rendo conto che è il metodo di layout da scegliere. È per questo motivo che incoraggio le persone a non pensare a Grid come a un layout di pagina rispetto ai componenti, se lo fai potresti perdere molte opportunità in cui può aiutare.

Aggiunta di sfondi e bordi alle aree del tuo design

Possiamo anche utilizzare il contenuto generato per impilare gli oggetti; il fatto è che più di un elemento può occupare una particolare cella della griglia. Questo può includere quegli elementi inseriti con contenuto generato.

Nel prossimo esempio, ho un design con due sezioni di contenuto e un elemento a larghezza intera. Dietro il contenuto c'è uno sfondo che corre anche sotto l'elemento a larghezza intera.

Un layout a colonna singola, con un'immagine a tutta larghezza
Il layout a cui puntiamo

Il markup ha un contenitore con le sezioni e l'elemento a larghezza intera come figli diretti e sto usando il posizionamento basato su riga per posizionare i miei elementi sulla griglia.

 <article class="grid"> <section class="section1"> <p>…</p> </section> <div class="full-width"> <img src=“placeholder.jpg” alt=“Placeholder”> </div> <section class="section2"> <p>…</p> </section> </article>
 .grid { display: grid; grid-template-columns: 1fr 20px 4fr 20px 1fr; grid-template-rows: auto 300px auto; grid-row-gap: 1em; } .section1 { grid-column: 3; grid-row: 1; } .section2 { grid-column: 3; grid-row: 3; } .full-width { grid-column: 1 / -1; grid-row: 2; background-color: rgba(214,232,182,.5); padding: 20px 0; }

Questo mi dà il layout con l'immagine a larghezza intera e due sezioni di contenuto posizionate; tuttavia, se aggiungo lo sfondo alle sezioni, si fermerà sopra lo row-gap tra la section e l'immagine a larghezza intera.

 .section { background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); } 
Un layout a colonna singola, con un'immagine a larghezza intera, colore di sfondo dietro le aree del contenuto
Lo sfondo è ora dietro le aree di contenuto

Se rimuovessimo il grid-row-gap e usassimo il riempimento per creare lo spazio, non consentirebbe comunque l'effetto dello sfondo in esecuzione sotto il pannello a larghezza intera.

È qui che possiamo utilizzare i contenuti generati. Aggiungo il contenuto generato ::before del contenitore della griglia e gli do un colore di sfondo. Se non faccio nient'altro, questo posizionerà il contenuto nella prima cella della griglia.

 .grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); } 
Un quadrato di colore nell'angolo in alto a sinistra del layout
Il contenuto generato va nella prima cella vuota della griglia

Posso quindi posizionare il contenuto utilizzando il posizionamento basato sulla linea per allungare l'area che dovrebbe mostrare il colore di sfondo.

 .grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }

Puoi vedere l'esempio completo in questo CodePen.

Guarda l'esempio di sfondo di Pen Generated Content di Rachel Andrew (@rachelandrew) su CodePen.

Guarda l'esempio di sfondo di Pen Generated Content di Rachel Andrew (@rachelandrew) su CodePen.

Controllo dello stack con z-index

Nell'esempio sopra, il contenuto generato viene inserito con ::before . Ciò significa che gli altri elementi vengono dopo, è in fondo allo stack e quindi verrà visualizzato dietro il resto del contenuto che è dove lo voglio. Puoi anche usare z-index per controllare lo stack. Prova a cambiare il selettore ::before in ::after . Lo sfondo del contenuto generato ora si trova sopra tutto, come puoi vedere dal modo in cui il bordo scorre sull'immagine. Questo perché ora è diventata l'ultima cosa nel contenitore della griglia, è dipinta per ultima e quindi appare "in cima".

Per cambiarlo, devi dare a questo elemento una proprietà z-index inferiore rispetto a tutto il resto. Se nient'altro ha un valore z-index , la cosa più semplice da fare è dare al contenuto generato uno z-index di -1 . Questo farà sì che sia la prima cosa nello stack, come l'elemento con lo z-index più basso.

 .grid::after { z-index: -1; content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }

L'aggiunta di sfondi in questo modo non deve limitarsi a eliminare completamente uno sfondo dietro i tuoi contenuti. Essere in grado di far apparire blocchi di colore dietro parte del tuo design potrebbe creare effetti interessanti.

È qualcosa che la specifica potrebbe risolvere in futuro?

L'aggiunta di sfondi e bordi sembra una caratteristica mancante della specifica CSS Grid e di cui il gruppo di lavoro ha discusso insieme a molti membri della comunità (il thread di discussione è su GitHub).

Se hai casi d'uso non facilmente risolvibili con il contenuto generato, aggiungi i tuoi pensieri a quel thread. I tuoi commenti e casi d'uso aiutano a dimostrare l'interesse degli sviluppatori per la funzione e assicurano anche che qualsiasi proposta copra il tipo di cose che devi fare.

Altri esempi, per favore!

Se questo articolo ti incoraggia a sperimentare con i contenuti generati o, se hai già un esempio, aggiungilo ai commenti. Tutti sono nuovi nell'usare Grid in produzione, quindi ci sono molti " Non ci avevo mai pensato! ” momenti da vivere, poiché combiniamo Grid con altri metodi di layout.