1. Layout con i CSS:
dalla struttura alla realtà

16 marzo 2008 - 18 marzo 2008

2. Introduzione

Nel nostro primo seminario abbiamo visto come convertire un documento da un formato non-(X)HTML al formato (X)HTML. In questo seminario vedremo come modificare il layout di un documento HTML partendo da una struttura molto semplice, che andremo progressivamente a modificare e a formattare con i fogli di stile. Vedremo inoltre come aumentare l'accessibilità del documento fornendo all'utente la possibilità di modificare gli stili della pagina senza dover ricorrere all'interfaccia del browser.

3. Il layout di partenza

Il layout di partenza è costituito da un articolo presente sul sito dell'autore e disponibile in copia locale. Il layout si presenta come mostrato nella seguente immagine.

Il layout di partenza Figura 1: Il layout di partenza [D]

4. La struttura del layout di partenza

Il layout di partenza appare strutturato nelle seguenti sezioni:

  1. il titolo del sito con il logo
  2. un menu di navigazione orizzontale
  3. una sezione "Sei qui"
  4. il motore di ricerca
  5. i contenuti dell'articolo.

Il layout è impaginato su un'unica colonna, ossia è di tipo monolitico.

5. La marcatura del layout di partenza

Il layout di partenza utilizza la seguente DTD:

La marcatura utilizzata nel corpo del documento è la seguente:

  1. <h1>CSS Zibaldone</h1>
  2. <p>
  3. [ <a href="#" title="Vai a Home" accesskey="1">Home</a> ] -
  4. [ <strong>Articoli</strong> ] -
  5. [ <a href="#" title="Vai alle traduzioni" accesskey="3">Traduzioni</a> ] -
  6. [ <a href="#" title="Vai ad altro" accesskey="4">Altro</a> ] -
  7. [ <a href="#" title="Vai agli Appunti sui CSS" accesskey="5">Appunti sui CSS</a> ] -
  8. [ <a href="#" title="Informazioni sull'autore del sito" accesskey="6">L'autore</a> ]
  9. </p>
  10. <p><strong>Sei qui:</strong>
  11. <a href="#">Home</a> &gt;
  12. <a href="#">Articoli</a> &gt;
  13. <strong>Post con stile</strong>
  14. </p>
  15. <form action="http://www.google.com/custom" method="get">
  16. <p><input value="css-zibaldone.com" name="as_sitesearch" type="hidden">
  17. <input value="it" name="hl" type="hidden">
  18. <input type="text" name="q" size="31" maxlength="255" value="">
  19. <input type="submit" name="cmdcerca" value="Cerca"></p>
  20. </form>
  21. <h2>Post con stile</h2>
  22. <p>...</p>
  23. ...omissis
  24. <pre>...</pre>

La marcatura è valida.

6. Analisi della struttura del layout di partenza

La struttura appena vista presenta alcuni vantaggi ed alcuni svantaggi.

Vantaggi

  1. estrema semplicità
  2. chiarezza nella suddivisione delle sezioni
  3. buona navigabilità.

Svantaggi

  1. la mancanza di identificatori o di classi per le sezioni rende difficile la modifica del layout di base
  2. la presenza di tasti di accesso potrebbe confondere i lettori di schermo, sovrapponendosi alle loro combinazioni di tasi predefinite
  3. la presenza di caratteri non necessari a fini presentazionali (come '[' o '&gt' nel menu di navigazione e nella sezione "Sei qui") rappresentano un inutile rumore di fondo per i lettori di schermo
  4. l'ordine con cui sono disposti i contenuti non è ottimale per una buona indicizzazione da parte dei motori di ricerca.

Come si può notare, gli svantaggi superano i vantaggi.

7. Gli stili del layout di partenza

Gli stili del layout di partenza sono i seguenti:

  1. body {
  2. font-family: Helvetica, Arial, sans-serif;
  3. font-size: 100.01%;
  4. color: #000;
  5. background: #fff;
  6. line-height: 1.5;
  7. margin-left: 2em;
  8. margin-right: 2em;
  9. }
  10. h1, h2, h3, h4, h5, h6 {
  11. line-height: normal;
  12. }
  13. h1 {
  14. margin: 0;
  15. padding-bottom: 0.2em;
  16. background: transparent url("../img/logo.png") no-repeat top right;
  17. color: #000;
  18. font-family: "Arial Black", Arial, sans-serif;
  19. font-size: 3em;
  20. text-transform: uppercase;
  21. }
  22. h2 {
  23. border-bottom: 1px dashed #000;
  24. }
  25. a:link, a:visited {
  26. color: #00c;
  27. background: transparent;
  28. }
  29. a:hover {
  30. color: #00f;
  31. background: transparent;
  32. }
  33. a img {border: 1px solid #fff;}
  34. a:hover img {border-color: #f00;}
  35. *:focus {outline-style: none;}
  36. blockquote {
  37. padding-left: 0.5em;
  38. border-left: 0.5em solid #ccc;
  39. }
  40. address {
  41. margin: 1em 0;
  42. }
  43. ul {
  44. list-style: disc;
  45. }
  46. ul ul {
  47. list-style: circle;
  48. margin-top: 0;
  49. margin-bottom: 0;
  50. }
  51. ul ul ul {
  52. list-style: square;
  53. margin-top: 0;
  54. margin-bottom: 0;
  55. }
  56. ol ol {
  57. list-style: upper-roman;
  58. margin-top: 0;
  59. margin-bottom: 0;
  60. }
  61. ol ol ol {
  62. list-style: lower-roman;
  63. margin-top: 0;
  64. margin-bottom: 0;
  65. }
  66. dl {
  67. padding: 1em;
  68. border: 1px solid #000;
  69. }
  70. dt {
  71. margin-left: 2.5em;
  72. display: list-item;
  73. list-style-type: square;
  74. }
  75. dl dl.highlight {
  76. padding: 0.8em;
  77. }
  78. table {
  79. border-collapse: collapse;
  80. border-spacing: 0;
  81. border: 1px solid #000;
  82. font-size: 1em;
  83. }
  84. caption {
  85. margin: 0;
  86. padding: 0.5em 0;
  87. text-align: center;
  88. font-weight: bold;
  89. font-variant: small-caps;
  90. }
  91. td {
  92. border: 1px solid #000;
  93. padding: 0.4em;
  94. vertical-align: middle;
  95. text-align: left;
  96. }
  97. th {
  98. border: 1px solid #000;
  99. padding: 0.4em;
  100. vertical-align: middle;
  101. text-align: center;
  102. font-weight: bold;
  103. }
  104. table.property {
  105. border: none;
  106. background: #def;
  107. color: #000;
  108. }
  109. table.property caption {
  110. text-align: left;
  111. font-variant: normal;
  112. background: #005a9c;
  113. color: #fff;
  114. }
  115. table.property td, table.property th {
  116. border: none;
  117. }
  118. table.property th {
  119. text-align: left;
  120. }
  121. pre, code, samp, kbd {
  122. font: 1em "Andale Mono", "Courier New", Courier, monospace;
  123. }
  124. pre {
  125. background: #e5ecf3;
  126. color: #000;
  127. }
  128. q:before {
  129. content: no-open-quote;
  130. }
  131. q:after {
  132. content: no-close-quote;
  133. }
  134. em, cite, dfn {
  135. font-style: normal;
  136. font-weight: bold;
  137. }
  138. abbr, acronym {
  139. cursor: help;
  140. border-bottom: 1px dashed #000;
  141. font-variant: small-caps;
  142. }
  143. img.wide {
  144. width: 100%;
  145. }
  146. form {
  147. margin: 0;
  148. padding: 0;
  149. }
  150. /* various */
  151. .summary {
  152. list-style: none;
  153. }
  154. .css {
  155. color: #363688;
  156. background: transparent;
  157. }
  158. .html {
  159. color: #900;
  160. background: transparent;
  161. }
  162. .left {
  163. float: left;
  164. margin: 0.2em 0.4em 0 0;
  165. }
  166. p.date {font-style: italic;}
  167. .important {background: #ffc; color: #000;}
  168. /* stolen from Gecko XML parsing error */
  169. .error {
  170. background: #ffffe0;
  171. color: #000;
  172. font-weight: bold;
  173. border: 1px inset;
  174. border-color: #800 #ffb2b2 #ffb2b2 #800;
  175. }
  176. .error .code {color: #d00; background: transparent;}

Ci soffermiamo solo su alcune caratteristiche interessanti:

  1. il layout è elastico, in quanto i margini laterali dell'elemento body sono stati impostati in em (righe 7-8)
  2. il logo è stato impostato come sfondo dell'elemento h1 (riga 16)
  3. è stato eliminato il focus dagli elementi, che alcuni browser rendono con un contorno tratteggiato (proprietà outline) (riga 35)
  4. gli elementi dt vengono visualizzati come elementi di un elenco non ordinato, tramite i valori list-item della proprietà display e square della proprietà list-style-type (righe 72-73).

8. Analisi degli stili del layout di partenza

Gli stili visti in precedenza presentano alcuni vantaggi ed alcuni svantaggi.

Vantaggi

  1. il layout è flessibile e leggibile
  2. il contrasto di colore è corretto
  3. il peso del foglio di stile è ridotto (l'autore usa fogli di stile extra per i documenti che lo richiedono).

Svantaggi

  1. il codice in alcuni punti è confuso
  2. il codice in alcuni punti è ridondante
  3. l'uso delle classi non è sempre corretto
  4. l'aspetto finale del sito non si attesta su un livello accettabile di design.

Come si può notare, gli svantaggi superano i vantaggi.

9. Cosa fare

Per procedere alla trasformazione di questo layout dobbiamo operare su due livelli:

  1. marcatura
  2. stili.

10. Operare sulla marcatura

Poichè nel nostro layout di partenza i contenuti venivano all'ultimo posto, nel layout che vogliamo ottenere sposteremo i contenuti in avanti. Per fare questo, creeremo un layout a due colonne, inserendo il menu di navigazione ed il motore di ricerca nella colonna laterale, che verrà dopo i contenuti nel sorgente. Alla fine della pagina inseriremo un piè di pagina a chiusura del nostro layout.

Come abbiamo visto nel precedente seminario, per abituarci ad una migliore correttezza formale, useremo la DTD XHTML 1.1 e serviremo il nostro documento come application/xhtml+xml. Parallelamente, osserveremo i nostri progressi in un secondo documento servito come text/html e avente lo stesso DOCTYPE del documento originale di partenza. Si ricorda che per i file statici l'estensione dovrà essere .xht o .xhtml per il primo tipo ed .html (e simili) per il secondo.

Quindi inizieremo il nostro nuovo documento scrivendo:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "
  3. http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="it">
  5. <head>
  6. <title>Layout a due colonne</title>
  7. <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
  8. ...omissis
  9. </head>

Usiamo la codifica UTF-8 per sfruttare al massimo la gamma di caratteri esistenti sul Web, avendo così a disposizione un insieme molto più vasto della tradizionale codifica ISO-8859-1. Questo ci permette di affrontare una futura internazionalizzazione delle nostre pagine con minore ansia.

La marcatura per il contenuto effettivo del nostro documento sarà quindi:

  1. <div id="wrapper">
  2. <div id="header"><h1>CSS Zibaldone</h1></div>
  3. <div id="top">
  4. <ul id="breadcrumbs">
  5. <li><strong>Sei qui:</strong></li>
  6. <li><a href="#">Home</a></li>
  7. <li><a href="#">Articoli</a></li>
  8. <li><strong>Post con stile</strong></li>
  9. </ul>
  10. <p id="change-style"><a href="#">Layout accessibile</a>
  11. <a href="#">Normale</a></p>
  12. </div>
  13. <div id="content">
  14. <div id="gutter">
  15. <h2>Post con stile</h2>
  16. <p>...</p>
  17. ...omissis...
  18. <ol class="code">
  19. <li><code>.post {</code></li>
  20. <li class="indent1"><code>width: 65%;</code></li>
  21. <li class="indent1"><code>margin: 0;</code></li>
  22. <li class="indent1"><code>font-size: 80%;</code></li>
  23. <li class="vspace"><code>}</code></li>
  24. ...omissis
  25. </ol>
  26. </div>
  27. </div>
  28. <div id="sidebar">
  29. <div id="navcontainer">
  30. <ul id="nav">
  31. <li><a href="#">Home</a></li>
  32. <li><strong>Articoli</strong></li>
  33. <li><a href="#">Traduzioni</a></li>
  34. <li><a href="#">Altro</a></li>
  35. <li><a href="#">Appunti sui CSS</a></li>
  36. <li><a href="#">L'autore</a></li>
  37. </ul>
  38. </div>
  39. <form action="http://www.google.com/custom" method="get">
  40. <p><input value="css-zibaldone.com" name="as_sitesearch" type="hidden" />
  41. <input value="it" name="hl" id="hl" type="hidden" />
  42. <input type="text" name="q" id="q" size="31" maxlength="255" value="" />
  43. <input type="submit" name="cmdcerca" id="cmdcerca" value="Cerca" /></p>
  44. </form>
  45. </div>
  46. <address>Gabriele Romanato</address>
  47. </div>

Possiamo verificare il lavoro svolto sinora nella versione XHTML e nella versione HTML del nostro documento.

11. Analisi della marcatura prodotta

Analizziamo in dettaglio la marcatura creata per il nuovo layout del documento.

  1. utilizziamo il contenitore generale #wrapper per contenere l'intero layout della pagina
  2. l'intestazione è costituita dall'elemento #header e dal suo figlio h1
  3. al di sotto dell'elemento #header troviamo l'elemento #top, che contiene:
    1. la sezione "Sei qui" (elemento #breadcrumbs)
    2. i link per il cambio di stile della pagina (elemento #change-style).
  4. viene quindi il contenuto effettivo della pagina (elemento #content), al cui interno troviamo:
    1. un elemento spaziatore (#gutter), secondo una nota tecnica usata da Dan Cederholm nel suo recente Bulletproof Webdesign
    2. il titolo dell'articolo (elemento h2)
    3. vari paragrafi di testo
    4. un elenco ordinato con classe .code che contiene il codice di esempio usato nell'articolo.
  5. dopo il contenuto viene la colonna laterale (elemento #sidebar), che contiene i seguenti elementi:
    1. un contenitore per il menu di navigazione (elemento #navcontainer)
    2. il menu di navigazione (elemento #nav)
    3. il motore di ricerca.
  6. a chiudere la pagina troviamo l'elemento address, che reca il nome dell'autore del documento e funge da piè di pagina.

Alcuni punti sono interessanti:

12. Operare sugli stili

Una volta ottenuta l'intelaiatura di base del documento, occorre cominciare a ragionare sugli stili da adottare. Riassumiamo quello che vogliamo ottenere:

  1. un layout fluido a due colonne, con intestazione e piè di pagina
  2. un design che riesca almeno a far definire il sito "carino".

Ragioniamo sul primo punto e poniamoci delle domande:

  1. Domanda: Come posizionare gli elementi?

    Risposta: Attualmente possiamo scegliere tra il float ed il posizionamento assoluto. Il posizionamento assoluto ha l'indubbio vantaggio di prescindere dall'ordine nel sorgente, ma ha anche il noto svantaggio di dipendere dalla quantità di contenuto presente sulla pagina, e questo diventa problematico nel caso di un sito dinamico. Il float dal canto suo dipende dall'ordine nel sorgente, ma è più flessibile rispetto al posizionamento assoluto. Volendo dare al nostro documento la maggiore applicabilità in àmbiti diversi, scegliamo di usare il float.

  2. Domanda: Come ottenere la fluidità degli elementi sullo schermo?

    Risposta: Scegliamo di usare misure in percentuale per gli elementi.

  3. Domanda: Useremo immagini come sfondo degli elementi?

    Risposta: Si, per il motivo elencato al punto 2.

  4. Domanda: Applicheremo la fluidità anche ai font?

    Risposta: Si, è indispensabile per ottenere un layout a misura di utente.

  5. Domanda: Forniremo layout alternativi?

    Risposta: Si, un layout a contrasto di colore invertito per gli utenti con problemi visivi.

Il secondo punto è più problematico, perché implica una riflessione quasi filosofica sul divario tra essere e apparire. Noi decidiamo di conciliare le due cose tenendo presente che:

  1. un buon design può anche essere accessibile
  2. un sito scarno esteticamente non implica un minore successo, ma per abbracciare il maggior pubblico possibile, è bene pensare al design.

Passiamo quindi a costruire il nostro layout seguendo un approccio top-down, ossia partendo dagli stili di base più generali fino ad arrivare a quelli delle specifiche sezioni del documento.

13. Considerazioni preliminari

Immaginiamo di dover dipingere un quadro. Le prime due cose di cui dobbiamo occuparci sono i colori di base e le proporzioni del dipinto. Per i colori di base, dobbiamo solo assicurarci che il contrasto tra colore di sfondo e di primo piano soddisfi i requisiti del W3C. Per il resto, siamo liberi di assecondare la nostra fantasia. Per le proporzioni, invece, dobbiamo operare dei calcoli precisi per fare in modo che i contenuti trovino spazio sulla pagina. Spazio è la parola chiave. Il nostro layout fluido dovrà adattarsi alle varie risoluzioni di schermo senza mostrare sovrapposizioni di elementi o la comparsa della temuta barra di scorrimento orizzontale. Poiché useremo misure in percentuale, dobbiamo tenere presente che:

  1. la percentuale si riferisce sempre alla larghezza dell'elemento genitore.
  2. nel nostro caso, si parte dalla larghezza base del 100%
  3. quando calcoliamo la larghezza percentuale di un elemento, dobbiamo sempre chiederci qual'è la larghezza del suo genitore.

Qui entra in gioco il box model dei CSS e i calcoli che ne derivano. In breve:

  1. i margini orizzontali, il padding orizzontale o i bordi destro e sinistro di un elemento si sommano alla larghezza espressa esplicitamente tramite la proprietà width. Per esempio, supponendo di avere i seguenti elementi di blocco:

    1. #box {
    2. width: 50%;
    3. }
    4. #box #child {
    5. width: 100%;
    6. padding: 1em;
    7. }

    Nei browser che rispettano il box model standard, l'elemento #child fuoriuscirà dal suo genitore, perché la seconda regola fa in modo che tale elemento occupi tutta la larghezza del suo genitore, più 2em complessivi per il padding destro e sinistro.

    Se lo scopo della seconda regola era quello di lasciare dello spazio tra i contenuti del box figlio e il suo genitore, allora si sarebbe potuto scrivere solo:

    1. #box #child {
    2. padding: 1em;
    3. }

    Così facendo il box figlio coinciderà ma non supererà il suo genitore, in quanto la larghezza complessiva del blocco contenitore (l'elemento #box) resterà inalterata

  2. per la proprietà height vale quanto detto per i calcoli della proprietà width, ma stavolta la somma va fatta tenendo presente i margini e il padding verticali e i bordi superiore ed inferiore.

Stabilite queste norme, dobbiamo decidere quale dimensione assegnare agli elementi della nostra pagina. Tenendo presente che si dovrebbe comunque garantire una certa leggibilità evitando una lunghezza di riga eccessiva, stabiliamo che:

  1. l'intestazione, il piè di pagina, e la sezione "Sei qui" occuperanno tutta la larghezza del documento
  2. i contenuti occuperanno il 70% del documento
  3. la colonna laterale occuperà il 30% del documento.

Detto questo, passiamo a vedere in dettaglio il layout dei vari elementi.

14. Gli stili generali

Passiamo quindi ad esaminare gli stili generali che daremo al nostro layout.

  1. /* Dichiarazioni generali */
  2. body {
  3. margin: 0;
  4. padding: 0;
  5. font: 100.01%/1.5 Helvetica, Arial, sans-serif;
  6. background: #fff url("img/col-dx.gif") repeat-y 70% 0;
  7. color: #000;
  8. }
  9. a:link, a:visited {
  10. color: #00c;
  11. background: transparent;
  12. }
  13. a:hover {
  14. color: #c00;
  15. background: transparent;
  16. }
  17. acronym {
  18. border-bottom: 1px dashed #333;
  19. cursor: help;
  20. }
  21. code {
  22. font: 1em Courier, monospace;
  23. }

Soffermiamoci sulle dichiarazioni date all'elemento body:

A questo punto occorre evidenziare un'importante differenza esistente tra il nostro documento servito come application/xhtml+xml e lo stesso documento servito come text/html. La differenza viene riassunta nelle due immagini che seguono.

L'immagine di sfondo in HTML L'immagine di sfondo in XHTML Figure 2-3: L'immagine di sfondo in HTML (a sinistra) e in XHTML (a destra) [D]

Nella prima figura abbiamo il documento servito come text/html. In questo caso l'elemento body viene trattato in modo speciale dai browser, nel senso che questo elemento copre interamente lo sfondo dell'elemento html, ossia dell'elemento radice. In altre parole, body "ruba" lo sfondo dell'elemento radice.

Nella seconda figura abbiamo il documento servito come application/xhtml+xml. In questo caso lo spazio bianco è giustificato dal fatto che ora body viene considerato come un elemento qualsiasi, ed il "furto" dello sfondo non ha più luogo. Poichè l'elemento h1 ha dei margini verticali, i browser ritengono che si venga a creare dello spazio tra l'elemento radice e body. Tale spazio viene mostrato.

Come ovviare al problema? La soluzione più semplice è quella di specificare l'immagine di sfondo anche per l'elemento html, usando la stessa dichiarazione usata per l'elemento body. Nel nostro caso questa soluzione non è necessaria, perché quello spazio sarà colmato dall'intestazione del nostro layout.

Possiamo osservare il lavoro svolto sinora nel nostro documento XHTML e nel nostro documento HTML.

15. Il contenitore generale

Gli stili del contenitore generale sono i seguenti:

  1. /* Contenitore principale */
  2. #wrapper {
  3. margin: 0;
  4. width: 100%;
  5. font-size: 90%;
  6. }

La larghezza del contenitore generale è ora pari al 100% della finestra di visualizzazione. La dimensione dei font è stata qui ridotta del 10%. A questo proposito occorre citare la riflessione di Franco Frascolla in merito alla necessità che la dimensione dei font non sia inferiore al 100%/1em. Questa riflessione in generale è valida, ma occorre fare alcune precisazioni in sede di design:

  1. una dimensione pari al 100% può essere ottimale se il contenitore del testo ha una larghezza tale da non creare interruzioni di riga eccessive
  2. la dimensione del font, quindi, dovrebbe essere proporzionale alla dimensione del contenitore.

La dimensione del contenitore del testo nel layout originale era tale da consentire l'uso del valore 100%/1em. Nel nostro caso la colonna dei contenuti avrà una dimensione pari al 70% della finestra di visualizzazione. In questo caso la scelta di ridurre il font ci appare ragionevole, tenendo anche presente che:

  1. l'utente può ridimensionare i font
  2. verrà fornito un layout alternativo.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

16. L'intestazione

Passiamo quindi ad assegnare le regole di stile all'intestazione del nostro documento:

  1. /* Intestazione */
  2. #header {
  3. background: #fff url("img/header.jpg") no-repeat 0 0;
  4. width: 100%;
  5. margin: 0;
  6. border-bottom: 1px solid #bccad9;
  7. }
  8. #header h1 {
  9. font: 3em/normal "Arial Black", Arial, sans-serif;
  10. padding: 0.2em 0;
  11. text-indent: 0.2em;
  12. text-transform: uppercase;
  13. margin: 0;
  14. background: transparent url("img/logo.gif") no-repeat 100% 50%;
  15. }

Passiamo in rassegna i nostri stili:

  1. Righe 2-7: Applichiamo un colore ed un'immagine di sfondo all'elemento principale della nostra intestazione. Il colore di sfondo fa in modo che nella versione XHTML scompaia lo spazio bianco creatosi tra l'elemento radice e l'elemento body. L'immagine di sfondo è allineata in alto a sinistra (coordinate 0, 0) e non viene ripetuta. La larghezza dell'elemento #header coincide con quella della finestra di visualizzazione. Abbiamo applicato anche un bordo inferiore
  2. Righe 8-15: Diamo quindi gli stili al titolo di primo livello all'interno dell'intestazione. Impostiamo una grandezza del font pari a tre volte quella dell'elemento genitore, normalizziamo l'interlinea e scegliamo un tipo di font abbastanza comune (Arial Black), dando comunque una scelta di ripiego (famiglia generica sans-serif). Quindi impostiamo un padding verticale ed un indentazione del testo pari a 0.2em. Questo valore viene calcolato a partire dai 3em dell'elemento h1. Azzeriamo i margini dell'elemento e gli assegniamo un'immagine di sfondo posta alla sua destra e centrata in verticale (coordinate 100%, 50%). Il colore di sfondo del titolo è trasparente, in modo da non coprire lo sfondo del suo genitore.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

17. La sezione "Sei qui" e lo style switcher

Tocca ora alla sezione "Sei qui" e allo style switcher. Decidiamo di raggrupparli all'interno di un unico elemento e di farli apparire l'uno a sinistra e l'altro a destra. Gli stili saranno:

  1. /* Sezione "Sei qui" e style switcher */
  2. #top {
  3. margin: 0;
  4. border-bottom: 1px solid #bccad9;
  5. height: 1.4em;
  6. line-height: 1.4em;
  7. background: #fff;
  8. color: #000;
  9. }
  10. #breadcrumbs {
  11. margin: 0;
  12. padding: 0 0 0 1em;
  13. height: 1.4em;
  14. line-height: 1.4em;
  15. float: left;
  16. }
  17. #breadcrumbs li {
  18. float: left;
  19. display: block;
  20. height: 1.4em;
  21. line-height: 1.4em;
  22. padding-right: 0.5em;
  23. }
  24. #breadcrumbs a:link,
    #breadcrumbs a:visited,
    #breadcrumbs a:hover {
  25. display: block;
  26. color: #008;
  27. background: transparent url("img/freccia.gif") no-repeat 100% 50%;
  28. padding-right: 1em;
  29. }
  30. #change-style {
  31. margin: 0;
  32. padding-right: 1em;
  33. text-align: right;
  34. height: 1.4em;
  35. line-height: 1.4em;
  36. float: right;
  37. }
  38. #change-style a {
  39. padding-left: 0.5em;
  40. }

Vediamo in dettaglio i nostri stili:

  1. Righe 2-9: L'elemento #top va a contenere le sezioni "Sei qui" e lo style switcher. Abbiamo impostato un'altezza uguale all'interlinea per 1) contenere i float che andremo ad usare (valore proprietà height) e 2) centrare il testo in verticale all'interno degli elementi (valore proprietà line-height = valore proprietà height). Grazie a questa dichiarazione, la semiinterlinea sarà uguale a 0.7em sopra e sotto il testo, il quale verrà centrato in verticale
  2. Righe 10-23: Facciamo flottare l'elemento #breadcrumbs a sinistra, ma non ne impostiamo la larghezza, in modo che in questo caso venga applicato l'algoritmo shrink-to-fit. Tale algoritmo fa in modo che la larghezza del float sia sufficiente per ospitare il suo contenuto, avendo così un float che si adatta al suo contenuto. Si noti che abbiamo ripetuto le dichiarazioni di altezza e di interlinea impostate in precedenza. Anche le voci dell'elenco sono state flottate a sinistra, e anche per loro abbiamo la stessa altezza e la stessa interlinea, più un padding destro per distanziare le voci
  3. Righe 24-29: I link all'interno del menu vengono dichiarati di blocco, in modo da non incorrere in problemi con Internet Explorer al momento di applicare l'immagine di sfondo. Tale immagine rappresenta il divisore all'interno del percorso, e va a sostituire i segni di maggiore usati nel layout originale. L'immagine è posizionata a destra del testo dei link e centrata verticalmente (coordinate 100%, 50%). Viene distanziata dal testo dei link tramite un padding destro pari ad 1em
  4. Righe 30-40: Lo style switcher viene fatto flottare a destra. Anche per questo elemento ripetiamo le dichiarazioni di altezza e di interlinea, e lasciamo che venga applicato l'algoritmo shrink-to-fit nel computo della sua larghezza. I link al suo interno vengono distanziati tra loro tramite un padding sinistro pari a 0.5em.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

18. Il posizionamento e la prima formattazione dei contenuti

Passiamo quindi a dare i primi stili ai contenuti:

  1. /* Contenuti */
  2. #content {
  3. float: left;
  4. margin: 0;
  5. width: 70%;
  6. }
  7. /* Elemento spaziatore */
  8. #gutter {
  9. padding: 1em 1em 0 1em;
  10. }

L'elemento #content è stato fatto flottare a sinistra e gli è stata assegnata una larghezza pari al 70% della superficie di visualizzazione. Abbiamo annullato i suoi margini per evitare che i browser assegnino dei valori extra al momento del floating. L'elemento #gutter funge da spaziatore tra i contenuti e la colonna laterale, tramite un padding destro pari ad 1em. Il padding superiore (1em) serve ad evitare problemi nel computo dei margini verticali tra tale elemento e i suoi figli di blocco.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

19. Intestazioni e paragrafi

Formattiamo quindi le intestazioni e i paragrafi all'interno dei contenuti:

  1. #content h2 {
  2. margin: 0;
  3. padding: 0;
  4. font: 1.6em/normal "Arial Narrow", Arial, sans-serif;
  5. color: #800;
  6. background: transparent url("img/plugin.gif") no-repeat 0 50%;
  7. text-indent: 1em;
  8. border-bottom: 1px dashed #999;
  9. }
  10. #content p {
  11. margin: 0;
  12. padding: 0.5em 0;
  13. }

Il titolo dell'articolo ha un font Arial Narrow di colore rosso scuro con una dimensione pari ad 1.6em. La sua interlinea è stata normalizzata in modo da evitare che ci crei spazio tra il testo ed il bordo sottostante. L'elemento ha un'immagine di sfondo posta alla sua sinistra e centrata in verticale (coordinate 0 50%). L'indentazione serve a creare dello spazio tra l'immagine ed il testo del titolo. I paragrafi usano il solo padding verticale, al fine di evitare alcuni problemi inerenti al computo dei margini verticali collassati.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

20. I blocchi di codice

Passiamo quindi alla formattazione dei blocchi di codice, ricordando che abbiamo scelto di usare un elenco ordinato in luogo dell'elemento pre, in quanto:

  1. tale elemento non garantisce un controllo preciso sul testo in caso di ridimensionamento della finestra di visualizzazione o di ingrandimento del testo
  2. non è semanticamente l'elemento più appropriato.

All'interno delle voci dell'elenco useremo l'elemento code, che è sicuramente più indicato a livello semantico. Gli stili sono i seguenti:

  1. ol.code {
  2. margin-left: 0;
  3. padding: 0.3em;
  4. border: 1px solid #999;
  5. }
  6. ol.code li {
  7. display: block;
  8. background: #ffe;
  9. color: #ffe;
  10. margin: 2px 0;
  11. padding: 0.25em;
  12. border-bottom: 1px solid #999;
  13. }
  14. ol.code li code {
  15. color: #000;
  16. }
  17. ol.code li.indent1 {
  18. text-indent: 2em;
  19. }
  20. ol.code li.vspace {
  21. margin-bottom: 0.5em;
  22. }
  1. Righe 1-5: all'elenco ordinato viene assegnata la classe .code. Il suo rientro viene annullato, gli viene assegnato un padding su tutti i lati ed un bordo
  2. Righe 6-13: le voci dell'elenco vengono dichiarate di blocco per sopprimere il marcatore di elenco senza ricorrere alla dichiarazione list-style: none. Per rendere lo stile compatibile anche con Internet Explorer 7 ed inferiori si imposta il colore di sfondo sullo stesso valore del colore del testo, eliminando la visualizzazione del marcatore. Questa dichiarazione viene poi sovrascritta sull'elemento code (righe 14-16)
  3. Righe 17-22: Vengono create due classi per gestire l'indentazione del codice (classe .indent1) e l'eventuale spazio verticale tra le righe del codice (classe .vspace). Si noti che per l'indentazione si può usare anche un padding sinistro, particolarmente indicato se una riga di codice viene spezzata su due righe.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

21. Il posizionamento della colonna laterale

Passiamo quindi a posizionare a destra la colonna laterale:

  1. /* Colonna laterale */
  2. #sidebar {
  3. float: right;
  4. width: 30%;
  5. margin: 0;
  6. }

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

22. La prima formattazione del menu di navigazione

Diamo quindi i primi stili al nostro menu di navigazione:

  1. #sidebar #navcontainer {
  2. margin: 1em auto;
  3. width: 90%;
  4. background: #fff url("img/sup-sx.gif") no-repeat top left;
  5. }
  6. #sidebar #nav {
  7. margin: 0;
  8. width: 100%;
  9. padding: 0;
  10. background: transparent url("img/inf-dx.gif") no-repeat bottom right;
  11. color: #000;
  12. }

Centriamo il contenitore esterno del menu di navigazione (#navcontainer) tramite margini orizzontali automatici e gli assegniamo una larghezza pari al 90% della colonna laterale. Quindi posizioniamo un'immagine di sfondo in alto a sinistra. Questa immagine andrà a formare l'angolo arrotondato superiore del menu.

A questo punto passiamo all'elenco non ordinato (#nav). Annulliamo i suoi margini e il suo padding e gli assegniamo un larghezza pari a quella del suo genitore. Quindi posizioniamo un'immagine di sfondo sulla parte inferiore destra dell'elemento. Questa immagine andrà a formare l'angolo arrotondato inferiore del menu. Si noti come il colore di sfondo di questo elemento sia trasparente, in modo da non coprire l'immagine di sfondo del suo genitore.

La centratura orizzontale tramite margini automatici non è compatibile con Internet Explorer 5. A questo proposito dovremmo:

  1. dare la dichiarazione text-align: center sull'elemento #navcontainer
  2. ripristinare l'allineamento tramite text-align: left sull'elemento #nav.

Si noti infine come le dichiarazioni di larghezza siano sempre esplicite. Questo ci permette di evitare i noti problemi con alcune versioni di Internet Explorer.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

23. Menu di navigazione a blocchi

Il menu di navigazione che andremo a formattare è un menu verticale a blocchi. Scegliamo di usare un indicatore per la sezione corrente ed un rollover per i link attivi. Gli stili saranno:

  1. #sidebar #nav li {
  2. display: block;
  3. color: #fff;
  4. width: 100%;
  5. margin: 0;
  6. padding: 0.5em 0;
  7. }
  8. #sidebar #nav strong {
  9. display: block;
  10. text-indent: 1.5em;
  11. width: 100%;
  12. color: #000;
  13. background: transparent url("img/freccia.gif") no-repeat 0 50%;
  14. text-transform: uppercase;
  15. }
  16. #sidebar #nav a:link,
    #sidebar #nav a:visited {
  17. display: block;
  18. width: 100%;
  19. text-indent: 1.5em;
  20. }
  21. #sidebar #nav a:hover {
  22. background: #f7f7f5 url("img/go.gif") no-repeat 0 50%;
  23. }
  1. Righe 1-7: le voci dell'elenco vengono rese di blocco. Per nascondere il marcatore anche in Internet Explorer 7 ed inferiori impostiamo un colore del testo uguale a quello di sfondo
  2. Righe 8-15: l'elemento strong svolge qui la funzione di marcare la sezione corrente. Viene quindi reso di blocco e gli viene assegnata una particolare immagine di sfondo posta a sinistra e centrata in verticale (coordinate 0, 50%). Il testo viene reso in maiuscolo ed indentato di 1.5em
  3. Righe 16-24: I link all'interno del menu vengono resi di blocco ed il loro testo viene indentato della stessa misura usata sull'elemento strong. Sullo stato :hover viene modificato il colore di sfondo ed assegnata un'immagine di sfondo posta a sinistra e centrata in verticale.

Si noti la ridondanza di dichiarazioni relative alla larghezza degli elementi, necessarie per evitare problemi in Internet Explorer 6 ed inferiori. Si noti anche come si sia evitato il preload delle immagini sul rollover, dato il peso irrisorio di queste ultime (pochi bytes).

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

24. Il motore di ricerca

Il motore di ricerca presenta i seguenti stili:

  1. #sidebar form {
  2. margin: 0 auto;
  3. width: 90%;
  4. }
  5. #sidebar form p {
  6. margin: 0;
  7. }
  8. #sidebar form input#q {
  9. width: 50%;
  10. background: #fff;
  11. color: #333;
  12. border: 1px solid;
  13. font: 1em Helvetica, Arial, sans-serif;
  14. }
  15. #sidebar form input#cmdcerca {
  16. font: bold 1em Helvetica, Arial, sans-serif;
  17. }

Come il menu di navigazione, il modulo viene centrato in orizzontale tramite i margini automatici e gli viene asssegnata la stessa larghezza del menu. I margini verticali del modulo e del paragrafo al suo interno vengono azzerati, onde evitare i noti problemi di Internet Explorer 6 nel computo dei margini degli elementi dei moduli. Poiché abbiamo assegnato due ID differenti al campo di testo e al bottone di invio, essi ricevono due stili diversi. Il primo ha una larghezza pari al 50% della larghezza del modulo ed un bordo nero, mentre il secondo ha il testo in grassetto. Poiché un fattore fondamentale nel computo delle dimensioni degli elementi dei moduli è costituito dal tipo di font scelto e dalla sua dimensione, impostiamo lo stesso tipo di font e la stessa dimensione per tali elementi. Ricordiamo che attualmente i browser applicano l'ereditarietà in modo diverso sugli elementi dei moduli. Si rende quindi necessario specificare il tipo e la dimensione del font su ogni elemento.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

25. Il piè di pagina

Infine, posizioniamo il piè di pagina sotto i contenuti e la colonna laterale, assegnandogli i seguenti stili:

  1. /* Piè di pagina */
  2. address {
  3. clear: both;
  4. width: 100%;
  5. margin: 0;
  6. font-style: normal;
  7. font-weight: bold;
  8. font-size: 110%;
  9. background: #fff url("img/footer.gif") no-repeat 100% 50%;
  10. text-align: center;
  11. color: #000;
  12. border-top: 1px solid #bccad9;
  13. text-transform: uppercase;
  14. height: 3em;
  15. line-height: 3em;
  16. }

La prima dichiarazione riguarda la proprietà clear e serve a ripristinare il flusso normale del documento dopo i float. Poiché gli elementi sono flottati in entrambe le direzioni usiamo qui il valore both. I margini verticali dell'elemento vengono annullati, poiché il computo di tali margini con la proprietà clear sono diversi da browser a browser. Assegniamo una larghezza esplicita all'elemento per evitare alcuni problemi con Internet Explorer 6 ed inferiori. Centriamo quindi il testo in orizzontale ed in verticale, assegnandogli una dimensione superiore al normale. Per centrare il testo in verticale abbiamo usato la stessa tecnica vista in precedenza per la sezione "Sei qui". Poiché l'elemento avrà un'immagine di sfondo posizionata in basso a destra (coordinate 100%, 50%), la sua altezza dovrà essere proporzionale alle dimensioni dell'immagine.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

26. Il codice JavaScript dello style switcher

Il codice JavaScript dello style switcher è tratto dall'articolo presente all'indirizzo http://www.alistapart.com/articles/alternate. La soluzione JavaScript è da considerarsi come un ripiego se non si ha la possibilità di usare un più sicuro codice lato server, come PHP (si veda in tal senso quanto scritto da Gianluca Troiani in CSS. Guida completa o si vada all'indirizzo http://css-discuss.incutio.com/?page=StyleSwitching).

Nello specifico, il codice JavaScript compie le seguenti operazioni:

  1. individua ricorsivamente tutti gli elementi link presenti nel documento
  2. verifica che questi elementi siano dei fogli di stile e che abbiano un titolo
  3. verifica che i fogli di stile siano abilitati o meno
  4. disabilita lo stile corrente ed imposta lo stile alternativo, tramite un semplice costrutto if
  5. crea un cookie per registrare la preferenza di stile scelta
  6. imposta la data di scadenza del cookie in modo che questa duri anche quando si chiude la sessione del browser, a meno che l'utente non abbia impostato la rimozione totale dei cookie a fine sessione
  7. associa il cookie al cambio di stile.

Occorre quindi modificare la nostra marcatura come segue:

  1. <link rel="stylesheet" href="demo.css" type="text/css" media="screen" title="Normale" />
  2. <link rel="alternate stylesheet" href="alternate.css" type="text/css" media="screen" title="Accessibile" />

Nel corpo del documento apporteremo le seguenti modifiche:

  1. <p id="change-style">
  2. <a href="#" onclick="setActiveStyleSheet('Accessibile'); return false;">Layout accessibile</a>
  3. <a href="#" onclick="setActiveStyleSheet('Normale'); return false;">Normale</a>
  4. </p>

Alcuni autori associano anche il metodo location.reload() al precedente codice. Se ne sconsiglia l'uso in quanto aggiungerebbe un inutile refresh alla pagina.

Possiamo osservare i nostri progressi nel nostro documento XHTML e nel nostro documento HTML.

27. Note sul layout accessibile

Il layout accessibile usato nel nostro esempio si rivolge soprattutto alle persone ipovedenti e a quegli utenti che possono trarre beneficio da un contrasto di colori invertito. Nello specifico, esso presenta le seguenti caratteristiche:

  1. tutte le immagini di sfondo sono state eliminate
  2. il testo è stato ingrandito del 180%
  3. i colori sono stati ridotti a combinazioni web safe (#0ff, #ff0, ecc.)

La struttura a due colonne è stata mantenuta, anche se si può linearizzare completamente la pagina eliminando le dichiarazioni di floating o di posizionamento. Nel nostro caso, poiché la struttura principale di navigazione è stata posta dopo i contenuti, si è preferito evitare all'utente il fastidio di dover scrollare l'intera pagina per accedere a tali informazioni. In ogni caso, si può sempre nascondere un menu di navigazione ad hoc e visualizzarlo solo nel layout alternativo.

Uno stile così concepito può anche essere usato come foglio di stile utente. In questo caso occorrerà usare la dichiarazione !important per sovrascrivere il foglio di stile dell'autore e del browser. Esempio:

  1. body {
  2. background-color: #000 !important;
  3. background-image: none !important;
  4. color: #fff !important;
  5. font-family: sans-serif !important;
  6. font-size: 180% !important;
  7. margin: 1em !important;
  8. padding: 0 !important;
  9. font-weight: bold !important;
  10. line-height: 1.5 !important;
  11. }

28. Conclusioni

Alla fine del nostro percorso, abbiamo migliorato un layout scadente portandolo verso un quasi livello di accettabilità. Restano tuttavia dei dubbi sulla reale accessibilità, usabilità e tassonomia informativa del documento. Questi dubbi potranno essere fugati solo con un dialogo aperto con esperti dei rispettivi settori, fermo restando il principio di mettere al servizio degli utenti le tecniche esposte sinora.