back to top

Sass: mixin e la direttiva @content

Finora abbiamo illustrato varie funzionalità presenti in Sass e abbiamo potuto apprezzare in che modo Sass permetta di generare dei fogli di stile in maniera più efficiente. In questa lezione parleremo invece dei mixin e vedremo come crearli e usarli per rendere il codice riutilizzabile.

Cosa sono e perché usare i mixin in Sass

I mixin in Sass costituiscono uno strumento configurabile attraverso il quale è possibile raggruppare un blocco di dichiarazioni che possiamo poi riutilizzare più volte nei fogli di stile. Il principale vantaggio derivato dall’uso dei mixin è la possibilità di incorporare frammenti di codice in diverse regole senza dover riscrivere ogni volta le stesse dichiarazioni in maniera ripetitiva.

Come creare un mixin in Sass

Creare un mixin in Sass è estremamente semplice. Basta infatti anteporre la direttiva @mixin al nome del mixin stesso e racchiudere fra parentesi graffe il blocco di dichiarazioni come mostrato nell’esempio sottostante in cui creiamo un mixin chiamato simple-button all’interno di un file _button.scss. Come per le variabili, anche per i nomi dei mixin non c’è distinzione fra il carattere ‘_’ e il carattere ‘-‘. Può inoltre risultare conveniente anteporre un prefisso al nome dei mixin che creiamo per evitare possibili conflitti con i mixin importati da altre librerie.

/* file _button.scss */
@mixin simple-button {
  box-sizing: border-box;
  text-transform: uppercase;
  border-radius: 3px;
  border: none;
  box-shadow: 0 3px 6px rgba(0,0,0,0.18);
  padding: 8px 12px;
  font-size: 12px;
  font-family: 'Roboto', Helvetica, sans-serif;
  width: 100px;
  transition: all 0.3s cubic-bezier(.18,.9,.18,1);
  cursor: pointer;
  background-color: #f74a34;
  color: rgba(255, 255, 255, 0.87);

  &:hover {
    transform: scale(1.03);
    box-shadow: 0 6px 12px rgba(0,0,0,0.24);
    background-color: darken(#f74a34, 5%);
    color: #fff;
  }

  &:focus {
    outline: none;
    box-shadow: 0 4px 8px rgba(0,0,0,0.24);
    background-color: darken(#f74a34, 10%);
    color: #fff;
  }

  &:active {
    box-shadow: 0 2px 4px rgba(0,0,0,0.12);
    background-color: darken(#f74a34, 5%);
    transform: scale(.96);
  }
}

Abbiamo creato il nostro primo mixin che consente di riutilizzare una serie di dichiarazioni in qualsiasi altra regola.

Come usare un mixin in Sass

A questo punto, dopo aver creato il mixin simple-button, non ci resterà che usarlo. A tal proposito creiamo un file style.scss nella stessa directory del file che contiene il mixin e al suo interno copiamo il seguente frammento di codice.

/* file style.scss */
@import "button";

.button {
  @include simple-button;
}

Basterà dunque usare la direttiva @include seguita dal nome del mixin da noi definito. Il blocco di dichiarazioni presenti nel mixin verranno inserite nella regola per la classe button. Lanciando il comando node-sass per compilare il file style.scss otteniamo un nuovo file style.css il cui contenuto sarà simile a quello riportato in basso.

/* file style.css */
.button {
  box-sizing: border-box;
  text-transform: uppercase;
  border-radius: 3px;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.18);
  padding: 8px 12px;
  border: none;
  font-size: 12px;
  font-family: 'Roboto', Helvetica, sans-serif;
  width: 100px;
  transition: all 0.3s cubic-bezier(0.18, 0.9, 0.18, 1);
  cursor: pointer;
  background-color: #f74a34;
  color: rgba(255, 255, 255, 0.87);
}

.button:hover {
  transform: scale(1.03);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.24);
  background-color: #f6341b;
  color: #fff;
}

.button:focus {
  outline: none;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.24);
  background-color: #ef2309;
  color: #fff;
}

.button:active {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
  background-color: #f6341b;
  transform: scale(0.96);
}

Mixin con parametri

Ma i mixin offrono molte più possibilità. Per esempio è possibile passare degli argomenti che consentono di configurare i mixin in maniera dinamica. In più ad ogni argomento si può assegnare un valore di default. Aggiorniamo quindi l’esempio visto in precedenza in modo da poter creare dei pulsanti di diversi colori.

/* file _button.scss */
@mixin simple-button($background-color: #333, $text-color: #fff) {
  box-sizing: border-box;
  text-transform: uppercase;
  border-radius: 3px;
  box-shadow: 0 3px 6px rgba(0,0,0,0.18);
  padding: 8px 12px;
  border: none;
  font-size: 12px;
  font-family: 'Roboto', Helvetica, sans-serif;
  width: 100px;
  transition: all 0.3s cubic-bezier(.18,.9,.18,1);
  cursor: pointer;
  background-color: $background-color;
  color: rgba($text-color, 0.87);

  &:hover {
    transform: scale(1.03);
    box-shadow: 0 6px 12px rgba(0,0,0,0.24);
    background-color: darken($background-color, 5%);
    color: $text-color;
  }

  &:focus {
    outline: none;
    box-shadow: 0 4px 8px rgba(0,0,0,0.24);
    background-color: darken($background-color, 10%);
    color: $text-color;
  }

  &:active {
    box-shadow: 0 2px 4px rgba(0,0,0,0.12);
    background-color: darken($background-color, 5%);
    transform: scale(.96);
  }
}

Nell’esempio visto sopra, il mixin simple-button presenta due parametri con i quali possiamo configurare le proprietà color e background-color. Se quindi invochiamo il mixin come nell’esempio precedente, verranno usati i valori predefiniti. Altrimenti possiamo passare degli argomenti come mostrato sotto.

/* file style.scss */
@import "button";

.button {
  @include simple-button(#00b176, #fff);
}

Bisogna però prestare attenzione perché qualsiasi parametro che abbia un valore predefinito non deve essere preceduto da parametri senza valore di default. Per cui non è possibile creare un mixin come quello sottostante.

/* file style.scss */
// ERRORE: required parameters must precede optional parameters

@mixin simple-button($background-color: #333, $text-color) {
  // <blocco-di-dichiarazioni>
}

Ma è invece consentito creare un mixin come mostrato di seguito.

/* file style.scss */
@mixin simple-button($background-color, $text-color: #fff) {
  // <blocco-di-dichiarazioni>
}

A volte può essere necessario passare a un mixin un numero di argomenti non noto a priori. Sass supporta una funzionalità detta “Variable arguments” che consente di passare un numero variabile di argomenti.

/* file style.scss */
@mixin padding-mixin($padding...) {
  padding: $padding;
}

p {
  border: 1px solid black;
  @include padding-mixin(20px 50px)
}

Gli argomenti passati al mixin padding-mixin vengono inseriti all’interno della lista $padding che viene poi usata per assegnare un valore alla proprietà padding. In questo modo possiamo passare al mixin uno o più argomenti a seconda delle necessità. Il file generato sarà quindi il seguente.

/* file style.css */
p {
  border: 1px solid black;
  padding: 20px 50px;
}

Un altro uso dell’operatore …

L’operatore ‘…’ può essere usato in alternativa per estrarre gli elementi da una lista e assegnarli come argomenti a un mixin. In questo caso useremo tale operatore in fase di invocazione del mixin e non quando il mixin viene definito. Cerchiamo di chiarire meglio quanto appena descritto attraverso un esempio. Riprendiamo il mixin simple-color già visto negli esempi precedenti a cui è possibile passare due argomenti. Supponendo di avere una lista di colori come mostrato sotto, possiamo usare l’operatore ‘…’ che estrae ciascun elemento dalla lista e lo passa in ordine come argomento al mixin.

/* file style.scss */
@import "button";

$colors_1: #90f8d9, #2e2d4d;

.button{
  @include simple-button($colors_1...);
}

Il risultato ottenuto è visibile nel frammento sottostante in cui viene usato #90f8d9 come valore della proprietà background-color e #2e2d4d come valore della proprietà color.

/* file style.css */
.button {
  box-sizing: border-box;
  text-transform: uppercase;
  border-radius: 3px;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.18);
  padding: 8px 12px;
  border: none;
  font-size: 12px;
  font-family: 'Roboto', Helvetica, sans-serif;
  width: 100px;
  transition: all 0.3s cubic-bezier(0.18, 0.9, 0.18, 1);
  cursor: pointer;
  background-color: #90f8d9;
  color: rgba(46, 45, 77, 0.87);
}

.button:hover {
  transform: scale(1.03);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.24);
  background-color: #78f6d1;
  color: #2e2d4d;
}

.button:focus {
  outline: none;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.24);
  background-color: #60f5c9;
  color: #2e2d4d;
}

.button:active {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
  background-color: #78f6d1;
  transform: scale(0.96);
}

La direttiva @content

La direttiva @content consente di personalizzare ulteriormente un mixin passando un blocco di dichiarazioni che verrà inserito nel mixin stesso. Modifichiamo per esempio il codice del mixin simple-button visto in precedenza come segue.

/* file _button.scss */
@mixin simple-button($background-color: #333, $text-color: #fff) {
  box-sizing: border-box;
  text-transform: uppercase;
  border-radius: 3px;
  box-shadow: 0 3px 6px rgba(0,0,0,0.18);
  padding: 8px 12px;
  border: none;
  font-size: 12px;
  font-family: 'Roboto', Helvetica, sans-serif;
  width: 100px;
  transition: all 0.3s cubic-bezier(.18,.9,.18,1);
  cursor: pointer;
  background-color: $background-color;
  color: rgba($text-color, 0.87);

  // il blocco di dichiarazioni passato al mixin
  // sarà inserito qui
  @content;

}

A questo punto possiamo passare un blocco di dichiarazioni al mixin nel momento in cui viene invocato.

/* file style.scss */
@import "button";

$background-color: #90f8d9; 
$text-color: #2e2d4d;

.button{
  // passiamo una serie di regole al mixin simple-button
  @include simple-button($background-color, $text-color) {
    &:hover {
      transform: scale(1.03);
      box-shadow: 0 6px 12px rgba(0,0,0,0.24);
      background-color: darken($background-color, 5%);
      color: $text-color;
    }

    &:focus {
      outline: none;
      box-shadow: 0 4px 8px rgba(0,0,0,0.24);
      background-color: darken($background-color, 10%);
      color: $text-color;
    }

    &:active {
      box-shadow: 0 2px 4px rgba(0,0,0,0.12);
      background-color: darken($background-color, 5%);
      transform: scale(.96);
    }
  }
}

Abbiamo passato una serie di regole al mixin che verranno inserite al posto della direttiva @content (Per passare le regole, le abbiamo inserite in una coppia di parentesi graffe nel momento in cui abbiamo invocato il mixin). Ripetiamo che è proprio grazie alla direttiva @content che il mixin può ricevere delle proprietà in fase di invocazione e può quindi essere esteso e personalizzato.

Il file style.css che viene generato contiene il seguente frammento di codice.

/* file style.css */
.button {
  box-sizing: border-box;
  text-transform: uppercase;
  border-radius: 3px;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.18);
  padding: 8px 12px;
  border: none;
  font-size: 12px;
  font-family: 'Roboto', Helvetica, sans-serif;
  width: 100px;
  transition: all 0.3s cubic-bezier(0.18, 0.9, 0.18, 1);
  cursor: pointer;
  background-color: #90f8d9;
  color: rgba(46, 45, 77, 0.87);
}

.button:hover {
  transform: scale(1.03);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.24);
  background-color: #78f6d1;
  color: #2e2d4d;
}

.button:focus {
  outline: none;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.24);
  background-color: #60f5c9;
  color: #2e2d4d;
}

.button:active {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
  background-color: #78f6d1;
  transform: scale(0.96);
}

Abbiamo ottenuto lo stesso risultato di prima, ma in maniera diversa.

Mixin, strutture di controllo e cicli

Concludiamo questo articolo osservando che ovviamente è possibile usare sia le strutture di controllo che i cicli o altri mixin all’interno di un certo mixin. In tal modo è possibile creare dei mixin più complessi, ma anche più efficaci.

Conclusioni

In questa lezione abbiamo mostrato come creare e usare i mixin che costituiscono un’altra funzionalità di Sass estremamente utile. Nella prossima lezione illustreremo invece come utilizzare e definire delle funzioni in Sass.

PubblicitÃ