#268 Sass Basics
- Download:
- source codeProject Files in Zip (80.5 KB)
- mp4Full Size H.264 Video (27.7 MB)
- m4vSmaller H.264 Video (15 MB)
- webmFull Size VP8 Video (16.5 MB)
- ogvFull Size Theora Video (38 MB)
Uno dei maggiori cambiamenti con il nuovo Rails 3.1 è il supporto per SASS, il quale rappresenta la soluzione di default per generare CSS. Grazie a concetti come annidamento, variabili e molto altro ancora, gestire lo stile della vostra applicazione diventa molto più semplice. Per dimostrare i vantaggi che comporta usare SASS, in questo episodio mostreremo come tradurre il CSS di una applicazione esistente in SASS.
Il sito su cui lavoreremo si presenta così:
Tutto lo stile è realizzato utilizzando CSS, il nostro obiettivo è mantenere lo stesso stile una volta finita la migrazione. Questo è il file su cui lavoreremo:
body { margin: 0; padding: 0; background-color: #FFF; font-family: verdana; font-size: 14px; } #header { background-color: #03507B; color: #FFF; padding: 4px 100px; border-bottom: solid 5px #00395A; } #header h1 { font-size: 30px; } a { color: #03507B; text-decoration: none; } a:hover { text-decoration: underline; } .new_project { background-color: #03507B; color: #FFF; padding: 5px 12px; margin: 10px 0; font-size: 16px; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; } #container { margin: 0 100px; } .project { border: solid 1px #777; margin: 20px 0; padding: 7px 12px; border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; } .project h2 { margin: 0; }
Questo file è abbastanza semplice quindi il nostro compito non dovrebbe essere molto difficile.Per prima cosa bisogna rinominare il file aggiungendo l'estensione .scss
. Standard CSS è completamente compatibile con SASS quindi ricaricando il browser tutto dovrebbe essere rimasto invariato.
Il nostro sito usa già SASS, ma ovviamente non è tutto qui. È comunque ottimo il fatto che CSS è completamente supportato poichè questo ci permette di scegliere solo le funzionalità che ci interessano. Se abbiamo un sito con un gran numero di CSS già esistenti possiamo rinominarli e modificarli quando e come vogliamo. Ma considerando quello che vi stiamo per mostrare probabilmente vorrette usare tutto immediatemente.
Annidamento
La prima funzionalità che useremo è annidiamento. Guarda questo codice CSS:
#header { background-color: #03507B; color: #FFF; padding: 4px 100px; border-bottom: solid 5px #00395A; } #header h1 { font-size: 30px; }
Questo codice definisce lo stile per un element con id
uguale a header e per ogni elemento h1
in esso contenuto. Con SASS possiamo annidare lo stile per h1
dentro quello per #header
così:
#header { background-color: #03507B; color: #FFF; padding: 4px 100px; border-bottom: solid 5px #00395A; h1 { font-size: 30px; } }
Quindi non abbiamo più bisogno di specificare il prefisso per elementi interni e siamo anche incoraggiati a mantenere compatto lo stile per elementi annidati. Può risultare semplice abusare di questa funzionalità introducento annidamenti lunghi e complessi ma è meglio invece mantenere il nostro annidamento semplice. In questa maniera basterà un'occhiata per capire cosa è dentro cosa. Questa non è comunque una regola e puoi trovare e usare il livello di annidamento che si adatta meglio ai tuoi gusti.
Possiamo anche usare annidimento auto-referenziale. Nel CSS abbiamo un selector per a
ed uno per a:hover
.
a { color: #03507B; text-decoration: none; } a:hover { text-decoration: underline; }
Poichè a:hover
non è un vero e proprio elemento annidato dobbiamo aggiungere una & al padre.
a { color: #03507B; text-decoration: none; &:hover { text-decoration: underline; } }
La & è necessaria perchè stiamo applicando stile a un attributo e non ad un vero e proprio elemento.
Variabili
Un' altra funzionalità veramente utile è data dalla possibilità di definire variabili. Nel nostro file CSS usiamo lo stesso colore in posti diversi. Se volessimo cambiarlo dovremmo modificare tutte le sue occorrenze.
SASS rende questo facile permettendoci di definire variabili. Il nome di una variabile deve cominciare con il simbolo dollaro. Definiremo quindi la nostra variabile così:
$main-color: #03507B;
Possiamo adesso sostituire tutte le occorrenze del colore con la variabile:
$main-color: #03507B; #header { background-color: $main-color; color: #FFF; padding: 4px 100px; border-bottom: solid 5px #00395A; h1 { font-size: 30px; } } a { color: $main-color; text-decoration: none; &:hover { text-decoration: underline; } }
Se ricarichiamo la nostra pagina tutto è rimasto lo stesso. Se adesso volessimo cambiare il colore, basta modificare il valore della variabile per passare da blu a verde.
$main-color: #1E7B12;
Quando ricarichiamo la pagina tutti gli stili che usano quel colore sono adesso cambiati: lo sfondo dell'header, i link ed il bottone “New Project” sono adesso verdi.Tutto questo è stato possibile con un singolo cambiamento nel foglio di stile.
Il bordo in basso all'header è ancora blu scuro ma vogliamo che abbia una tonalità più scura dell'header stesso. SASS ci permette di definire colori relativi usando delle funzioni. Sul sito di SASS possiamo trovare la completa lista delle funzioni disponibili, la quale include una funzione darken che fa esattamente quello di cui abbiamo bisogno. Passando un colore e una percentuale come parametri otterremo un colore più scuro come risultato.
Il colore del bordo in basso è definito nella dichiarazione per #header
.
#header { background-color: $main-color; color: #FFF; padding: 4px 100px; border-bottom: solid 5px #00395A; h1 { font-size: 30px; } }
Possiamo sostituirlo con una chiamata a darken
in maniera tale che il bordo abbia lo stesso colore dell'header ma più scuro del 10%.
#header { background-color: $main-color; color: #FFF; padding: 4px 100px; border-bottom: solid 5px darken($main-color, 10%); h1 { font-size: 30px; } }
Ricaricando la pagina il colore del bordo è adesso un verde scuro.
Mix-ins
Mix-ins sono un'altra feature di SASS che ci aiuta a ridurre la duplicazione. Nel nostro CCS ci sono due elementi che hanno il bordo arrotondato. Poiche' ogni vendor ha delle specifiche diverse, risulta essere più difficile del previsto ottenere dei bordi arrotondati che funzionino su tutti i browser.
border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;
Spostando questo codice in un mix-in, risulterà molto più semplice aggiungere la dichiarazione per dei bordi arrotondati. Un mix-in viene definito usando la parola chiave @mixin
e il nome che verrà poi usato per referenziarlo.
@mixin rounded-corners { border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; }
Possiamo adesso applicare il bordo arrotondato ovunque vogliamo chiamando @include
.
.new_project { background-color: $main-color; color: #FFF; padding: 5px 12px; margin: 10px 0; font-size: 16px; @include rounded-corners; }
Per ottenere un border-radius
contenente un valore diverso potremmo definire un altro mix-in. Ma fortunatamente è anche possibile passare argomenti ai mix-ins in maniera tale da modificare il nostro rounded-corners mix-in nella seguente maniera:
@mixin rounded-corners($radius) { border-radius: $radius; -moz-border-radius: $radius; -webkit-border-radius: $radius; }
Possiamo adesso passare qualunque valore ogni volta che vogliamo avere un bordo arrotondato.
.project { border: solid 1px #777; margin: 20px 0; padding: 7px 12px; @include rounded-corners(10px); }
Inoltre è anche possibile specificare un valore di default.
@mixin rounded-corners($radius: 5px) { border-radius: $radius; -moz-border-radius: $radius; -webkit-border-radius: $radius; }
Utilizzare SASS in file differenti
Anche usando SASS i nostri fogli di stile possono diventare lunghi e difficili da mantenere, adesso vedremo come è possibile organizzare il nostro stile separandolo in file differenti. Abbiamo già un file projects.css.scss
nella nostra applicazione, il quale venne generato al momento della generazione dello scaffold per Projects
. Questo file contiene al momento soltanto un commento, ma possiamo inserire del codice che sarà compilato e incluso da Rails 3.1 in un singolo file chiamato application.css.
Vogliamo quindi spostare qualunque codice SASS specifico per project dentro il file projects.css.scss
. Facciamolo e vediamo cosa succede.
.new_project { background-color: $main-color; color: #FFF; padding: 5px 12px; margin: 10px 0; font-size: 16px; @include rounded-corners(5px); } .project { border: solid 1px #777; margin: 20px 0; padding: 7px 12px; @include rounded-corners(10px); } .project h2 { margin: 0; }
Ricaricando la pagina vedremo che adesso lo stile non è più presente.
Per controllare se SASS ha lanciato un errore possiamo guardare il file di log o il foglio di stile nel browser.
Vediamo che un errore di sintassi ha impedito la generazione del foglio di stile. In questo caso l'errore è dovuto ad una variabile non definita:
Undefined variable: "$main-color".
Sembrerebbe che la variabile definita nel file principale non sia stata propagata negli file rimanenti.
Questo errore è dovuto al modo in cui Sprockets funziona in Rails 3.1. La variabili non vengono condivise fra i file SASS e possiamo vederne il perchè nel file application.css
.
/* * This is a manifest file that'll automatically include all the stylesheets available in this directory * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * the top of the compiled file, but it's generally better to create a new file per style scope. *= require_self *= require_tree . */
La linea require_tree .
dice a Sprockets di includere qualunque file che si trovi dentro la cartella stylesheets
. Il problema è che ogni file SASS viene compilato separatamente in un singolo CSS e soltanto dopo questi files vengono combinati in uno unico, il che significa che le variabili non vengono condivise tra i files. Per risolvere questo problema dobbiamo rimuovere require_tree .
ed usare SASS per importare ciascun file. Il vantaggio di questo approccio è che ci permette di definire l'ordine con cui i file vengono caricati. Questo non è possibile usando require_tree
. Dobbiamo quindi rinominare application.css
in application.css.scss
, rimuovere require_tree
ed importare i nostri stili.
/* * This is a manifest file that'll automatically include all the stylesheets available in this directory * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * the top of the compiled file, but it's generally better to create a new file per style scope. *= require_self */ @import "layout.css.scss"; @import "projects.css.scss";
Questo preserva tutte le nostre variabili, mix-ins e qualunque cosa abbiamo definito. Quando ricarichiamo la pagina il nostro stile funziona ora correttamente e la varibili definite nel foglio di layout sono disponibili per tutti gli altri.
SCSS vs SASS
Ti potresti chiedere perchè i file hanno una estensione .scss
se il linguaggio si chiama SASS. Questo è perchè SASS supporta due sintassi differenti. SCSS è la nuova sintassi a partire da SASS 3 ma quella vecchia è ancora disponibile e continuerà ad essere supportata. Per utilizzarla il file di stile dovrà avere l'estensione .sass
. La vecchia sintassi è simile a quella nuova ma non usa parentesi graffe o punti e virgola alla fine di ogni linea, il livello del blocco viene determinato in base al numero di spazi. La sintassi SCSS, essendo in super insieme di CSS, è più facile da usare specialmente se bisogna migrare da fogli di stile esistenti.
Fogli di stile condizionali
Finiamo questo episodio con un piccolo suggerimento. Come possiamo cambiare i file che vengono inclusi in base all'attuale controller? Dato un file projects.css.scss
potremmo che pensare che questo venga incluso solo per le azioni incluse in ProjectsController
, ma non è così. Tutti i CSS vengono compilati in un singolo file che viene applicato a tutte le pagine dell'applicazione. In genere questo non è un problema se utilizziamo gli scope correttamente ma certe volte potrebbe non essere abbastanza.
Una soluzione è quella di modificare il tag di apertura del body nel file di layout ed aggiungere un attributo id
avente il nome dell'attuale controller come valore.
<body id="<%= params[:controller].parameterize %>_controller">
Chiamiamo parameterize
sul nome del controller per rimuovere qualunque carattere speciale. Avendo adesso un unico id
per ciascun controller, possiamo usare questo per introdurre degli scope nei nostri fogli di stile:
#projects_controller { .new_project { background-color: $main-color; color: #FFF; padding: 5px 12px; margin: 10px 0; font-size: 16px; @include rounded-corners(5px); } .project { border: solid 1px #777; margin: 20px 0; padding: 7px 12px; @include rounded-corners(10px); } .project h2 { margin: 0; } }
Questi stili verranno adesso applicati solo alle azioni del ProjectsController
. Questo significa minori possibilità di avere conflitti tra id
o class
in controller diversi.
Questo è tutto per questo episodio su SASS. Non abbiamo parlato di tutto quello che SASS può fare, quindi suggeriamo di dare un'occhiata alla documentazione sul sito ufficiale per ottenere maggiori informazioni.