Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Cambiare al volo i fogli di stile

Come utilizzare l'oggetto styleSheets per manipolare i css con DHTML
Come utilizzare l'oggetto styleSheets per manipolare i css con DHTML
Link copiato negli appunti

Con questo tutorial, vorrei introdurre l'oggetto styleSheets, il cui uso sicuramente potrà essere un ulteriore sostegno (per chi già non lo conosca) alle tradizionali tecniche per la realizzazione di applicazioni e scripts DHTML.

Introduzione e Compatibilità

L'oggetto stileSheets è una collezione dell'oggetto document che contiene tutta la lista dei fogli di stile incorporati ed esterni. Questa collezione permette non solo di recuperare gli stili contenuti nei css, ma anche di modificarli dinamicamente, dando la possibilità di accedere agli stili di ogni elemento nella pagina. Gli oggetti a cui vengono cambiati gli stili reagiranno ai cambiamenti, adeguandovisi e dimostrando quindi che gli elementi di una pagina HTML sono "vivi".

Nelle tradizionali tecniche DHTML, per modificare gli stili degli oggetti occorre ricercarli lungo la pagina, scandendo le varie collezioni di cui fanno parte, o recuperandoli grazie all'uso degli attributi ID, e una volta individuati, occorre "convincerli" a modificare i loro stili.

Utilizzando l'oggetto styleSheets, invece, si possono modificare gli stili degli oggetti direttamente cercandoli nei fogli di stile, saranno poi gli oggetti stessi a seguire le modifiche. È poi facile estendere questa logica per realizzare scripts veramente efficienti.

Perchè non si utilizzava?

La risposta è semplice: la compatibilità crossbrowser.

Infatti, nonostante sia definito tra gli standard del DOM W3C, alcune vecchie versioni dei browser non lo includevano, in particolare i problemi nascevano con Netscape 4.x, che si era "inventata" tutta una serie di collezioni per definire e recuperare gli stili:

collezioni che davano la possibilità di definire gli stili, ma non permettevano di modificarli dinamicamente, perciò chi voleva realizzare scripts DHTML che fossero stati crossbrowser, era costretto a rinunciare alle potenzialità dell'oggetto styleSheets.

Con la versione 6, Netscape ha eliminato queste collezioni e si è adeguato agli standard, aprendo le porte alla creazione di scripts che facciano uso di styleSheets. Per le mie conoscenze attuali l'oggetto è supportato da:

  • Explorer 4.0 e superiori su Windows e Macintosh (5.0)
  • Netscape 6.0 e superiori su Windows e Macintosh
  • Konqueror 2.2 su RedHat Linux 7.1

mentre non è supportato da Opera 5 (che in verità supporta ben pochi oggetti, metodi e proprietà standard).

File disponibili

In questo tutorial faremo uso di due file esterni. Il foglio di stile styleSheets.css che definisce la visualizzazione di alcuni elementi della pagina (tra cui tutto il contenuto di questo articolo) e il file Javascript js03.js che è il contenitore delle funzioni che agiscono sui fogli di stile. Il file sono compresi in un unico file zip. Confrontanto il contenuto del Javascript con la sintassi di questa pagina e degli esempi ricaverete tutte le funzionalità di questo codice.


Descrizione e Uso

Iniziamo con lo stabilire se il browser supporta l'oggetto; come per le altre collezioni la sintassi è:

if(document.styleSheets) {
   // supporta l'oggetto styleSheets
  }
else {
   // non supporta l'oggetto styleSheets
  }

verifichiamolo:

Il passo successivo è capire cosa l'oggetto styleSheets contenga. Per mostrarlo la cosa più efficace è fare un esempio. Per capire, inanzitutto, mostro il codice di questa pagina relativa agli stili:

<link rel="stylesheet" type="text/css" href="/css/styleSheets.css">
<link rel="stylesheet" type="text/css" href="https://www.html.it/stilens.css" >
<style type="text/css">
@import url(https://www.html.it/stile.css);
</style>

Noi agiremo sulle proprietà del primo foglio di stile (styleSheets.css) che contiene le seguenti dichiarazioni:

div.w {background: #FFFFFF;
   font-family:"arial";
   font-size:15px;
   }
H1{font-family:"verdana";
   font-size:22px;}
H2{background:#333333;
   color:#EEEEEE;
   font-family:"verdana";
   font-size:18px;}
H3{background:#CCCCCC;
   color:#999999;
   font-family:"verdana";
   font-size:15px;}

Come ho accennato prima, l'oggetto stileSheets colleziona in un array tutti i fogli di stile esterni ed incorporati, presenti nella pagina. In questo caso l'array conterrà 5 elementi, il cui indice nell'array rispecchia l'ordine con il quale sono inseriti nella pagina; ovviamente, come per tutti gli array, il primo elemento è caratterizzato dall'indice 0.

Recuperiamo il numero degli styleSheets con la proprietà length, comune a tutti gli array.

document.styleSheets.length // numero dei fogli di stile nella pagina


A questo punto possiamo entrare all'interno dei singoli fogli di stile, esterni o incorporati che siano, per recuperare i valori degli stili applicati e successivamente modificarli o aggiungerne di nuovi. Innanzitutto individuiamo il foglio di stile sul quale vogliamo intervenire (il primo della lista, con indice 0)

document.styleSheets[0]

nell'esempio stiamo considerando il primo foglio di stile (indice 0), relativo al foglio esterno. Questa dichiarazione, con cui si apre il javascript esterno che abbiamo utilizzato in queste pagine, è fondamentale in quanto assegna all'oggetto stile il valore del primo CSS della pagina. Tutto lo script che richiamerà stile farà dunque sempre riferimento al primo foglio di stile incontrato dal browser.

Ora dobbiamo recuperare le singole leggi di stile, nella nomenclatura rules. Per intenderci, una rule è ogni insieme di stili compresi tra parentesi graffe, indipendemente che siano stili per tag, classi o identificatori (attributo ID):

DIV.w {
background: #FFFFFF; /* questa è la prima rules */
font-family:"arial"; /* del primo foglio di stile */
font-size:15px;
}

Per accedere, via Javascript, alle singole rules, si utilizza un'altra collezione, che per l'appunto memorizza tutte le rules di un foglio di stile. Questo è praticamente l'unico punto nel quale i due principali browser si differenziano:

document.styleSheets[0].cssRules // per Netscape 6+ e Konqueror

document.styleSheets[0].rules // per Explorer 4+

Come si vede, però, la differenza è veramente minima, offrendo così un ulteriore vantaggio per costruire codici che rimangano compatti e quindi leggibili, senza contare che si alleggerisce lo sforzo mnemonico (che non guasta!).

Ad esempio negli script di questo tutorial ho usato sempre un codice che ricalca la seguente filosofia:

ok = (document.styleSheets) ? 1:0;
IE4 = (document.all) ? 1:0;
NN6 = (!document.all && document.getElementById) ? 1:0;

if(ok) {
  if(IE4) stile = document.styleSheets[0].rules
  if(NN6) stile = document.styleSheets[0].cssRules
  }

Dopo queste poche righe, stile rappresenterà il vettore delle rules del primo foglio di stile su entrambi i principali browser, permettendo così di scrivere un solo codice. Ovviamente, per accedere a fogli di stile differenti si dovranno usare variabili con nomi differenti, ad esempio, stile2, stile3 ecc. o qualsiasi altro nome.

Nota: Vorrei specificare che tra le due sintassi, quella conforme agli standard del DOM W3C, è, sfortunatamente, quella di Netscape. Sfortunatamente, non perchè abbia qualcosa contro Netscape, ma solo perchè, l'optimum per la creazione di scripts sarebbe quello di non perdersi nel duplicare codici per i vari browser e la speranza è che con le prossime versioni dei browser si tenda all'unificazione delle sintassi, ma per far questo qualcuno deve adeguarsi. Ma se si adeguasse Netscape, ci si allontanerebbe dagli standard (poco probabile), se si adeguasse Explorer, invece, si perderebbero le versioni precedenti del browser di casa Microsoft...per cui, finchè non non sarà avvenuto il cambio del "parco browsers", occorrerà fare attenzione al crossbrowser e al crossversion. Questo sempre se Microsoft si adegui...

Torniamo al tutorial. Siamo arrivati ad avere l'oggetto crossbrowser stile che contiene le rules del secondo foglio di stile.

Per recuperare tutti gli stili di una rule si deve inanzitutto scorrere l'array stile fino a raggiungere la rule d'interesse.

NON è possibile accedervi passando il nome della rule, ma solo il suo indice:

stile[0] //contiene la rule relativa al tag BODY
stile[1] //contiene la rule relativa al tag H1
stile[2] //contiene la rule relativa al tag H2
stile[3] //contiene la rule relativa al tag H3

Si possono recuperare tutti gli stili di una rule attraverso l'uso della proprietà cssText. Explorer deve anteporre la parola chiave style per usare la proprietà. Nell'esempio qui sotto si visualizzano le rules del primo foglio di stile (se volessimo visualizzare quelle del secondo dovremmo modificare il codice fornito poco sopra e incluso nel javascript esterno da document.styleSheets[0] a document.styleSheets[1]) :

rule0 = (IE4) ? stile[0].style.cssText : stile[0].cssText; // stili di BODY

rule1 = (IE4) ? stile[1].style.cssText : stile[1].cssText; // stili di H1

rule2 = (IE4) ? stile[2].style.cssText : stile[2].cssText; // stili di H2

rule2 = (IE4) ? stile[3].style.cssText : stile[3].cssText; // stili di H3





Nota: Come vedete, anche in questo caso i due principali browser differiscono, ma in realtà, per il momento, questo ha uno scarso valore applicativo. Infatti in Netscape la proprietà

cssText permette solo di leggere gli stili e non di modificarli, cosa invece concessa in Explorer, perciò, nella maggior parte dei casi, questa non sarà una proprietà usata, se non a fini di controllo.

Ora non ci resta che occuparci di come cambiare dinamicamente gli stili.


Manipolare gli stili dinamicamente

Per modificare gli stili, una volta appresa la tecnica per accedere ai singoli fogli di stile e alle singole rules, si utilizza la proprietà style applicata alle rules recuperate.
La sintassi è:

stile[indice_della_rule].style.nomeStile = valoreStile

Tenendo presente che nel nostro caso l'oggetto stile si riferisce al primo foglio di stile, ed è perciò stato definito così:

IE4 = (document.all) ? 1:0;
NN6 = (!document.all && document.getElementById) ? 1:0;

if(IE4) stile = document.styleSheets[0].rules
if(NN6) stile = document.styleSheets[0].cssRule

Per capire meglio, passiamo subito ad una dimostrazione pratica, andando a modificare il valore dello stile font-Size, della rule riferita al tag DIV.w (che formatta l'intero contenuto dell'articolo). Per fare questo, costruiamo una piccola funzione:

function cambiaFontSize(size) {
stile[0].style.fontSize = size
}




Come vedete dall'esempio, i nomi degli stili sono quelli tradizionalmente usati nel DHTML. Vi fornisco una lista abbastanza completa degli stili:


azimuth font pauseAfter
background fontFamily pauseBefore
backgroundAttachment fontSize pitch
backgroundColor fontSizeAdjust pitchRange
backgroundImage fontStretch playDuring
backgroundPosition fontStyle position
backgroundRepeat fontVariant quotes
border fontWeight richness
borderBottom height right
borderBottomColor left size
borderBottomStyle length speak
borderBottomWidth letterSpacing speakHeader
borderCollapse lineHeight speakNumeral
borderColor listStyle speakPunctuation
borderLeft listStyleImage speechRate
borderLeftColor listStylePosition stress
borderLeftStyle listStyleType tableLayout
borderLeftWidth margin textAlign
borderRight marginBottom textDecoration
borderRightColor marginLeft textIndent
borderRightStyle marginRight textShadow
borderRightWidth marginTop textTransform
borderSpacing markerOffset top
borderStyle marks unicodeBidi
borderTop maxHeight verticalAlign
borderTopColor maxWidth visibility
borderTopStyle minHeight voiceFamily
borderTopWidth minWidth volume
borderWidth orphans whiteSpace
bottom outline widows
captionSide outlineColor width
clear outlineStyle wordSpacing
clip outlineWidth zIndex
color overflow  
content padding  
counterIncrement paddingBottom  
counterReset paddingLeft  
cue paddingRight  
cueAfter paddingTop  
cueBefore page  
cursor pageBreakAfter  
direction pageBreakBefore  
display pageBreakInside  
emptyCells pause  

Il procedimento, a questo punto, non cambia: qualsiasi variazione si voglia effettuare su uno o più stili di una o più rules di uno o più fogli di stile, la sintassi rimane inalterata. In particolare, quando si voglia modificare molti stili di una stessa rule, è molto conveniente l'uso del costrutto with.

Mostriamone la sintassi con un esempio nel quale cambiamo contemporaneamente, la famiglia e la taglia del font usato in una pagina, e il colore del testo:

/*---------------------------------------------
invece di ripetere le stesse righe scrivendo:

stile[0].style.fontFamily = "verdana";
stile[0].style.fontSize = "9px";
stile[0].style.color = "blue";

scriviamo le seguenti righe:
----------------------------------------------*/

with(stile[0].style) {
fontFamily = "verdana";
fontSize = "9px";
color = "blue";
}



Nella sezione Esempi, al termine dell'articolo, sono mostrate diverse applicazioni descrittive dei concetti fin qui esposti e forse potranno mostrare con più chiarezza le potenzialità e la libertà che offre l'oggetto stileSheets.


Manipolare gli stili "semi-dinamicamente"

In questa sezione descriverò quelli che ho definito cambiamenti "semi-dinamici" degli stili. Mostrerò infatti come poter facilmente modificare gli stili di una pagina, abilitando e disabilitando opportunamente fogli di stile (esterni o incorporati che siano) già esistenti.

Perciò, in realtà non viene fatta alcuna modifica dinamica dei fogli di stile, ma si interviene solo sulla loro effettiva applicazione alla pagina. In sostanza, si può decidere quale foglio di stile "accendere" e quale no.

Tutto questo viene realizzato attraverso una semplice proprietà (crossbrowser) dell'oggetto styleSheets: disabled. La sua sintassi e suoi possibili valori sono:

document.styleSheets[indice_stile].disabled = true | false

  • indice_stile : (intero) è l'indice che individua il foglio di stile che si vuole disabilitare (true) o abilitare (false).

Per default, ovviamente, la proprietà disabled è settata a false,e se vengono disabilitati tutti i fogli di stile, la pagina assume le caratteristiche predefinite dall'utente.

Con la seguente funzione è possibile accendere o spegnere il foglio di stile che si desidera, passandogli il suo indice e il valore della proprietà «disabled».

function stili_on_off(indice_stile,valore) {
  document.styleSheets[indice_stile].disabled = valore
}

Applichiamola ai fogli di stile del contenuto di questa pagina:



Per concludere questa sezione, per completezza occorre dire che Explorer offre anche la possibilità di sostituire i fogli di stile esterni, utilizzando la proprietà href di styleSheets. Questa proprietà, oltre ad essere definita dalle specifiche del W3C, è supportata anche da Netscape, ma è una proprietà di sola lettura e permette solo di recuperare il nome (e il path) del foglio di stile esterno, il che elimina il suo utilizzo per scopi crossbrowser.

Con la seguente funzione, viene usata la proprietà href in lettura in entrambi i browser, e in scrittura in Explorer sostituendo l'attuale foglio di stile esterno con "styleSheets_02.css".

function usaHref(){
alert(document.styleSheets[1].href)
if(IE4) document.styleSheets[1].href = "css/styleSheets_02.css"
}



Aggiungere ed Eliminare stili

L'oggetto styleSheets consente non solo di accedere e manipolare gli stili già definiti, ma anche di aggiungerne ed eliminarne altri "al volo". Questo è previsto anche dalle specifiche W3C, ma come vedremo anche in questo caso, tra i due principali browser esistono differenze. Anche in questo caso Explorer, seppur implementa questa possibilità già dalla versione 4.0, non è conforme agli standard ed usa un metodo dell'oggetto styleSheets diverso da quello usato da Netscape 6.0:

  • Explorer (4.0+)

    document.styleSheets[indice_stile].addRule(selettore,stili_rule)

    • indice_stile : (intero) è l'indice che individua il foglio di stile nel quale si vuole inserire la rule di stili.
    • selettore : (stringa) il tag, la classe o l'identificatore al quale si vuole aggiungere la rule di stili
    • stili_rule : (stringa) la rule da inserire, costituita dall'insieme degli stili da applicare al selettore scelto.
  • Netscape (6.0+) [W3C]

    document.styleSheets[indice_stile].insertRule(rule,indice_rules)

    • indice_stile : (intero) è l'indice che individua il foglio di stile nel quale si vuole inserire la rule di stili.
    • rule: (stringa) la rule da inserire, costituita da un selettore (tag, classe
      o identificatore) e dall'insieme degli stili da applicare a questo.
    • indice_rules : (intero) indice della posizione nel vettore che colleziona le rules prima della quale si vuole inserire la rule specificata.

Facciamo qualche esempio.

Inseriamo al volo uno stile nel primo foglio di stile, dopo l'ultima rule (visto che Explorer non dà possibilità di scelta), ovvero dopo quella del tag H3. In particolare inseriamo un'altra rule al tag H2 (quello relativo ai titoli delle varie sezioni del tutorial), settiamo gli stili per il colore del testo e dello sfondo.

Prima verifichiamo il numero delle rules del secondo foglio di stile, per semplicità, utilizziamo l'oggetto crossbrowser stile, creato precedentemente:


La funzione sarà:

if(IE4)
document.styleSheets[0].addRule("H2","{color:orange;background-color:#AAAAAA;}")

if(NN6)
document.styleSheets[0].insertRule("H2{color:orange;background-color:#AAAAAA;}",4)

e tornate poi a controllare il numero delle rules.

Esempio di tag <H2> modificato

Come vi sarete accorti, la collezione delle rules è aumentata, e gli stili aggiunti hanno preso il soppravvento sui corrispettivi definiti precedentemente (color e background-color) del selettore in questione, mentre hanno lasciato invariati quelli non considerati (font-family e font-size).

Inoltre, se continuate a premere, il numero delle rules continuerà ad aumentare. Per evitare questo si può settare una variabile globale (flag) che controlli se lo stile è stato aggiunto:

flag = false

function aggiungiUnaRule() {
 if(!flag) {
  if(IE4)
    document.styleSheets[0].addRule("H2","{color:orange;background-color:#AAAAAA;}")
  if(NN6)
    document.styleSheets[0].insertRule("H2{color:orange;background-color:#AAAAAA;}",4)
  flag = true;
 }
}

Per verificare l'effettivo funzionamento, ricaricate la pagina e provate i bottoni sottostanti



A questo punto, possiamo occuparci di eliminare gli stili aggiunti, o precedentemente definiti. Anche in questo caso, Explorer e Netscape utilizzano metodi differenti dell'oggetto styleSheets:

  • Explorer (4.0+)

    document.styleSheets[indice_stile].removeRule(indice_rules);

    • indice_stile : (intero) è l'indice che individua il foglio di stile dal quale si vuole eliminare la rule di stili.
    • indice_rules : (intero) indice del vettore che colleziona le rules relativo alla rule che si vuole eliminare.
  • Netscape (6.0+) [W3C]

    document.styleSheets[indice_stile].deleteRule(indice_rules)

    • indice_stile : (intero) è l'indice che individua il foglio di stile dal quale si vuole eliminare la rule di stili.
    • indice_rules : (intero) indice del vettore che colleziona le rules relativo alla rule che si vuole eliminare.

Passiamo alla pratica ed eliminiamo la rule aggiunta.

Analogamente a prima, per evitare che si ripeta ad ogni pressione l'eliminazione della rule, utilizziamo una variabile globale. Occorre inserire l'indice della rule che si vuole eliminare, per cui occorre sempre tenere presente quale sia l'indice della rule in questione, in particolare in casi in cui ci siano più inserimenti ed eliminazioni di stili. Per eliminare l'ultima rules, utilizzo il seguente codice, facendo ancora una volta uso dell'oggetto stile e ricordando le proprietà dei vettori:

flag_elimina = false

function EliminaUnaRule() {
if(!flag_elimina) {
 if(IE4)
  document.styleSheets[0].removeRule(stile.length-1)
 if(NN6)
  document.styleSheets[0].deleteRule(stile.length-1)
 flag_elimina = true;
 }
}



Esempio di tag <H2> modificato

Esempio di tag <H3> modificato

Se premete quest'ultimo pulsante senza aver aggiunto la nuova rule (dopo aver ricaricato la pagina) sarà comunque eliminata l'ultima rule, in questo caso, quella relativa al tag H3 (applicata ai titoli degli esempi).

Per cui fate attenzione all'uso di questo metodo, soprattuto se lasciato "libero".

Nota:L'operazione di eliminazione delle rules, teoricamente senza troppe difficoltà, attualmente invece può procurare dei problemi, causati dalla presenza di bug in Netscape 6.0. Infatti ogni rule prevede la proprietà (definita anche dal W3C) selectorText, che restituisce il nome del selettore (tag, classe, o identificatore) della rule al quale viene applicato. Netscape supporta questa proprietà, ma in realtà è inutile, per il fatto che invece di contenere la stringa con il selettore, non contiene niente!

Non solo, ma pur supportando il metodo, NN6.0 non esegue di fatto le operazioni di eliminazione delle rules, e per vedere l'effettiva validità dei codici proposti, occorre utilizzare un browser come Mozilla 1.0, che fornisce un completo e solido supporto alle specifiche W3C.

Nella sezione Esempi (ultima pagina), mostro un modo di aggirare il problema del selectorText usando variabili globali, ma ovviamente ci si aspetta che con le versioni successive Netscape "guarisca" da tutti i suoi bugs.


Esempi

Premetto inanzitutto, che questi sono semplici esempi dimostrativi, realizzati al fine di mostrare alcune delle capacità dell'oggetto styleSheets descritte in questo tutorial.

Vi renderete subito conto, che la gestione dei fogli di stile è molto semplice, e l'oggetto styleSheets permette di manipolare le rules con molta elasticità. Altrettanto immediatamente vi renderete conto che l'uso di questa tecnica fornisce una visione "globale" della pagina HTML, che si fonda sul DOM. Premetto inoltre, che questi esempi sono stati testati su Explorer 4.0+ e Netscape 6.0 su PC/Windows(95/98/XP).

Cambiare gli stili del testo [esempio]

In questo esempio, vengono modificati piu stili delle classi associate ai paragrafi (tag P), cominciando a mostrare le potenzialità di styleSheets. Interessante sono anche le variazioni che si effettuano sugli stili del documento tag (BODY), che mostrano con più chiarezza cosa si intende per elemento parent, infatti modifiche sullo stile marginTop del body si ripercuotono su tutti gli elementi children.

Usare i fogli di stile esterni [esempio]

Viene riproposto praticamente lo stesso esercizio precedente usando fogli di stile e files js esterni.

Gestire le immagini di fondo [esempio]

L'esempio mostra come sia possibile e facile cambiare l'immagine di fondo, modificare la sua posizione e la sua rappresentazione nella pagina.

Un'alternativa ai DIV: un preloader [esempio]

In questo esempio realizziamo un piccolo preloader, modificando le dimensioni della cella di una tabella. Lo scopo è fornire un'alternativa all'uso dei livelli, per realizzare piccole animazioni. Nella prima parte viene mostrato il funzionamento del preloader, nella seconda, una sua possibile applicazione reale.

Cambiare gli stili di una tabella [esempio]

Nell'esempio si utilizza l'oggetto styleSheets per manipolare gli stili degli elementi di una tabella. Non c'è nulla da aggiungere a quello spiegato finora riguardo styleSheets, mentre occorre prestare un po' d'attenzione all'applicazione degli stili alle tabelle. Infatti Netscape ed Explorer, come forse vi sarà capitato di verificare, spesso gestiscono le ereditarietà e le "precedenze" degli stili di una tabella in maniera differente. Ma questo esula dai fini del tutorial.

Cambiare tutti gli stili di una pagina con un colpo solo [esempio]

Questa è una delle possibilità offerta dal semplice uso della proprietà disabled dell'oggetto styleSheets. L'operazione può essere estesa a tutte le pagine di un sito, attraverso l'uso di cookie, dando la possibilità all'utente di scegliere il "proprio" stile.

Evidenziare il codice [esempio]

Nell'esempio è possibile aggiungere ed eliminare dinamicamente rules al foglio di stile applicato alla pagina, per evidenziare parti del codice proposto. Si implementa anche un semplice meccanismo per l'eliminazione "mirata" delle rules.

Risorse

Ti consigliamo anche