Elenchi, marcatori e contatori CSS
Pubblicato: 2022-03-10 Le liste nei CSS hanno proprietà particolari che ci danno lo stile standard delle liste che ci aspettiamo. Un elenco non ordinato ottiene un elenco puntato, del tipo disc
e gli elenchi ordinati sono numerati. Il mio interesse nell'esplorare gli elenchi in modo più dettagliato è venuto da alcuni lavori che ho fatto per documentare lo pseudo-elemento ::marker
per MDN. Questo pseudo-elemento viene fornito in Firefox 68 e viene rilasciato oggi . Con lo pseudo elemento ::marker
a nostra disposizione, possiamo iniziare a fare alcune cose interessanti con le liste e in questo articolo spiegherò di più.
Decostruire una lista
Potresti non aver pensato molto alle liste, anche se le usiamo frequentemente nel nostro markup. Molte cose possono essere contrassegnate in modo abbastanza logico come un elenco. Mentre le istruzioni dettagliate o gli elementi classificati possono essere naturalmente descritti da un elenco ordinato <ol>
, molte cose in un progetto possono essere descritte utilizzando un elenco non ordinato <ul>
. Un uso molto comune dell'elemento, ad esempio, è contrassegnare la navigazione, in quanto è un elenco di destinazioni sul sito. Per la nostra esplorazione, iniziamo scoprendo esattamente cos'è un elenco in CSS.
Come per molte cose nei CSS, agli elenchi sono applicati alcuni valori iniziali. Questi valori li fanno sembrare un elenco. Questi valori speciali iniziano con l'informazione che un elemento dell'elenco ha la proprietà display
con un valore di list-item
. Questo crea una casella a livello di blocco, con una casella di indicatore aggiuntiva. La casella dell'indicatore è il punto in cui viene aggiunto il punto elenco o il numero.
Gli elenchi sono stati definiti all'inizio in CSS e gran parte della definizione di elenchi come li usiamo oggi proviene da CSS2. La specifica CSS2 descrive una voce di elenco come segue:
“Un elemento condisplay: list-item
genera una casella di blocco principale per il contenuto dell'elemento e, a seconda dei valori dilist-style-type
elist-style-image
, eventualmente anche una casella marker come indicazione visiva che l'elemento è una voce di elenco.
La casella del blocco principale è la casella principale dell'elemento e contiene tutti i figli poiché un elemento dell'elenco può contenere altro markup. La casella del marker viene quindi posizionata rispetto a questa casella principale. La specifica prosegue descrivendo in dettaglio il fatto che qualsiasi colore di sfondo sarà solo dietro questa casella principale e non l'indicatore. Inoltre, l'indicatore può essere impostato su uno di un intervallo di valori predefiniti:
-
disc
-
circle
-
square
-
decimal
-
decimal-leading-zero
-
lower-roman
-
upper-roman
-
lower-greek
-
lower-latin
-
upper-latin
-
armenian
-
georgian
-
lower-alpha
-
upper-alpha
-
none
-
inherit
La specifica del display di livello 3 definisce display: list-item
insieme agli altri possibili valori per la proprietà display
. Fa riferimento a CSS 2.1, così come molte proprietà e valori CSS che provengono da CSS2, ma descrive la parola chiave list-item
come "causando l'elemento di generare uno pseudo-elemento ::marker
".
La specifica di livello 3 introduce anche la possibilità di creare una voce di elenco inline con la sintassi dei due valori utilizzata display: inline list-item
. Questo non è ancora implementato dai browser.
Creazione di caselle contrassegno su elementi non di elenco
Come con altri valori di display
, è perfettamente valido assegnare a qualsiasi elemento HTML un tipo di visualizzazione di list-item
(se si desidera generare uno pseudo-elemento ::marker
sull'elemento). Ciò non farà sì che l'elemento diventi semanticamente un elemento dell'elenco, ma verrà visualizzato solo visivamente come elemento dell'elenco e quindi sarà in grado di avere un ::marker
. Quando discutiamo dello pseudo-elemento ::marker
di seguito, scoprirai alcuni casi in cui fornire altri elementi display: list-item
può essere utile.
Il CSS elenca le specifiche di livello 3: ::marker
e contatori
La specifica di display
amplia e chiarisce la definizione di liste che troviamo nei CSS2, tuttavia esiste anche una specifica che definisce in dettaglio il comportamento delle liste: la CSS Lists Specification Level 3. Poiché il comportamento di base delle voci di elenco è definito in display
, questo specifica in dettaglio la casella marker generata quando qualcosa è display: list-item
insieme ai contatori che vengono utilizzati per impostazione predefinita ogni volta che si crea un elenco ordinato. Ci sono alcune funzionalità potenzialmente utili accessibili tramite queste funzionalità.
Il ::marker
Pseudo-elemento
Lo pseudo-elemento ::marker
consente di scegliere come target l'indicatore dell'elenco, separatamente dal contenuto dell'elemento dell'elenco. Questo non era possibile nelle versioni precedenti di CSS, quindi, se hai cambiato il colore o la dimensione del carattere di ul
o li
, questo cambierebbe anche il colore e la dimensione del carattere dei marcatori. Per fare qualcosa di apparentemente semplice come avere elenchi puntati di colori diversi rispetto al testo, comporterebbe l'avvolgimento del contenuto dell'elemento dell'elenco in un intervallo (o l'utilizzo di un'immagine per il marcatore).
ul { color: #00b7a8; } ul span { color #333; }
Con lo pseudo elemento ::marker
, la cosa più semplice che potresti voler provare è avere un diverso colore del punto elenco rispetto al testo, il che significa che invece del codice nell'esempio sopra puoi usare:
ul { color: #333; } ul ::marker { color: #00b7a8; }
Potresti anche voler utilizzare una dimensione e font-family
di caratteri diverse per la numerazione in un elenco ordinato.
ol ::marker { font-size: 200%; color: #00b7a8; font-family: "Comic Sans MS", cursive, sans-serif; }
Puoi vederli tutti in un browser di supporto usando il mio esempio CodePen:
È possibile utilizzare lo pseudo-elemento ::marker
su elementi non in elenco. Nel codice seguente, ho impostato un'intestazione da display: list-item
. Questo gli dà un punto elenco e quindi una ::marker
box da mirare.
Ho cambiato il proiettile per usare un'emoji:
h1 { display: list-item; } h1::marker { content: ""; }
Nell'esempio sopra, ho usato il contenuto generato nelle regole per il marcatore. Solo un piccolo sottoinsieme di proprietà CSS è disponibile per l'uso su ::marker
. Questi includono le proprietà del carattere e il colore, tuttavia includono anche la proprietà del content
, per includere il contenuto generato.
L'aggiunta di content
come proprietà consentita per ::marker
è recente, tuttavia è inclusa nell'implementazione di Firefox. L'inclusione significa che puoi fare cose come includere una stringa di testo in un ::marker
. Offre inoltre ulteriori possibilità per la formattazione dei marker quando si combina l'uso dei contatori con ::marker
.
Supporto del browser e fallback
Per i browser che non supportano lo pseudo-elemento ::marker
, il fallback è il normale marker che sarebbe stato comunque visualizzato. Sfortunatamente, al momento non possiamo utilizzare le query di funzionalità per rilevare il supporto per selettori come questo pseudo-elemento in questo momento, sebbene sia stato sollevato un problema sull'aggiunta di questo alle specifiche. Ciò significa che non puoi eseguire il fork del tuo codice per fare una cosa quando hai il supporto e qualcos'altro se non lo hai. Nella maggior parte dei casi, ricadere sull'indicatore normale sarà una soluzione ragionevole.
Contatori
Gli elenchi ordinati hanno una numerazione degli elenchi, qualcosa che si ottiene tramite un contatore CSS. La specifica CSS Lists descrive quindi anche questi contatori. Possiamo accedere e creare noi stessi dei contatori che, combinati con lo pseudo-elemento ::marker
, possono fornirci alcune utili funzionalità. Questi contatori possono essere utilizzati anche in contenuti generati regolarmente (non ::marker
).
Se ho un elenco numerato di passaggi (e vorrei scrivere "Passaggio 1", "Passaggio 2" e così via), posso farlo utilizzando il contenuto generato nel mio marcatore e aggiungendo il contatore list-item
, questo rappresenta il contatore integrato:
::marker { content: "Step " counter(list-item) ": "; }
Contatori nidificati
Se hai elenchi nidificati, un modo comune per numerarli è avere un numero intero per l'elemento di primo livello, (1), quindi elementi figlio come (1.1, 1.2) e i loro figli (1.1.1, 1.1.2), e così via. È possibile ottenere ciò utilizzando più funzionalità dei contatori.
Quando annidi elenchi HTML, ti ritroverai con più contatori con lo stesso nome, annidati uno dentro l'altro. È possibile accedere al nido di contatori utilizzando la funzione counters()
.
Nel codice seguente, sto usando counters()
per formattare i miei marcatori di elenco come descritto sopra. Il primo argomento per counters()
è il nome del contatore da utilizzare. Sto usando il contatore list-item
integrato. Il secondo argomento è una stringa: questo è ciò che verrà concatenato tra i contatori di output (sto usando un .
). Infine, aggiungo un :
al di fuori della funzione contatore ma all'interno del valore del content
in modo che il mio output del contatore sia separato dal contenuto da due punti.
::marker { content: counters(list-item,'.') ':'; color: #00b7a8; font-weight: bold; }
Questo mi dà l'output come nell'immagine. Se stai utilizzando un browser che supporta ::marker
e contatori, puoi vederlo funzionare nell'esempio CodePen: prova a cambiare la stringa da un file .
a qualcos'altro per vedere come ciò cambia l'output.
Qual è la differenza tra counter()
e counters()
?
La funzione counter()
che abbiamo usato nel primo esempio per scrivere i nostri passi usa solo il contatore più interno. Pertanto, nella situazione in cui hai una serie di liste nidificate, scriverai il contatore relativo al livello in cui ti trovi attualmente.
La funzione counters()
essenzialmente scrive l'intero ramo e ti dà l'opportunità di concatenare una stringa tra i contatori nel ramo. Quindi, se hai una voce di elenco con un contatore di 2
(che fa parte di una lista annidata all'interno di una voce di lista con un contatore di 4
), il ramo contiene:
-
4
-
2
Puoi emetterlo come 4.2
nel marcatore usando:
::marker { content: counters(list-item,'.'); }
Contatori su altri elementi
I contatori possono essere usati su cose che non sono liste — sia per produrre un marcatore — nel qual caso l'elemento dovrà avere display: list-item
— o per produrre contenuto generato regolare. I contatori sono ampiamente utilizzati nella produzione di libri, al fine di abilitare la numerazione dei capitoli e delle figure in altre cose. Non c'è motivo per non adottare un approccio simile sul web, in particolare per gli articoli più lunghi.
Le proprietà CSS definite nella specifica CSS Lists che si occupano di questi contatori sono:
-
counter-set
-
counter-reset
-
counter-increment
Per vedere come funzionano al di fuori degli elenchi, possiamo guardare un esempio di utilizzo di contatori per numerare le intestazioni in un documento.
La prima cosa che devo fare è creare un contatore per le intestazioni sull'elemento body — pronto per l'uso. Sto usando la proprietà di counter-reset
per farlo. Le proprietà counter-reset
e azzeramento del counter-set
sono molto simili. La proprietà counter-reset
creerà un nuovo contatore se non esiste già un contatore con il nome specificato, ma creerà anche contatori nidificati come descritto sopra se esiste un contatore con quel nome. La proprietà counter-set
creerà un nuovo contatore solo se non è presente alcun contatore con quel nome. Per questo, l'uso di entrambe le proprietà funzionerebbe bene, tuttavia, counter-set
non ha un buon supporto per il browser come counter-reset
, quindi sto prendendo la strada pratica:
body { counter-reset: heading-counter; }
Ora che ho un contatore, posso quindi utilizzare la proprietà counter-increment
sul selettore per le intestazioni; questo dovrebbe incrementare il contatore ogni volta che il selettore corrisponde.
h2 { counter-increment: heading-counter; }
Per vedere il valore, devo inviarlo al documento. Posso farlo usando il contenuto generato e aggiungendolo before
dell'intestazione come mostrato nel seguente esempio CodePen:
h2::before { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; }
In alternativa, potrei trasformare l'elemento h2
in un elemento list-item
e quindi utilizzare ::marker
, come dimostrato di seguito. Come già dettagliato, l'utilizzo dell'elemento ::marker
ha un supporto del browser limitato. In Firefox, dovresti vedere il contatore utilizzato come indicatore per l'intestazione, mentre altri browser mostreranno il punto elenco predefinito.
h2 { display: list-item; } h2::marker { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; }
Contatori sugli elementi del modulo
C'è anche un po' di interattività che puoi ottenere usando i CSS Counters, qualcosa che potresti pensare di aver bisogno di JavaScript per farlo.
Ho un modulo che ha un numero di campi obbligatori. Lo stato richiesto può essere selezionato in CSS con una pseudo-classe :required
e il fatto che un campo non sia stato completato può essere rilevato tramite la :invalid
. Ciò significa che possiamo verificare la presenza di campi obbligatori e non validi e incrementare un contatore. Quindi emettilo come contenuto generato.
Quanto sia utile in realtà è discutibile, dato che non possiamo davvero fare nulla con quel valore se non inserirlo nel contenuto generato. Ci sono anche preoccupazioni riguardo al fatto che il contenuto generato sia inaccessibile a determinati lettori di schermo, quindi qualsiasi utilizzo che sia più che decorativo dovrebbe garantire altri modi di accedere a tali informazioni. Leggi "Supporto per l'accessibilità per i contenuti generati da CSS" e le informazioni più recenti "Compatibilità con il lettore di schermate delle proprietà dei contenuti CSS" per maggiori dettagli sull'accessibilità e sui contenuti generati.
Tuttavia, dimostra che i contatori possono ottenere risultati più utili della semplice numerazione degli elenchi. Può darsi che un giorno la conoscenza torni utile per risolvere alcuni problemi su cui stai lavorando.
Scopri di più
Questo articolo è finito piuttosto lontano dalle liste di stili, nonostante il fatto che tutto ciò che ho descritto si trova nella specifica delle liste CSS. Puoi trovare maggiori informazioni sulle cose descritte nei link sottostanti. Se hai trovato un uso interessante per i CSS Counters, o puoi pensare a cose per cui potresti usare ::marker
, aggiungi una nota nei commenti.
-
::marker
-
counter-set
-
counter-reset
-
counter-increment
- "Utilizzo dei contatori CSS", documenti web MDN
- "Conteggio con contatori CSS e griglia CSS", CSS-Tricks