Organizzare e gestire la tipografia con le mappe di SASS

Dopo aver visto come è possibile organizzare e gestire i colori in un progetto grazie alle mappe di SASS vediamo come gestire la tipografia.

La tipografia è leggermente più complessa rispetto ai colori perché ogni singola dichiarazione è composta da più proprietà e come per i colori il primo passo che ho fatto è stato quello di chiedermi come mi sarebbe piaciuto organizzare il file di configurazione per renderlo comprensibile senza impazzire con mille nomi di variabili.

Con questa organizzazione volevo raggiungere sostanzialmente due obiettivi:

  1. Poter stampare tutte le regole associate ad un tag semplicemente chiamando il suo nome
  2. Stampare una regola specifica di un tag

Ho scelto quindi di organizzare la mia mappa per la tipografia in questo modo:

$fonts: (
    h1: (
        font-size: 48px,
        line-height: 1.1,
        font-weight: 700
    ),
    p: (
        font-size: 16px,
        line-height: 1.5,
        font-weight: 400
    ),
    text_small: (
        font-size: 12px
    )
);

Primo obiettivo: stampare tutto le regole associate ad una chiave specifica

Per raggiungere il primo obiettivo l'approccio che seguiremo sarà quello di creare un mixin, che chiameremo "font", che accetti un parametro in ingresso per la chiave e uno per la mappa, che come per i colori imposteremo con un default.

Andiamo quindi a sviluppare il nostro mixin: @mixin font( $type, $map: $font )

A questo punto abbiamo bisogno di ciclare sulle mappe legate ad ogni singola chiave e possiamo farlo utilizzando la funzionalità di @each.

Con il primo ciclo andremo a crearci due variabili che chiameremo $t e $v, rispettivamente con il nome del tag, per esempio h1 e la sua mappa di valori font-size: 48px e così via.

@mixin font( $type, $map: $fonts ) {
    @each $t, $v in $map {
        …
    } } 

Ora che siamo in grado di elencare tutte le chiavi della nostra mappa dobbiamo come prima cosa verificare che quella che stiamo passando al nostro mixin come $type esista veramente e per farlo possiamo usare map-has-key, in caso contrario ritorniamo un errore:

@mixin font( $type, $map: $fonts ) {
    @each $t, $v in $map {
        @if map-has-key( $map, $type ) {
            …
        } @else {
            @error "type non existent";
        } } } 

Siamo arrivati alla conclusione del nostro mixin, non ci resta altro che stampare tutte le regole contenute nella mappa della nostra chiave se corrisponde a quella passata al nostro mixin:

@mixin font( $type, $map: $fonts ) {
    @each $t, $v in $map {
        @if map-has-key( $map, $type ) {
            @if $t == $type {
                @each $prop, $val in $v {
                    #{$prop}: $val;
                } } } @else {
            @error "type non existent";
        } } } 

Secondo obiettivo: stampare una regola specifica di un tag

Il precedente mixin ci permetterà di coprire l'80% buono del nostro progetto, tuttavia potremo aver bisogno in alcuni casi di richiamare una proprietà specifica, per farlo ho scelto di crearmi una funzione che mi ritorna solo il valore di una proprietà e un mixin che funge da shortcut, ma del tutto opzionale.

Vediamo prima la funzione, che chiameremo font-get-property, e accetterà tre parametri in ingresso, la chiave, la proprietà che vogliamo estrarre e la mappa di font di riferimento come nel caso precedente.

Questa funzione a livello di struttura è quasi del tutto simile al mixin precedentemente creato:

@function font-get-property( $type, $property, $map: $fonts ) {
    @each $t, $v in $map {
        @if map-has-key( $map, $type ) {
            @if $t == $type {
                …
            } } @else {
            @error "type non existent";
        } } } 

All'interno del nostro @if a questo punto andremo a valorizzare una variabile $props con la mappa di valori appartenenti alla nostra chiave:

$props: map-get( $map, $type );

sfruttando map-has-key che abbiamo visto precedentemente verificheremo che esista la proprietà che vogliamo estrarre nella mappa e la ritorniamo:

@if map-has-key( $props, $property ) {
    @return map-get( $props, $property );
} @else {
    @error "prop non existent";
} 

La funzione completa sarà la seguente:

@function font-get-property( $type, $property, $map: $fonts ) {
    @each $t, $v in $map {
        @if map-has-key( $map, $type ) {
            @if $t == $type {
                $props: map-get( $map, $type );

                @if map-has-key( $props, $property ) {
                    @return map-get( $props, $property );
                } @else {
                    @error "prop non existent";
                } } } @else {
            @error "type non existent";
        } } } 

e potremo utilizzarla in questo modo:

.main-heading {
    font-size: font-get-property( h1, font-size );
 } 

il che ci porta al mixin di cui parlavo prima, visto che come potete notare con questo approccio dobbiamo scrivere il nome della proprietà due volte.

Possiamo a questo punto creare un mixin che chiameremo font-property, parametrizzato esattamente come la funzione che di fatto si occuperà di stampare proprietà e valore in un colpo solo:

@mixin font-property( $type, $property, $map: $fonts ) {
    #{$property}: font-get-property( $type, $property, $map );
} 

e lo andremo ad applicare in questo modo:

.main-heading {
    @include font-property( h1, font-size );
} 

Non sarà sicuramente il sistema migliore del mondo e c'è ancora qualcosa su cui non sono ancora soddisfatto (ovvero la gestione della parte responsive) ma ritengo sia più strutturato rispetto alle variabili.

Nel prossimo post vedremo come le mappe possono migliorare la gestione delle media queries.

Blog