Le potenzialità di una proprietà CSS che in pochi utilizzano: attr()

attr(), una proprietà di cui pochi conoscono l'esistenza e che quasi nessuno utilizza. Utilissima in diverse occasioni, in questo articolo scopriremo come funziona e alcuni dei suoi casi d'uso.

Le potenzialità di una proprietà CSS che in pochi utilizzano: attr()

Nel mondo dello sviluppo web, esplorare le funzionalità avanzate dei linguaggi di stile come il CSS può portare a piacevoli scoperte. Tra queste, l'attributo attr() emerge come un'opzione elegante e pratica che aggiunge dinamicità e personalizzazione ai nostri layout. In questo articolo, esamineremo nel dettaglio l'utilizzo di questa proprietà, le sue funzionalità e forniremo esempi pratici di come può essere impiegato in scenari reali.

Funzionamento di attr()

L'attributo attr() agisce come un placeholder all'interno della proprietà content. Per esempio, consideriamo il seguente codice:

CSS
.content::before { content: attr(data-info); }

Questo ci consente di inserire il valore dell'attributo data-info all'interno del selettore :before o :after. Se abbiamo un elemento HTML simile a questo:

HTML
<div class=”content” data-info=”artCode”>il nostro primo articolo</div> <style> .content::before { content: attr(data-info); } </style>

Quando applichiamo lo stile CSS precedente, il testo "Blocco citazione:" verrà visualizzato prima del contenuto dell'elemento div.

Possiamo anche concatenare l'attributo attr() con del testo:

CSS
.content::before{ content: "developed by " attr(data-info); }

Questo combinerà il testo "Tipo elemento: " con il valore dell'attributo data-info, generando un output combinato.

Dinamicità dei valori

Un punto di forza dell'attributo attr() è la sua capacità di riflettere i cambiamenti nei valori degli attributi in tempo reale. Ciò significa che se il valore dell'attributo cambia dinamicamente attraverso degli script, il testo generato tramite attr() si aggiorna di conseguenza, rendendolo quindi sensibile ai cambi di valore degli attributi del nostro contenitore.

Questo lo rende particolarmente utile in applicazioni web complesse dove i dati sono passati e manipolati attraverso gli attributi HTML.

Limitazioni e considerazioni

Tuttavia, è importante notare che l'attributo attr() ha alcune limitazioni. Per esempio, non è possibile utilizzarlo per definire direttamente valori di proprietà come background-image o width.

È vincolato esclusivamente alla proprietà content per la generazione di testo all'interno degli pseudoelementi :before o :after.

CSS
/* Casi d’uso NON validi */ .social-icon { background-image: url(attr(data-icon-url)); } img { width: attr(width); } .container { --main-color: attr(data-main-color); }

Caso d’uso: tabelle responsive

Capita molto spesso di trovarsi in difficoltà nel gestire la responsività delle tabelle, soprattutto quando si hanno tabelle con molteplici colonne che rendono ostica la visualizzazione da dispositivi mobile. In questo caso ci viene in contro la proprietà attr(), vediamo come!

Prendiamo in considerazione la seguente tabella:

HTML
<table> <tr> <th>Posizione</th> <th>Nome</th> <th>Squadra</th> <th>Presenze</th> <th>Goal Fatti</th> </tr> <tr> <td data-cell="Posizione">1</td> <td data-cell="Nome">Lionel Messi</td> <td data-cell="Squadra">Paris Saint-Germain</td> <td data-cell="Presenze">25</td> <td data-cell="Goal Fatti">30</td> </tr> <tr> <td data-cell="Posizione">2</td> <td data-cell="Nome">Cristiano Ronaldo</td> <td data-cell="Squadra">Manchester United</td> <td data-cell="Presenze">23</td> <td data-cell="Goal Fatti">25</td> </tr> <tr> <td data-cell="Posizione">3</td> <td data-cell="Nome">Robert Lewandowski</td> <td data-cell="Squadra">Bayern Monaco</td> <td data-cell="Presenze">24</td> <td data-cell="Goal Fatti">28</td> </tr> </table>

Questa è una semplice tabella di una classifica marcatori di calcio. La particolarità è che viene aggiunto all'interno di ogni singola cella un attributo data-cell="" dove viene riportata la colonna di riferimento del dato.

Per gestire la responsività e la leggibilità anche in versione mobile, basterà aggiungere qualche stile in una media query; senza bisogno di dover rivoluzionare il nostro layout:

CSS
@media screen and (max-width: 600px) { th { display: none; } td { display: block; width:100%; } td::before { content: attr(data-cell) ': '; font-weight: bold; } }

In primo luogo nascondiamo l'intestazione della tabella con un display: none.

Successivamente impostiamo un display: block a tutti i td in modo che occupino tutto lo spazio disponibile su una singola riga.

Come ultimo andiamo ad inserire in un :before il valore del dato che stiamo visualizzando all'interno di ogni singola cella (avendo nascosto in precedenza l'intestazione).

Con 3 semplici modifiche CSS abbiamo dunque reso leggibile la tabella da tutti i dispositivi con all'utilizzo della proprietà attr()!

Ecco l'esempio completo:

HTML
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Classifica Giocatori di Calcio</title> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet"> <style> * { box-sizing: border-box; } body { font-family: 'Inter', sans-serif; color: #ffffff; margin: 0; padding: 0; } h2 { text-align: center; color: #ffffff; margin-top: 30px; } table { border-collapse: collapse; width: 95%; max-width: 900px; margin: 20px auto; background-color: #2e2e2e; } th, td { border: 1px solid #3e3e3e; text-align: left; padding: 12px; } th { background-color: #3e3e3e; color: #ffffff; font-weight: bold; } tr:nth-child(odd) { background-color: #3e3e3e; } tr:hover { background-color: #4e4e4e; } @media screen and (max-width: 600px) { th{ display: none; } td{ display: block; width:100%; } td::before{ content: attr(data-cell) ': '; font-weight: bold; } } </style> </head> <body> <table> <tr> <th>Posizione</th> <th>Nome</th> <th>Squadra</th> <th>Presenze</th> <th>Goal Fatti</th> </tr> <tr> <td data-cell="Posizione">1</td> <td data-cell="Nome">Lionel Messi</td> <td data-cell="Squadra">Paris Saint-Germain</td> <td data-cell="Presenze">25</td> <td data-cell="Goal Fatti">30</td> </tr> <tr> <td data-cell="Posizione">2</td> <td data-cell="Nome">Cristiano Ronaldo</td> <td data-cell="Squadra">Manchester United</td> <td data-cell="Presenze">23</td> <td data-cell="Goal Fatti">25</td> </tr> <tr> <td data-cell="Posizione">3</td> <td data-cell="Nome">Robert Lewandowski</td> <td data-cell="Squadra">Bayern Monaco</td> <td data-cell="Presenze">24</td> <td data-cell="Goal Fatti">28</td> </tr> </table> </body> </html>

Caso d’uso: testi multilingua nei content:''

Altro caso d'uso che potrebbe tornarci utili in progetti più articolati: ci troviamo all'interno di una pagina multilingua e abbiamo la necessità di inserire un testo all'interno di un content tramite CSS, proprio come in questo caso:

HTML
<div className="header__switch"> <button className="header__switch-theme" onClick={handleDarkMode} aria-label="Cambia tema" ></button> </div>
CSS
.header__switch-theme::before { content: attr(aria-label); font-size: 0.7rem; line-height: 1; position: absolute; top: -15px; left: 0; right: 0; text-align: center; }

Nel contesto attuale, abbiamo un pulsante che consente di impostare il tema della pagina (chiaro/scuro).

Per chiarire la funzione di questo pulsante, è necessario inserire un titolo sopra di esso. Ho deciso di farlo tramite CSS, utilizzando il posizionamento assoluto e l'attributo aria-label come parte del contenuto.

Questo approccio semplifica la gestione delle traduzioni in lingua della pagina, poiché il testo da tradurre non è separato in un foglio di stile distinto, ma è integrato direttamente nella struttura HTML della pagina, pur essendo utilizzato all'interno della proprietà content CSS.

Proverete ad utilizzarlo in qualche vostro progetto?