7 Settembre 2013

Font sizing responsive per sani di mente: conosci i rem?

Piccola confessione: le unità em non sono mai riuscito a sopportarle. Sarò negato in aritmetica, ma dal secondo livello di nesting semplicemente perdo il controllo della situazione: durante la scrittura del CSS non sono più in grado di intuire quanti pixel approssimativamente verrà grosso un dato testo o box. E se non sono i grado io che lo sto scrivendo, figuriamoci il prossimo disperato che dovrà rimetterci le mani sopra tra qualche mese.

Perchè usare gli em?

La ragione storica dell'utilizzo degli em è da imputare al fatto che i browser risalenti a qualche era geologica fa, per applicare uno zoom alla pagina, scalavano proporzionalmente solo il testo. I risultati erano ovviamente terribili, perchè tutti i box che non erano definiti in em ma in px rimanevano invece delle medesime dimensioni.

Oggi fortunatamente tutti i browser scalano proporzionalmente tutte le unità di misura, comprese quelle definite in px, quindi il problema non si pone. Andiamo di pixel, perdio!

La riscossa degli em?

Una nuova necessità nel frattempo invece è diventata fondamentale: garantire un sito visibile sotto qualsiasi dimensione di pagina possibile. I fautori degli em ritornano dunque alla carica, spiegando come con layout totalmente definito in em è possibile scalare proporzionalmente interi blocchi di contenuto modificando unicamente il font-size del blocco padre.

Mettendo da parte il fatto che pensare di ottenere un layout device-independent semplicemente scalando tutte le dimensioni in misura proporzionale è utopistico, l'utilizzo di unità di misura relative alla larghezza della pagina tornerebbe comodo almeno per gestire gli stili base.

L'osservazione iniziale però rimane: gli em sono inutilizzabili, contro-intuitivi, offuscanti e, per quanto mi riguarda, non raccomandabili.

Gestire il responsive con i rem

Esiste un'altra unità che fa al caso nostro. I rem sono sì relativi, ma rispetto al font-size del root element (il tag html, per intenderci).

I browser di default hanno il font-size del tag html pari a 16px, dunque 1rem corrisponderà sempre a 16px, a prescindere dal font-size dei box padri.

Ora che abbiamo una unità di misura “affidabile” e relativa, possiamo preparare una semplicissima serie di mixin Sass per utilizzare i rem alla stregua dei px:

// rem_font_size.css.sass

$base-font-size: 14px !default

=html-font-size($font-size: $base-font-size)
  font-size: percentage($font-size / 16px)

@function rem-size($size)
  @return ($size / $base-font-size) + rem

=font-size($size)
  font-size: $size
  font-size: rem-size($size)

// application.css.sass

@import 'rem_font_size'

$base-font-size: 13px

html
  +html-font-size

  @media screen and (min-width: 600px)
    +html-font-size(16px)

h1
  +font-size(20px)

In questo esempio, stiamo realizzando un layout mobile-first: il font-size standard della pagina viene impostato a 13px grazie al mixin html-font-size, e tutte le dimensioni sono espresse in pixel nel foglio di stile Sass (massima leggibilità), ma producono regole CSS in rem, con fallback in px per browser meno recenti (che comunque non supporterebbero le media queries).

A questo punto è sufficiente aggiungere una @media query a livello di tag html modificando il font-size del solo root element, per vedere aumentare proporzionalmente tutte le dimensioni espresse in rem.

Demo su CodePen