A Marcello Cerruti, amico e maestro.
Tradizionalmente si è portati a ritenere che tra struttura S (codice HTML) e presentazione P (codice CSS) esista una corrispondenza biunivoca tale che ad ogni elemento di un insieme corrisponderà un unico elemento nell'altro insieme. Nello specifico, si consideri il seguente esempio:
.warning {
color: #c00;
background: #ffc;
}
In questo caso un elemento class in P corrisponde a più elementi
in S. L'attributo class ha solo valore presentazionale. D'altro canto
l'attributo id ha sia valore presentazionale che strutturale, in quanto
può non solo identificare uno stile unico nella pagina, ma anche, ad esempio,
un'ancora. Inoltre mentre class può essere applicato a diversi elementi,
id conserva una sua peculiare univocità.
Inoltre è altrettanto sbagliato ritenere che i due modelli (o insiemi) siano reciprocamente interdipendenti: la struttura sopravvive ed è fruibile senza la presentazione, mentre la presentazione non ha senso senza la struttura.
In questo contesto occorre stabilire il ruolo del contenuto generato ed il suo rapporto tra struttura e presentazione. Indicheremo il contenuto generato con G, e vedremo quando un abuso di quest'ultimo è dannoso alla fruibilità delle pagine web.
Per definizione il contenuto generato viene prodotto dal CSS attraverso l'uso
combinato degli pseudo-elementi :before (b) e :after (a)
e della proprietà 'content'. Quindi non è azzardato scrivere
che:
G ∈ P
Tuttavia l'uso degli pseudo-elementi pone un problema in tale rapporto, in quanto essi sono interpretati dal browser come:
<p> <before>G</before> Contenuto del paragrafo <after>G</after> </p>
Il risultato non è dissimile da quello che otteniamo con JavaScript tramite
document.write, ed infatti il contenuto generato può essere
considerato come una forma di scripting CSS, di cui conserva una traccia nell'uso
di certe funzioni (come 'attr(valore)' o 'counters(contatore)').
Posto che gli pseudo-elementi, all'atto dell'inserimento del contenuto, vengono considerati come elementi non presenti nel sorgente e come unità di memorizzazione del contenuto, si potrebbe giungere alla conclusione secondo cui:
a ∈ S b ∈ S
Quindi, in via ipotetica, anche:
G ∈ S
Questo azzardo è smentito dal fatto che non vi è traccia di tali pseudo-elementi nel sorgente, ma è pur vero che i browser considerino vero tale rapporto all'atto della formattazione della pagina.
Un diagramma ipotetico potrebbe essere il seguente:

Come si evince dalle precedenti considerazioni, l'uso del contenuto generato pone dei problemi a livello di accessibilità alle informazioni della pagina, in quanto:
Queste due considerazioni ci spingono ad approfondire ulteriormente l'argomento, esaminando da vicino alcuni casi di uso e abuso del contenuto generato.
Cominciamo da un semplice esempio:
p.nota:before {
content: "Nota: ";
font-weight: bold;
padding-right: 5px;
}
Questo esempio è stato a lungo citato come un buon uso del contenuto generato. In realtà, se i CSS sono disabilitati o il contenuto generato non è supportato, l'utente non vedrà (e neppure sentirà nel caso dei lettori di schermo) la parola "Nota" prima del paragrafo. Molto meglio adottare una soluzione strutturale in questo caso:
<p class="nota"> <strong>Nota:</strong> ... </p>
Un altro caso è la gestione degli URL nella pagina. Per esempio:
a[href^="http://"]:after {
content: " (URL: " attr(href) " )";
color: #000;
}
Oppure:
li > a[href^="#"]:hover:after {
content: attr(href);
padding-left: 5px;
}
Nel primo caso inseriamo l'URL assoluto dell'elemento A dopo il contenuto
dell'elemento, mentre nel secondo creiamo un effetto dinamico sull':hover inserendo
l'URL relativo di un'ancora interna dopo il contenuto dell'elemento
A (il caso tipico è quello di un sommario di pagina). Come abbiamo
visto in precedenza, queste due soluzioni vengono vanificate dallo scarso supporto
al contenuto generato e dal fatto che l'informazione veicolata non è più
visibile con i CSS disabilitati. Possiamo risolvere il primo caso inserendo strutturalmente
l'URL nella pagina.
Un ulteriore caso si verifica con i contatori. Consideriamo il seguente esempio:
body {counter-reset: capitolo;}
h2:before {
counter-increment: capitolo;
content: "Capitolo " counter(capitolo)":";
}
L'effetto previsto "Capitolo 1:, Capitolo 2:,..." viene vanificato per i motivi visti poc'anzi. Una situazione ancor peggiore si verifica per le liste annidate, in cui tutta la numerazione progressiva viene perduta. Ancora una volta la soluzione strutturale è da preferire.
Un caso estremo lo abbiamo con:
p.image:before {
content: url("img/img.jpg");
float: left;
padding: 3px;
border: 1px solid #000;
margin: 0 5px 5px 0;
}
Qui viene creata un'immagine flottata all'inizio di un paragrafo. Oltre ai problemi
già visti, in questo caso non è possibile utilizzare l'attributo
alt né longdesc per rendere accessibile l'immagine.
Inoltre solo Opera supporta la proprietà 'float' per il contenuto
generato.
Passiamo ora alla "pars aedificans", ossia agli esempi di buon uso del
contenuto generato. Il primo esempio riguarda la gestione delle virgolette sull'elemento
Q:
q:before {
content: no-open-quote;
}
q:after {
content: no-close-quote;
}
È risaputo che Internet Explorer non aggiunge di default le virgolette
di apertura e di chiusura all'elemento Q, mentre Firefox ad esempio
lo fa. Questa diversa interpretazione pone un problema all'atto della formattazione,
in quanto se aggiungiamo le virgolette come entità HTML queste si sovrapporranno
a quelle già inserite dal browser. Tramite contenuto generato possiamo
sopprimere l'inserirmento delle virgolette e risolvere il problema. Tuttavia, inserire
le virgolette tramite la proprietà 'quotes' può essere
controproducente per i motivi visti in precedenza.
Da questo primo esempio possiamo dedurre che un uso sano del contenuto generato si ha quando inseriamo elementi presentazionali la cui omissione non arreca danno alla fruizione delle informazioni della pagina. Un altro esempio:
h2:before, h3:before, h4:before {
content: '\221E';
font-weight: normal;
padding-right: 5px;
color: #000;
background: transparent;
}
body > h2:after,
body > h3:after,
body > h4:after {
content: '\221E';
font-weight: normal;
padding-left: 5px;
color: #000;
background: transparent;
}
In questo esempio inseriamo il simbolo matematico di infinito prima e dopo il contenuto delle intestazioni di secondo, terzo e quarto livello. La sua omissione non toglie nulla all'accessibilità del contenuto di questi elementi. Ancora:
p[id="scarica"]:before {
font-weight: bold;
content: '\2192';
padding-right: 4px;
}
#content > #scarica:hover:before {
content: '\2190';
}
Qui creiamo un effetto di rollover cambiando il simbolo della freccia verso sinistra
con quella verso destra quando l'utente passa col mouse sopra il paragrafo.
L'effetto si può anche ottenere senza contenuto generato con la proprietà
'background'. Anche in questo caso l'omissione del contenuto generato
non toglie nulla alla fruizione del contenuto del paragrafo. Un ultimo esempio:
a[title="Collegamento esterno"]:before {
content: '\20AA';
color: #000;
background: transparent;
padding-right: 3px;
}
In quest'ultimo esempio inseriamo un simbolo prima di un collegamento esterno.
In questo caso l'effetto si può ottenere anche con la proprietà
'background'. Da notare che anche qui l'omissione del contenuto generato è
ininfluente e che l'informazione chiave è veicolata dall'attributo title.
Da quanto abbiamo visto sinora, è lecito concludere affermando che il contenuto generato si rivela utile solo quando le informazioni fornite con esso non sono essenziali alla fruizione della pagina. Un uso diverso è da considerarsi abuso e quindi dannoso.
Inoltre vanno tenute presenti le seguenti considerazioni:
1. L'accessibilità della pagina ha la sua ragion d'essere in una struttura solida e semantica. Fare affidamento su caratteristiche presentazionali può rivelarsi controproducente quando queste caratteristiche non sono disponibili o non sono supportate. Il mito dell'aumento dell'accessibilità tramite contenuto generato è infondato e fuorviante. Nello specifico, il punto 4 delle CSS Techniques for Web Content Accessibility Guidelines 1.0 è completamente errato.
2. Il contenuto generato si basa sulle potenzialità dei CSS che dipendono interamente dal supporto da parte del programma utente o dal fatto che tale supporto sia abilitato o meno. Per una distribuzione sicura del contenuto occorre fare affidamento sulla struttura codificata della pagina e non su tecnologie accessorie.
3. Il contenuto generato è supportato solo da alcuni browser. Nello specifico, Internet Explorer per Windows non lo supporta. Ciò significa che gli utenti di questo browser (o gli utenti con disabilità che si appoggiano ad esso per navigare con lettori di schermo) non avranno accesso alle informazioni veicolate dal contenuto generato.
4. Il contenuto generato potrà avere maggior impatto sui contenuti Web solo nel futuro, quando il suo supporto sarà esteso ad altri browser. In via ipotetica una futura versione di Internet Explorer (forward-compatibility) potrebbe estendere il supporto al contenuto generato, ma tale supporto non sarebbe compatibile con le versioni precedenti (backward-compatibility).