Con centinaia di framework e UI kit, stiamo assemblando ogni tipo di blocchi di contenuto per creare pagine web. Tuttavia, una tale modularità e versatilità non è ancora stata raggiunta a livello degli elementi web. Imparando dal Lego, possiamo spingere il web design modulare un passo più in là.
Il modular atomic design è in giro da un po’. Concettualmente, lo amiamo tutti: i componenti web dovrebbero essere versatili e riutilizzabili. Dovremmo essere in grado di posizionarli come mattoni, incastrandoli in qualsivoglia maniera senza preoccuparsi di cambiare alcunché nel codice.
Finora, l’abbiamo fatto a livello del blocco di contenuto: ogni blocco occupa un’intera riga, ha una larghezza consistente ed è self-contained. Adesso, siamo in grado di assemblare diversi blocchi per realizzare pagine web senza dover considerare gli stili e gli elementi all’interno di ciascun blocco. È un grande passo in avanti e ha portato all’esplosione di framework e UI kit, rendendo il design delle pagine web modulare e anche più accessibile alle masse.
Ottenere una simile modularità a livello dell’elemento web non è così semplice. Pattern Lab dice che dovremmo essere in grado di mettere i pattern UI uno all’interno dell’altro come le matrioske. Ma, pensando alle matrioske, ogni layer ha il suo spessore, l’equivalente di padding e margin nel web design. Quando una matrioska a tre layer viene messa vicino a una matrioska a sette layer, lo spazio tra queste è incostante. Mentre non è un grande problema con le matrioske, sulle pagine web potrebbe portare o a un white space mal distribuito o a sovrascrivere più livelli di CSS.
Per anni, ho utilizzato Bootstrap e Foundation e questo è esattamente quello che succede quando cercavo di scrivere layout complessi all’interno di quei framework: righe annidate in colonne annidate in righe, piccoli elementi in elementi più grandi, tutti con i propri padding e margin come le matrioske. Poi dovevo gestire i problemi di nesting, togliere il padding eccessivo su first-
e last-child
, calcolare, sovrascrivere, aggiungere commenti qua e là.
Non era la cosa più carina che avrei potuto fare ai miei fogli di stile, ma era ancora tollerabile. Poi sono andata a lavorare in Graphiq, una knowledge company che realizza data visualization su più di 700 argomenti diversi. Qui, ai content editor è permesso inserire qualsiasi dato vogliano, in qualunque formato vogliano, per creare la miglior esperienza possibile per i propri lettori. Tale flessibilità ha senso per le piccole startup e noi abbiamo un’interfaccia drag-and-drop che aiuta ad organizzare tutto da un singolo data point a infografiche e grafici, a colonne, blocchi e card. I content editor possono anche aggiungere logica al layout della pagina. Due grafici a barre uno accanto all’altro potrebbero finire in strutture HTML piuttosto diverse. Come potete immaginare, questo livello di versatilità risulta spesso in un inferno di styling per i designer e i developer. Sebbene una soluzione davvero promettente, CSS Grid Layout, sia all’orizzonte, non è ancora approdata in Chrome. E potrebbero volerci anni per noi per adattarci completamente a un nuovo attributo display
. Questo mi ha portato a pensare che se possiamo cambiare la mentalità matrioska, possiamo fare un altro passo avanti verso il design modulare con gli strumenti che abbiamo a disposizione.
Imparare dal Lego#section1
Per trovare una metafora migliore, sono tornata al Lego, l’epitomo del modular atomic design. È saltato fuori che non dobbiamo mai preoccuparci di padding e margin quando “annidiamo” una piccola struttura Lego in una grande struttura Lego e poi in una struttura Lego ancora più grande. In effetti, non c’è un concetto simile al “nesting” nel Lego. Tutti gli elementi sembrano vivere allo stesso livello, non su layer multipli.
Ma questo cosa significa per il web design? Noi dobbiamo annidare gli elementi web per la struttura semantica e per selezionare facilmente. Non sto dicendo che dovremmo cambiare le nostre strutture HTML, ma nei nostri fogli di stile potremmo mettere la spaziatura solo sugli elementi web di livello più basso (o “atomi” per citare la terminologia dell’atomic design) e non i molti layer che si trovano in mezzo.
Date uno sguardo alla parte superiore di ogni singolo mattoncino Lego. Se immaginate che lo spazio attorno l’esterno dei piroli sia il padding di un elemento web e tutto quello che sta all’interno del padding sia il contenuto, scoprirete che tutti i mattoncini Lego hanno un padding consistente attorno al contenuto, che è esattamente la metà dello spazio tra gli elementi.
Non importa quanti piroli abbia un mattoncino: il padding attorno a questi è lo stesso che c’è su ogni altro Lego.
E quando si mettono assieme i mattoncini Lego, tutti gli elementi avranno tra loro lo stesso gutter.
Il padding si estende dal punto più esterno dei piroli di un mattoncino al punto piùx esterno dei piroli del mattoncino vicino.
Non serve altro padding o margin: gli spazi si formano naturalmente. Tutti gli elementi, non importa quanto siano annidati profondamente, appaiono sullo stesso livello e non servono altre sovrascritture CSS o aggiustamenti, nemmeno i reset di first-
e last-child
.
Mettendo tutto questo nel codice, possiamo creare una class che aggiunga la spaziatura half-gutter e applicarla a tutti gli elementi web di livello più basso sulla pagina. Poi possiamo rimuovere tutta la spaziatura sui div
strutturali come .row
e .col
.
$gutter: 20px;
.element {
padding: $gutter / 2;
}
Una piccolissima modifica di cui essere consapevoli è che quando il padding è solo su .element
, il padding tra gli elementi più esterni e il div
padre dovrà essere solo la metà del gutter.
Il margine esterno è solo la metà del gutter, per ora.
Dobbiamo aggiungere lo stesso padding anche al container più esterno.
Il container più esterno con metà gutter aggiunto tutto intorno.
$gutter: 20px;
.container,
.element {
padding: $gutter / 2;
}
E tutto ciò risulterà in questo:
Con l’aggiunta del padding più esterno, tutto il padding sembra uguale.
Pensate a quanti layer di sovrascrittura avremmo bisogno per creare questo layout con l’attuale mentalità a righe e colonne. Il meglio che possiamo fare probabilmente è qualcosa così:
Lo stesso layout con righe e colonne.
E nel codice: Vedi su Codepen.
Con la mentalità Lego, la spaziatura e il codice possono essere molto più semplici, come mostrato nei due esempi sottostanti:
Esempio con div: Vedi su Codepen.
Esempio con Flexbox: Vedi su Codepen.
Più flessibile del Lego#section2
Il Lego è davvero una soluzione adatta a tutto. Con il Lego, non dobbiamo modificare leggermente il padding dei mattoncini a seconda dei nostri progetti e non possiamo avere padding orizzontali e verticali diversi. Il web design ci offre molte più variazioni in quest’area.
Invece di impostare un unico valore come il gutter, possiamo impostare quattro variabili diverse e ottenere un layout più flessibile in questo modo:
$padding-x: 10px;
$padding-y: 20px;
$padding-outer-x: 40px;
$padding-outer-y: 30px;
.container {
padding: $padding-outer-y $padding-outer-x;
}
.element {
padding: ($padding-y / 2) ($padding-x / 2);
}
Il risultato ha questo aspetto:
A differenza dei pezzi Lego reali, possiamo impostare diversi valori per il padding.
È ancora modulare, ma ha anche spazi variabili per creare uno stile più dinamico.
Con il responsive design, potremmo anche volere spaziature diverse per media query diverse. Possiamo spingere questo approccio un passo più in là e scrivere la logica in un mixin Sass (in alternativa, potete farlo anche con LESS):
@mixin layout ($var) {
$padding-x: map-get($var, padding-x);
$padding-y: map-get($var, padding-y);
$padding-outer-x: map-get($var, padding-outer-x);
$padding-outer-y: map-get($var, padding-outer-y);
.container {
padding: $padding-outer-y $padding-outer-x;
}
.element {
padding: ($padding-y / 2) ($padding-x / 2);
}
}
Usando questo mixin, possiamo inserirgli diverse mappature di spaziature per generare regole CSS per differenti media query:
// Variabili di spaziatura
$spacing: (
padding-x: 10px,
padding-y: 20px,
padding-outer-x: 40px,
padding-outer-y: 30px
);
$spacing-tablet: (
padding-x: 5px,
padding-y: 10px,
padding-outer-x: 20px,
padding-outer-y: 15px
);
// Genera regole CSS di default
@include layout($spacing);
// Genera regole CSS per la visualizzazione tablet
@media (max-width: 768px) {
@include layout($spacing-tablet);
}
E in maniera altrettanto semplice, tutti i nostri elementi avranno ora una spaziatura diversa nella vista desktop e in quella tablet.
Esempio live: Vedi su Codepen.
Discussione#section3
Dopo aver usato questo metodo per quasi un anno, mi sono imbattuta in alcune domande frequenti e casi limite che vorrei affrontare.
Background e border#section4
Quando aggiungete background e border agli elementi web, non applicateli al div
.element
. Il background coprirà sia il contenuto sia le aree di padding dell’elemento, quindi romperà la griglia visivamente in questo modo:
Un background applicato a
.element
rompe la griglia.
Al contrario, applicate il background al div
figlio all’interno del div
.element
:
<div class="element">
<div style="background-image:url();"></div>
</div>
Un
div
figlio contiene l’immagine, così non si rompe la griglia.
Ho usato questa struttura in tutti i miei esempi precedenti.
In maniera simile, il border va attorno al padding nel box model, così dovremmo applicare anche il border dell’elemento a un div
figlio per mantenere la corretta spaziatura.
Come con il background, applicate il bordo a un
div
figlio.
Elementi full row#section5
Un’altra questione comune si ha quando occasionalmente vogliamo degli elementi full row, concettualmente così:
A volte vogliamo interrompere la griglia con degli elementi a riga intera.
Per assegnare degli stili agli elementi riga seguendo la struttura di .container
e .element
, dobbiamo usare il margin negativo:
.element-full-row {
margin: 0 (-$padding-outer-x);
padding: ($padding-y / 2) ($padding-x / 2 + $padding-outer-x);
}
Notate che dobbiamo aggiungere di nuovo il $padding-outer-x
al padding, così che il contenuto in .element-full-row
sia allineato al contenuto in .element
.
Il contenuto di
.element-full-row
si allinea con il contenuto di .element
align.
Il codice di prima gestisce la spaziatura orizzontale e la stessa logica può essere applicata anche per sostituire la spaziatura verticale (come mostrato nell’esempio sopra: l’elemento header sostituisce il padding superiore). Possiamo aggiungere anche un margine negativo molto facilmente nei nostri fogli di stile.
.element-full-row:first-child {
margin: (-$padding-outer-y) (-$padding-outer-x) 0;
padding: ($padding-y / 2 + $padding-outer-y) ($padding-x / 2 + $padding-outer-x) ($padding-y / 2);
}
Potete applicarla come regola standalone o includerla nel mixin Sass o LESS, poi non dovrete più preoccuparvene.
Annidamento#section6
La libertà completa nell’annidamento è quello in cui eccelle questo metodo CSS Lego. Tuttavia, c’è un tipo di annidamento che non possiamo fare: non possiamo annidare un .element
all’interno di un .element
. Questo creerebbe un padding doppio e la ragion d’essere di questo metodo andrebbe persa. Questo è il motivo per cui si dovrebbe applicare la class .element
solo agli elementi web di livello più basso (o “atomi” per usare la terminologia dell’atomic design) come un pulsante, una input box, una text box, un’immagine, etc.
Prendiamo in considerazione questa comment box molto generica.
Invece di trattarla come un singolo “elemento”, dobbiamo trattarla come un gruppo pre-definito di elementi (titolo, textarea, button e helper text):
<div class="comment">
<h3 class="comment-title element">Add a new comment</h3>
<textarea class="element"></textarea>
<div class="clearfix">
<div class="float-left">
<div class="element">
<button class="btn-post">Post comment</button>
</div>
</div>
<div class="float-right">
<div class="helper-text element">
<i class="icon-question"></i>
Some HTML is OK.
</div>
</div>
</div>
</div>
Poi, possiamo trattare .comment
come un componente riutilizzabile o, nel contesto dell’atomic design, come una “molecola”, che si comporterà bene con altri componenti riutilizzabili scritti nella stessa maniera e potrà essere raggruppata in strutture HTML di più alto livello. E, indipendentemente da come le organizzerete, la spaziatura tra esse sarà sempre corretta.
Altezze e layout variabili#section7
Per la maggior parte di questo articolo, abbiamo usato lo stesso esempio di fitted row. Questo potrebbe portare alcuni a pensare che questo metodo funzioni solo per elementi con altezza e larghezza definiti.
In realtà, è più versatile di così. Non importa in che modo gli elementi cambino in altezza e larghezza, lazy load, o float attorno, il padding simile al Lego assicura lo stesso spazio consistente tra gli elementi.
Ho creato un rapido flow layout di Pinterest per dimostrare in che modo funziona questa mentalità con elementi fluidi e che cambiano.
Mantenimento#section8
Alcuni tra voi potrebbero anche preoccuparsi dei costi di mantenimento. In effetti, ci vuole del tempo per apprendere questo nuovo metodo, ma una volta che si inizia ad adottare questa mentalità e a scrivere i CSS in questo modo, il mantenimento diventa estremamente semplice.
Specialmente con i layout mixin, tutte le regole di spaziatura sono centralizzate e controllate da alcuni gruppi di variabili. Un singolo cambiamento nelle variabili verrà propagato automaticamente a tutti gli elementi sulla pagina web.
In confronto, potremmo dover cambiare padding e margin in 20 posti diversi con il vecchio metodo e poi dovremmo testare per essere sicuri che funzioni ancora tutto. Sarebbe un processo molto più movimentato.
Grid layout#section9
Infine, c’è il Grid layout, che supporta layout molto complicati e annida in maniera molto più graceful che i blocchi. Potreste pensare che si tratti di un lavoro piuttosto duro per un problema che va scomparendo.
Mentre molte delle questioni di cui abbiamo parlato in questo articolo potrebbero sparire con Grid, potrebbero volerci degli anni perché Grid venga supportato dai browser. E poi, potrebbe volerci molto tempo perché la community acquisisca familiarità con il nuovo metodo e sviluppi delle best practice e dei framework attorno ad esso. Come Flex, è già supportato dalla maggior parte dei browser, ma è ben lungi dall’essere ampiamente adottato.
E dopo tutto, potrebbe volerci molto tempo per un tipico utente web per capire Grid e il suo funzionamento. In maniera simile richiederebbe a noi molto sviluppo tradurre lo user layout input in buon codice CSS Grid. Il vecchio metodo a colonne e righe è molto più semplice da capire e quando il nesting non è un problema, potrebbe essere una buona soluzione per siti web che permettono agli utenti di fare delle configurazioni.
Conclusioni#section10
Abbiamo cominciato ad implementare questo metodo in Graphiq all’inizio del 2016. Dopo quasi un anno, lo adoriamo e crediamo sia il modo in cui dovremmo scrivere i layout web nel futuro. Man mano che facciamo il refactor di ogni pagina, stiamo cancellando centinaia di righe di vecchio codice CSS e rendendo i fogli di stile molto più logici e molto più semplici da leggere. Abbiamo anche molti meno bug nei layout e nelle spaziature rispetto a tutti i nostri refactor del passato. Ora, non importa come i nostri content editor decidano di annidare i loro data point, abbiamo molto poco di cui preoccuparci.
Da quello che abbiamo visto questo è un vero game changer nel modo in cui pensiamo ai nostri layout e come li trasformiamo in codice. Quando i componenti web sono flessibili come i mattoncini Lego fino a livello degli elementi, diventano molto più versatili e facili da mantenere. Crediamo che questo sia il prossimo passo da fare nel web design modulare. Provatelo voi stessi: potrebbe cambiare il modo in cui scrivete le vostre pagine web.
Nessun commento
Altro da ALA
Webwaste
Uno strumento essenziale per catturare i vostri progressi lavorativi
Andiamo al cuore dell’accessibilità digitale
JavaScript Responsabile, Parte II
JavaScript Responsabile: parte prima