Disposizione del testo attorno a percorsi personalizzati
Per molto tempo, i web designer sono stati costretti a creare entro i vincoli del rettangolo. La maggior parte dei contenuti sul web è ancora intrappolata in semplici riquadri perché la maggior parte delle iniziative creative con layout non rettangolari finisce per essere frustrante. La situazione sta per cambiare con l'introduzione delle forme CSS, disponibili a partire da Chrome 37. Le forme CSS consentono ai web designer di inserire contenuti attorno a percorsi personalizzati, come cerchi, ellissi e poligoni, liberandosi così dai vincoli del rettangolo.
Le forme possono essere definite manualmente o dedotte dalle immagini.
Vediamo un esempio molto semplice.
Forse hai avuto la mia stessa ingenuità quando hai provato per la prima volta a posizionare un'immagine con parti trasparenti, aspettandoti che i contenuti si adattassero e riempissero gli spazi vuoti, per poi rimanere deluso dalla forma rettangolare del testo che persisteva attorno all'elemento. Le forme CSS possono essere utilizzate per risolvere questo problema.
<img class="element" src="image.png" />
<p>Lorem ipsum…</p>
<style>
.element{
shape-outside: url(image.png);
shape-image-threshold: 0.5;
float: left;
}
</style>
La dichiarazione CSS shape-outside: url(image.png) indica al browser di estrarre una forma dall'immagine.
La proprietà shape-image-threshold definisce il livello minimo di opacità dei pixel che verranno utilizzati per creare la forma. Il suo valore deve essere compreso tra 0.0 (completamente trasparente) e 1.0 (completamente opaco). Pertanto, shape-image-threshold: 0.5 significa che per creare la forma verranno utilizzati solo i pixel con opacità pari o superiore al 50%.
La proprietà float è fondamentale in questo caso. Sebbene la proprietà shape-outside definisca la forma dell'area attorno alla quale verrà disposto il contenuto, senza il float non vedrai gli effetti della forma.
Gli elementi hanno un'area mobile sul lato opposto del valore float. Ad esempio, se un elemento con l'immagine di una tazza di caffè viene spostato a sinistra, l'area di spostamento verrà creata a destra della tazza. Anche se puoi progettare un'immagine con spazi vuoti su entrambi i lati, i contenuti verranno disposti intorno alla forma solo sul lato opposto designato dalla proprietà float, a sinistra o a destra, mai su entrambi.
In futuro, sarà possibile utilizzare shape-outside su elementi che non sono mobili con l'introduzione delle esclusioni CSS.
Creazione manuale delle forme
Oltre a estrarre le forme dalle immagini, puoi anche codificarle manualmente. Puoi scegliere tra alcuni valori funzionali per creare forme: circle(), ellipse(), inset() e polygon(). Ogni funzione di forma accetta un insieme di coordinate ed è associata a una casella di riferimento che stabilisce il sistema di coordinate. A breve parleremo più nel dettaglio delle caselle di riferimento.
La funzione circle()
La notazione completa per un valore di forma circolare è circle(r at cx cy), dove r è il raggio del cerchio, mentre cx e cy sono le coordinate del centro del cerchio sull'asse X e sull'asse Y. Le coordinate del centro del cerchio sono facoltative. Se li ometti, verrà utilizzato per impostazione predefinita il centro dell'elemento (l'intersezione delle sue diagonali).
.element{
shape-outside: circle(50%);
width: 300px;
height: 300px;
float: left;
}
Nell'esempio precedente, i contenuti verranno disposti intorno all'esterno di un percorso circolare. L'argomento singolo 50% specifica il raggio del cerchio, che in questo caso specifico equivale alla metà della larghezza o dell'altezza dell'elemento. La modifica delle dimensioni dell'elemento influirà sul raggio della forma circolare. Questo è un esempio di base di come le forme CSS possono essere adattabili.
Prima di andare oltre, una breve parentesi: è importante ricordare che le forme CSS influenzano solo la forma dell'area mobile attorno a un elemento. Se l'elemento ha uno sfondo, questo non verrà ritagliato dalla forma. Per ottenere questo effetto, devi utilizzare le proprietà di CSS Masking, ovvero clip-path o mask-image. La proprietà clip-path è molto utile perché segue la stessa notazione delle forme CSS, quindi puoi riutilizzare i valori.
Le illustrazioni di questo documento utilizzano il ritaglio per evidenziare la forma e aiutarti a comprendere gli effetti.
Torniamo alla forma del cerchio.
Quando utilizzi le percentuali per il raggio del cerchio, il valore viene effettivamente calcolato con una formula leggermente più complessa: sqrt(width^2 + height^2) / sqrt(2). È utile comprenderlo perché ti aiuterà a immaginare quale sarà la forma del cerchio risultante se le dimensioni dell'elemento non sono uguali.
Tutti i tipi di unità CSS possono essere utilizzati nelle coordinate della funzione shape: px, em, rem, vw, vh e così via. Puoi scegliere quello più flessibile o rigido in base alle tue esigenze.
Puoi regolare la posizione del cerchio impostando valori espliciti per le coordinate del suo centro.
.element{
shape-outside: circle(50% at 0 0);
}
In questo modo, il centro del cerchio viene posizionato nell'origine del sistema di coordinate. Qual è il sistema di coordinate? È qui che introduciamo i riquadri di riferimento.
Riquadri di riferimento per le forme CSS
La casella di riferimento è una casella virtuale attorno all'elemento, che stabilisce il sistema di coordinate utilizzato per disegnare e posizionare la forma. L'origine del sistema di coordinate si trova nell'angolo in alto a sinistra, con l'asse X rivolto verso destra e l'asse Y rivolto verso il basso.
Ricorda che shape-outside altera la forma dell'area mobile attorno alla quale verrà disposto il contenuto. L'area mobile si estende ai bordi esterni della casella definita dalla proprietà margin. Questa è chiamata margin-box ed è la casella di riferimento predefinita per una forma se non ne viene menzionata esplicitamente una.
Le seguenti due dichiarazioni CSS hanno risultati identici:
.element{
shape-outside: circle(50% at 0 0);
/* identical to: */
shape-outside: circle(50% at 0 0) margin-box;
}
Non abbiamo ancora impostato un margine sull'elemento. A questo punto, è lecito presumere che l'origine del sistema di coordinate e il centro del cerchio si trovino nell'angolo in alto a sinistra dell'area dei contenuti dell'elemento. Questo cambia quando imposti un margine:
.element{
shape-outside: circle(50% at 0 0) margin-box;
margin: 100px;
}
L'origine del sistema di coordinate ora si trova al di fuori dell'area dei contenuti dell'elemento (100 px in alto e 100 px a sinistra), così come il centro del cerchio. Anche il valore calcolato del raggio del cerchio aumenta per tenere conto della superficie aumentata del sistema di coordinate stabilito dalla casella di riferimento margin-box.
È possibile utilizzare una sola casella di riferimento alla volta con una dichiarazione shape-outside. Ogni casella di riferimento influenzerà la forma in modo diverso e talvolta impercettibile. C'è un altro articolo che approfondisce l'argomento e vi aiuta a comprendere le caselle di riferimento per le forme CSS.
La funzione ellipse()
Le ellissi sembrano cerchi schiacciati. Sono definite come ellipse(rx ry at cx cy), dove rx e ry sono i raggi dell'ellisse sull'asse X e sull'asse Y, mentre cx e cy sono le coordinate del centro dell'ellisse.
.element{
shape-outside: ellipse(150px 300px at 50% 50%);
width: 300px;
height: 600px;
}
I valori percentuali verranno calcolati in base alle dimensioni del sistema di coordinate. Non servono calcoli complessi. Puoi omettere le coordinate del centro dell'ellisse, che verranno dedotte dal centro del sistema di coordinate.
I raggi sugli assi X e Y possono essere definiti anche con parole chiave: farthest-side produce un raggio pari alla distanza tra il centro dell'ellisse e il lato del riquadro di riferimento più lontano, mentre closest-side significa l'esatto opposto, ovvero utilizza la distanza più breve tra il centro e un lato.
.element{
shape-outside: ellipse(closest-side farthest-side at 50% 50%);
/* identical to: */
shape-outside: ellipse(150px 300px at 50% 50%);
width: 300px;
height: 600px;
}
Questo può essere utile quando le dimensioni dell'elemento (o della casella di riferimento) possono cambiare in modi imprevedibili, ma vuoi che la forma dell'ellisse si adatti.
Le stesse parole chiave farthest-side e closest-side possono essere utilizzate anche per il raggio nella funzione di forma circle().
La funzione polygon()
Se cerchi qualcosa di più di cerchi ed ellissi, la funzione di forma poligonale ti offre un mondo di opzioni. Il formato è polygon(x1 y1, x2 y2, ...), dove specifichi coppie di coordinate x e y per ogni vertice (punto) di un poligono. Il numero minimo di coppie per specificare un poligono è tre, un triangolo.
.element{
shape-outside: polygon(0 0, 0 300px, 300px 600px);
width: 300px;
height: 600px;
}
I vertici sono posizionati sul sistema di coordinate. Per i poligoni adattabili, puoi utilizzare valori percentuali per alcune o tutte le coordinate.
.element{
/* polygon responsive to font-size*/
shape-outside: polygon(0 0, 0 100%, 100% 100%);
width: 20em;
height: 40em;
}
Esiste un parametro fill-rule facoltativo, importato da SVG, che indica al browser come considerare l'"internità" di un poligono in caso di percorsi che si intersecano o forme chiuse. Joni Trythall spiega molto bene come funziona la proprietà fill-rule in SVG. Se non definito, il valore predefinito di fill-rule è nonzero.
.element{
shape-outside: polygon(0 0, 0 100%, 100% 100%);
/* identical to: */
shape-outside: polygon(nonzero, 0 0, 0 100%, 100% 100%);
}
La funzione inset()
La funzione di forma inset() consente di creare forme rettangolari attorno alle quali disporre i contenuti. Questo potrebbe sembrare controintuitivo considerando la premessa iniziale secondo cui le forme CSS liberano i contenuti web dalle semplici caselle. Potrebbe essere così. Devo ancora trovare un caso d'uso per inset() che non sia già realizzabile con float e margini o con un polygon(). Tuttavia, inset() fornisce un'espressione più leggibile per le forme rettangolari rispetto a polygon().
La notazione completa per una funzione di forma inset è inset(top right bottom left border-radius). I primi quattro argomenti di posizione sono gli offset verso l'interno dai bordi dell'elemento. L'ultimo argomento è il raggio del bordo della forma rettangolare. È facoltativo, quindi puoi ometterlo. Segue la notazione abbreviata border-radius che utilizzi già in CSS.
.element{
shape-outside: inset(100px 100px 100px 100px);
/* yields a rectangular shape which is 100px inset on all sides */
float: left;
}
Creazione di forme da caselle di riferimento
Se non specifichi una funzione di forma per la proprietà shape-outside, puoi consentire al browser di derivare una forma dalla casella di riferimento dell'elemento. La casella di riferimento predefinita è margin-box. Finora niente di strano, è così che funzionano già i float. Tuttavia, applicando questa tecnica, puoi riutilizzare la geometria di un elemento. Diamo un'occhiata alla proprietà border-radius.
Se la utilizzi per arrotondare gli angoli di un elemento con float, ottieni l'effetto di ritaglio, ma l'area con float rimane rettangolare. Aggiungi shape-outside: border-box per avvolgere il contorno creato da border-radius.
.element{
border-radius: 50%;
shape-outside: border-box;
float: left;
}
Naturalmente, puoi utilizzare tutte le caselle di riferimento in questo modo. Ecco un altro utilizzo delle forme derivate: le citazioni in evidenza con offset.
È possibile ottenere l'effetto di citazione con offset utilizzando solo le proprietà float e margin. Tuttavia, questo richiede di posizionare l'elemento della citazione nell'albero HTML nel punto in cui vuoi che venga visualizzato.
Ecco come ottenere lo stesso effetto di citazione con offset con una maggiore flessibilità:
.pull-quote{
shape-outside: content-box;
margin-top: 200px;
float: left;
}
Impostiamo esplicitamente la casella di riferimento content-box per il sistema di coordinate della forma. In questo caso, la quantità di contenuti nella citazione definisce la forma attorno alla quale verranno inseriti i contenuti esterni. La proprietà margin-top viene utilizzata qui per posizionare (offset) la citazione, indipendentemente dalla sua posizione nell'albero HTML.
Margine forma
Noterai che l'inserimento di contenuti intorno a una forma può farli avvicinare troppo all'elemento. Puoi aggiungere spaziatura intorno alla forma con la proprietà shape-margin.
.element{
shape-outside: circle(40%);
shape-margin: 1em;
float: left;
}
L'effetto è simile a quello a cui sei abituato con la proprietà margin normale, ma shape-margin influisce solo sullo spazio intorno al valore shape-outside. Aggiungerà spaziatura intorno alla forma solo se c'è spazio nel sistema di coordinate. Ecco perché nell'esempio precedente il raggio del cerchio è impostato su 40% e non su 50%. Se il raggio fosse stato impostato su 50%, il cerchio avrebbe occupato tutto lo spazio nel sistema di coordinate, non lasciando spazio per l'effetto di shape-margin. Ricorda che la forma è in ultima analisi limitata al margin-box dell'elemento (l'elemento più il margin circostante). Se la forma è più grande e si espande oltre i limiti, verrà ritagliata in base al margin-box e otterrai una forma rettangolare.
È importante capire che shape-margin accetta un solo valore positivo. Non ha una notazione estesa. Che cos'è un margine superiore della forma per un cerchio?
Animazione delle forme
Puoi combinare le forme CSS con molte altre funzionalità CSS, come transizioni e animazioni. Tuttavia, devo sottolineare che gli utenti trovano molto fastidioso quando il layout del testo cambia mentre stanno leggendo. Se decidi di animare le forme, presta molta attenzione all'esperienza.
Puoi animare i raggi e i centri delle forme circle() e ellipse(), purché siano definiti in valori che il browser può interpolare. È possibile passare da circle(30%) a circle(50%). Tuttavia, l'animazione tra circle(closest-side) e circle(farthest-side) bloccherà il browser.
.element{
shape-outside: circle(30%);
transition: shape-outside 1s;
float: left;
}
.element:hover{
shape-outside: circle(50%);
}
È possibile ottenere effetti più interessanti quando si animano le forme polygon(), con l'importante nota che il poligono deve avere lo stesso numero di vertici tra i due stati dell'animazione. Il browser non può eseguire l'interpolazione se aggiungi o rimuovi vertici.
Un trucco consiste nell'aggiungere il numero massimo di vertici necessari e posizionarli raggruppati nello stato di animazione in cui vuoi che la forma abbia meno bordi percepiti.
.element{
/* four vertices (looks like rectangle) */
shape-outside: polygon(0 0, 100% 0, 100% 100%, 0 100%);
transition: shape-outside 1s;
}
.element:hover{
/* four vertices, but second and third overlap (looks like triangle) */
shape-outside: polygon(0 0, 100% 50%, 100% 50%, 0 100%);
}
Adattamento del testo all'interno di una forma
La bozza iniziale della specifica CSS Shapes includeva una proprietà shape-inside che consentiva di inserire i contenuti all'interno di una forma. Per un certo periodo sono state implementate anche in Chrome e Webkit. Tuttavia, l'inserimento di contenuti posizionati in modo arbitrario all'interno di un percorso personalizzato richiede molto più impegno e ricerca per coprire tutti i possibili scenari ed evitare bug. Per questo motivo, la proprietà shape-inside è stata posticipata a CSS Shapes Level 2 e le relative implementazioni sono state ritirate.
Tuttavia, con un po' di impegno e qualche compromesso, puoi comunque ottenere l'effetto di andare a capo all'interno di una forma personalizzata. Il trucco consiste nell'utilizzare due elementi mobili con shape-outside, posizionati sui lati opposti di un contenitore. Il compromesso è che devi utilizzare uno o due elementi vuoti che non hanno un significato semantico, ma fungono da supporti per creare l'illusione di una forma all'interno.
<div>
<div class='left-shape'></div>
<div class='right-shape'></div>
Lorem ipsum...
</div>
La posizione degli elementi strut .left-shape e .right-shape nella parte superiore del container è importante perché verranno spostati a sinistra e a destra per affiancare i contenuti.
.left-shape{
shape-outside: polygon(0 0, ...);
float: left;
width: 50%;
height: 100%;
}
.right-shape{
shape-outside: polygon(50% 0, ...);
float: right;
width: 50%;
height: 100%;
}
Questo stile fa sì che i due elementi fluttuanti occupino tutto lo spazio all'interno dell'elemento, ma le proprietà shape-outside ritagliano spazio per il resto dei contenuti.
Se le forme CSS non sono supportate dal browser, si otterranno effetti sgradevoli, in quanto tutti i contenuti verranno spostati verso il basso. Ecco perché è importante utilizzare la funzionalità in modo da ottenere un potenziamento progressivo.
Negli esempi precedenti di animazione delle forme, noterai che lo spostamento del testo può essere fastidioso. Non tutti i casi d'uso richiedono una forma animata. Tuttavia, puoi animare altre proprietà che interagiscono con le forme CSS per aggiungere effetti dove opportuno.
Nella dimostrazione di CSS Shapes di Alice nel Paese delle Meraviglie, abbiamo utilizzato la posizione di scorrimento per modificare il margine superiore dei contenuti. Il testo è compresso tra due elementi mobili. Man mano che si sposta verso il basso, deve essere rimpaginato in base alla shape-outside dei due elementi mobili. Questo dà l'impressione che il testo stia scendendo nella tana del coniglio e aggiunge un tocco di storytelling all'esperienza. Caso limite di contenuti senza costi? Forse. Ma è bello.
Poiché il layout del testo viene eseguito in modo nativo dal browser, le prestazioni sono migliori rispetto all'utilizzo di una soluzione JavaScript. Tuttavia, la modifica di margin-top durante lo scorrimento attiva molti eventi di ricalcolo del layout e di visualizzazione, il che potrebbe ridurre notevolmente le prestazioni. Da usare con cautela. Tuttavia, l'utilizzo di CSS Shapes senza animazione non comporta un impatto percepibile sulle prestazioni.
Potenziamento progressivo
Inizia supponendo che il browser non supporti le forme CSS e, se rilevi la funzionalità, aggiungi il supporto. Modernizr è una buona soluzione per eseguire il rilevamento delle funzionalità ed è disponibile un test per le forme CSS nella sezione "Non-core detects".
Alcuni browser forniscono il rilevamento delle funzionalità in CSS tramite la regola @supports senza la necessità di librerie esterne. Google Chrome, che supporta anche le forme CSS, comprende la regola @supports. Ecco come utilizzarlo per il potenziamento progressivo:
.element{
/* styles for all browsers */
}
@supports (shape-outside: circle(50%)){
/* styles only for browsers which support CSS Shapes */
.element{
shape-outside: circle(50%);
}
}
Lea Verou ha scritto di più su come utilizzare la regola @supports di CSS.
Disambiguazione dalle esclusioni CSS
Quello che oggi conosciamo come CSS Shapes si chiamava CSS Exclusions and Shapes nei primi giorni della specifica. Il cambio di nome potrebbe sembrare una sfumatura, ma in realtà è molto importante. CSS Exclusions, ora una specifica separata, consente di avvolgere i contenuti attorno a elementi posizionati arbitrariamente, senza la necessità di una proprietà float. Immagina di avvolgere i contenuti attorno a un elemento con posizionamento assoluto: questo è un caso d'uso per le esclusioni CSS. Le forme CSS definiscono semplicemente il percorso attorno al quale verranno disposti i contenuti.
Quindi, le forme e le esclusioni non sono la stessa cosa, ma si completano a vicenda. Le forme CSS sono disponibili nei browser oggi, mentre le esclusioni CSS non sono ancora implementate con l'interazione delle forme.
Strumenti per lavorare con le forme CSS
Puoi creare percorsi nei classici strumenti di creazione di immagini, ma nessuno di questi, al momento della stesura di questo articolo, esporta la sintassi richiesta per i valori delle forme CSS. Anche se lo facessero, lavorare in questo modo non sarebbe molto pratico.
Le forme CSS sono pensate per essere utilizzate nel browser, dove reagiscono ad altri elementi della pagina. È molto utile visualizzare gli effetti della modifica della forma sui contenuti che la circondano. Esistono alcuni strumenti che possono aiutarti in questo flusso di lavoro:
Brackets: l'estensione CSS Shapes Editor per Brackets utilizza la modalità di anteprima dal vivo dell'editor di codice per sovrapporre un editor interattivo per la modifica dei valori delle forme.
Google Chrome: l'estensione CSS Shapes Editor per Google Chrome estende gli Strumenti per sviluppatori del browser con controlli per creare e modificare le forme. Posiziona un editor interattivo sopra l'elemento selezionato.
L'inspector di Google Chrome ha un supporto integrato per l'evidenziazione delle forme. Passa il mouse sopra un elemento con una proprietà shape-outside per evidenziare la forma.
Forme dalle immagini: se preferisci generare immagini e fare in modo che il browser ne estragga le forme, Rebecca Hauck ha scritto un buon tutorial per Photoshop.
Polyfill: Google Chrome è il primo browser principale a supportare le forme CSS. È previsto il supporto per la funzionalità su iOS 8 e Safari 8 di Apple. Altri fornitori di browser potrebbero prenderlo in considerazione in futuro. Fino ad allora, è disponibile un polyfill per le forme CSS per fornire un supporto di base.
Conclusione
In un web in cui i contenuti sono per lo più intrappolati in semplici riquadri, le forme CSS offrono un modo per creare layout espressivi, colmando il divario di fedeltà tra il web design e il design per la stampa. Naturalmente, le forme possono essere utilizzate in modo improprio e creare distrazioni. Tuttavia, se applicate con gusto e buon senso, le forme possono migliorare la presentazione dei contenuti e focalizzare l'attenzione dell'utente in un modo unico.
Ti lascio con una raccolta di lavori di altri, per lo più di stampa, che dimostra usi interessanti per il layout non rettangolare. Spero che questo ti ispiri a provare le forme CSS e a sperimentare nuove idee di design.
Un ringraziamento speciale a Pearl Chen, Alan Stearns e Zoltan Horvath per aver esaminato questo articolo e aver fornito preziosi insight.