Rettangoli all’interno di altri rettangoli: ecco da cosa sono sempre state fatte le nostre pagine web. Da molto tempo stiamo provando a liberarci da queste costrizioni usando CSS per creare delle forme geometriche, ma queste forme non hanno mai influenzato la posizione del contenuto all’interno dell’elemento con una certa forma, o il modo in cui l’elemento viene visto dagli altri presenti sulla stessa pagina.
La nuova specifica CSS Shapes sta cambiando proprio questi aspetti. Introdotta da Adobe a metà del 2012, il suo obiettivo è quello di fornire ai web designer un nuovo modo per cambiare la maniera in cui il contenuto si posiziona all’interno e attorno a forme complesse e arbitrarie: cosa che non siamo mai stati in grado di fare prima d’ora, nemmeno con JavaScript.
Per esempio, osservate come il testo si sistemi attorno alle immagini circolari nel seguente design. Senza Shapes, il testo sarebbe rettangolare, sprecando il tocco sofisticato che porta il design a un livello superiore.

Notate in questo esempio il modo in cui il testo si posiziona attorno alla forma circolare di una ciotola. Usando CSS Shapes possiamo creare dei design simili per il Web.
Vediamo come funzionano le Shapes e come si possono cominciare ad usare.
Supporto nei browser#section1
Le CSS Shapes attualmente sono supportate solo in Webkit Nightly e Chrome Canary, ma il loro Module Level 1 ha raggiunto lo status di Candidate Recommendation, quindi le proprietà e la sintassi definita nella specifica sono piuttosto stabili. Non ci vorrà molto prima che venga implementata anche in altri browser. Questo “Level” è incentrato sulle proprietà delle Shapes che modificano lo scorrere del contenuto attorno ad una forma. Più nello specifico, ruota attorno alla proprietà shape-outside
e sulle proprietà ad essa correlate.
Utilizzando CSS Shapes insieme ad altre feature all’avanguardia come Clipping and Masking, CSS Filters e Compositing and Blending potremo creare design più raffinati e sofisticati senza dover ricorrere a programmi di grafica come Photoshop o InDesign.
I Level futuri di CSS Shapes si concentreranno sulla presentazione del contenuto anche all’interno di una forma. Per esempio, oggi è semplice creare una forma a rombo in CSS: basta ruotare semplicemente l’elemento di 45 gradi e poi ruotare al contrario il contenuto al suo interno, così che si posizioni orizzontalmente sulla pagina. Ma il contenuto all’interno del rombo non sarà influenzato dalla forma romboidale del suo container e rimarrà sempre rettangolare. Quando la proprietà shape-inside
di CSS Shapes verrà implementata, saremo in grado di far sì che anche il contenuto diventi a forma di rombo, rendendo fattibile il layout come quello mostrato nell’immagine seguente.

Presto, CSS Shapes permetterà che anche il testo all’interno di queste forme, come i rombi, si aggiusti ai lati del suo contenitore piuttosto che uscirne o venirne tagliato.
Per usare subito CSS Shapes in Chrome Canary dovete abilitare la flag delle feature sperimentali. Se non siete sicuri su come si fa, date un’occhiata a questa guida passo a passo sul blog di Adobe.
Creare una CSS Shape#section2
Potete applicare una forma a un elemento usando una delle proprietà di Shapes. Si passa alla shape property una shape function come valore. La shape function è il posto in cui si passano gli argomenti che definiscono la forma che si vuole applicare all’elemento.

Le forme possono essere create usando una delle seguenti funzioni:
circle()
ellipse()
inset()
polygon()
Ogni forma è definita da un insieme di punti. Alcune funzioni prendono i punti come parametri, altre richiedono gli offset, ma alla fine tutte disegnano le forme come un insieme di punti sull’elemento. Vedremo i parametri per ciascuna di queste funzioni negli esempi che creeremo.
Una forma può anche essere definita estraendola da un’immagine con un alpha channel. Quando un’immagine viene passata alla shape property, il browser andrà poi ad estrarre la forma dall’immagine basandosi su una shape-image-threshold
. La forma è definita dai pixel il cui valore alfa è maggiore della soglia (treshold). L’immagine deve essere compatibile con CORS. Se l’immagine fornita per qualche ragione non può essere mostrata (come se ad esempio non esistesse), allora non verrà applicata alcuna forma.
Le proprietà shape che accettano le funzioni di cui sopra come valori sono:
shape-outside
: sistema il contenuto attorno (all’esterno) della formashape-inside
: sistema il contenuto all’interno della forma
Si può usare la proprietà shape-outside
insieme alla proprietà shape-margin
per aggiungere un margine attorno alla forma così da allontanare il contenuto che scorre attorno alla forma, creando più spazio fra questa e il contenuto. Proprio come shape-outside
ha una proprietà shape-margin
, così shape-inside
ha una proprietà shape-padding
, che aggiunge un padding interno.
Usando le shape properties e functions, la dichiarazione di una shape su un elemento può essere tanto semplice quanto aggiungere una riga di CSS:
.element {
shape-outside: circle(); /* il contenuto scorrerà attorno
al cerchio definito sull'elemento */
}
Oppure:
.element {
shape-outside: url(path/to/image-with-shape.png);
}
Ma…
Se applicate quella riga di CSS al vostro elemento, la shape non verrà ad esso applicata a meno che non vengano soddisfatte due condizioni:
- All’elemento deve essere applicato un float. I livelli futuri di CSS Shapes potrebbero permetterci di definire le forme sugli elementi che non hanno float, ma al momento non è ancora possibile.
- L’elemento deve avere dimensioni intrinseche. L’altezza e la larghezza impostate su un elemento verranno usate per stabilire un sistema di coordinate su quell’elemento.
Come avete visto nelle definizioni di funzione di cui sopra, le forme sono definite da insiemi di punti. Poiché questi punti hanno delle coordinate, serve un sistema di coordinate per far sì che il browser sappia dove posizionare ciascun punto sull’elemento. Quindi, l’esempio di prima funzionerebbe se includesse qualcosa come:
.element {
float: left;
height: 10em;
width: 15em;
shape-outside: circle();
}
Comunque, dare all’elemento delle dimensioni intrinseche non influenza la sua “responsiveness” (ne parleremo più avanti).
Dal momento che ciascuna forma è definita da un insieme di punti posizionati usando una coppia di coordinate, cambiare le coordinate di un punto influenzerà direttamente la forma creata. Per esempio, l’immagine seguente mostra una forma esagonale che può essere creata usando la funzione polygon()
. La forma è creata con sei punti. Cambiando la coordinata orizzontale del punto in arancio cambierà anche la forma risultante e influenzerà il flusso del contenuto all’interno e/o all’esterno di qualsiasi elemento a cui è applicata questa forma.

Se l’elemento ha float right e gli si applica questa forma, il contenuto alla sua sinistra cambierà il suo andamento quando la coordinata del punto arancio verrà cambiata all’interno della funzione polygon()
.
Il reference box di una Shape#section3
Le CSS Shapes sono definite e create all’interno di una reference box, che è il box usato per disegnare la forma sull’elemento. Oltre all’altezza e alla larghezza dell’elemento, i box del box model dell’elemento – margin box, content box, padding box e border box – vengono anche usati come riferimento per specificare la dimensione della forma di un elemento.
Di default, il margin box viene usato come riferimento, quindi, se un elemento a cui volete applicare una forma ha un margin sul lato inferiore (bottom), la forma che definite sull’elemento si estenderà fino ai bordi dell’area di margin, non fino alla border area dell’elemento. Se volete usare uno degli altri box value, potete specificarlo insieme alla shape function che passate alle shape properties:
shape-outside: circle(250px at 50% 50%) padding-box;
La parola chiave padding-box
nella regola di cui sopra specifica che la forma verrà applicata e sarà ristretta al padding box (padding area) dell’elemento. La funzione circle()
definisce una forma circolare, la sua dimensione e la sua posizione sull’elemento.
Definire le Shapes usando le shape function#section4
Cominceremo col posizionare alcune informazioni attorno all’immagine di un avatar di un utente, come potreste voler fare per mostrare uno user profile o un testimonial.

Usando CSS Shapes, il testo attorno ad un’immagine circolare per lo user profile scorre lungo la forma invece di rimanere rettangolare.
Useremo la funzione circle()
per applicare una forma circolare all’immagine del profilo, usando il seguente markup:
<img src="http://api.randomuser.me/0.3.2/portraits/men/7.jpg"
alt="profile image" />
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum itaque
nam blanditiis eveniet enim eligendi quae adipisci?</p>
<p>Assumenda blanditiis voluptas tempore porro quibusdam beatae
deleniti quod asperiores sapiente dolorem error! Quo nam quasi soluta
reprehenderit laudantium optio ipsam ducimus consequatur enim fuga
quibusdam mollitia nesciunt modi.</p>
Potreste chiedermi “Perché non usiamo border-radius
per arrotondare l’immagine?” La risposta è che la proprietà border-radius
non ha alcun effetto sul fluire del contenuto all’interno o attorno all’elemento a cui è applicato: non influenza l’area del contenuto dell’elemento né l’area di posizionamento del contenuto attorno all’elemento. Ha effetto solo sui bordi di un elemento e sugli eventuali background. L’area del background è agganciata agli angoli arrotondati dalla proprietà e questo è tutto; il contenuto all’interno dell’elemento rimarrà rettangolare e il contenuto al di fuori dell’elemento vedrà ancora e tratterà l’elemento come se fosse rettangolare, perché lo è.
Noi useremo la proprietà border-radius
per rendere l’immagine circolare. Questo è quello che facciamo di solito per arrotondare le immagini o altri elementi di una pagina:
img {
float: left;
width: 150px;
height: 150px;
border-radius: 50%;
margin-right: 15px;
}

Senza CSS Shapes, il testo vede l’immagine come rettangolare e quindi si scorre attorno ad una forma rettangolare non intorno ad una circolare.
In un browser che non supporta CSS Shapes, il contenuto attorno all’immagine circolare si posizionerà attorno a questa come se non fosse circolare. Questo è il modo in cui apparirebbe il fallback nei browser più vecchi.
Per cambiare il flusso di contenuto perché si sistemi attorno ad una forma, useremo le shape properties.
img {
float: left;
width: 150px;
height: 150px;
border-radius: 50%;
shape-outside: circle();
shape-margin: 15px;
}
Con questo codice, il testo “vedrà” la forma circolare applicata all’immagine e vi si posizionerà attorno, come mostrato nel primo screenshot. (Potete vedere il risultato “live” qui). Nei browser che non supportano queste proprietà, il risultato sarà quello di fallback mostrato nella seconda immagine.
Potete usare la funzione circle()
così com’è o passandogli dei parametri. La sua sintassi ufficiale è:
circle() = circle( [<shape-radius>]? [at <position>]? )
I punti di domanda indicano che questi parametri sono opzionali e possono essere omessi. Se ne omettete uno, quel parametro verrà impostato al suo valore di default dal browser. Quando usate circle()
così com’è, invece di impostare semplicemente la sua posizione, il suo default consisterà in un cerchio posizionato al centro dell’elemento a cui la state applicando.
Si può specificare il raggio del cerchio usando una qualsiasi unità di lunghezza (px
, em
, pt
, etc.). Potete anche specificare il raggio usando closest-side
o farthest-side
, ma closest-side
è il default, quindi il browser userà la lunghezza dal centro dell’elemento verso il suo lato più vicino come lunghezza del raggio. farthest-side
usa la lunghezza dal centro verso il lato più lontano.
shape-outside: circle(farthest-side at 25% 25%); /* definisce un cerchio
il cui raggio è metà della lunghezza del lato più lungo,
posizionato nel punto di coordinate 25% 25%
sul sistema di coordinate dell'elemento */
shape-inside: circle(250px at 500px 300px); /* definisce un cerchio il cui centro
è posizionato orizzontalmente a 500px e verticalmente a 300px,
con un raggio di 250px. */

La funzione ellipse()
funziona allo stesso modo della funzione circle()
, con lo stesso elenco di valori ma invece che prendere in ingresso un parametro per il raggio, ne richiede due: uno per la lunghezza del raggio sull’asse X e un altro per l’asse Y.
ellipse() = ellipse( [<shape-radius>{2}]? [at <position>]? )
Sebbene non direttamente collegata a un cerchio o a un ellisse, la funzione inset()
è usata per creare forme rettangolari all’interno di un elemento. Dal momento che gli elementi sono già rettangolari, tuttavia, non abbiamo bisogno di creare altri rettangoli. Al contrario, inset()
ci aiuta a creare rettangoli con angoli arrotondati il cui contenuto scorre attorno a questi angoli.

La funzione inset()
prende da uno a quattro valori di offset, che specificano l’offset verso l’interno dai lati del reference box. Questi specificano dove il rettangolo “inset” deve andare all’interno dell’elemento. La funzione prende anche un parametro opzionale per arrotondare gli angoli del rettangolo “inset”. Gli angoli arrotondati sono specificati esattamente nello stesso modo di border-radius, usando da uno a quattro valori, insieme alla parola chiave
round
.
inset() = inset( offset{1,4} [round <border-radius>]? )
Il seguente codice creerà un rettangolo arrotondato su un elemento con float.
.element {
float: left;
width: 250px;
height: 150px;
shape-outside: inset(0px round 100px) border-box;
}
Guardate l’esempio live qui.
L’ultima funzione shape è polygon()
, che definisce forme arbitrarie più complesse usando un qualunque numero di punti. La funzione prende in ingresso un insieme di coppie di coordinate, ciascuna coppia specifica la posizione di un punto. L’insieme di punti forma la shape.
Nell’esempio seguente, un’immagine con float right occupa l’intera altezza dello schermo usando le unità della viewport. Vogliamo che il testo scorra sulla sinistra lungo la clessidra all’interno dell’immagine, così usiamo la funzione polygon()
per definire una forma irregolare sull’immagine.

Il CSS per l’immagine qui sopra è così:
img.right {
float: right;
height: 100vh;
width: calc(100vh + 100vh/4);
shape-outside: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%,
45% 40%);
}
Potete impostare le coordinate dei punti che definiscono la forma in unità di lunghezza o in percentuali, come ho fatto io in questo esempio.
Questo codice da solo produrrà il risultato di cui sopra, ma come potete vedere, la shape function non influenza le parti rimanenti dell’immagine al di fuori della forma definita. In realtà, applicare una shape function a un elemento, che sia un’immagine, un container o qualcosa tra questi due estremi, non influenzerà niente se non l’area in cui scorrerà il contenuto. I background, i bordi e tutto il resto rimarranno invariati.
Per visualizzare la forma del poligono che abbiamo creato dobbiamo ritagliare le parti dell’immagine al di fuori della forma. Ci viene in aiuto la proprietà clip-path
da CSS Masking Module.
La proprietà clip-path
prende le stesse shape function e gli stessi valori delle shape properties. Se passiamo la stessa forma poligonale che abbiamo usato nella proprietà shape-outside
alla proprietà clip-path
, questa ritaglierà tutte le parti dell’immagine che si trovano al di fuori della forma definita.
img.right {
float: right;
height: 100vh;
width: calc(100vh + 100vh/4);
shape-outside: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%,
45% 40%);
/* clip the image to the defined shape */
clip-path: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);
}
Il risultato apparirà così:

La proprietà clip-path
è al momento supportata con i prefissi, quindi funzionerà in Chrome con il prefisso -webkit-
aggiunto alla proprietà clip-path
. Potete guardare la live demo qui.
La proprietà clip-path
è una compagna eccellente per le shape properties, perché contribuisce a visualizzare le forme create e a ritagliare tutte le parti dell’elemento che si trovano al di fuori delle forme definite, così probabilmente vi troverete ad usarla molto spesso insieme alle shape properties.
La funzione polygon()
, inoltre, prende in ingresso una keyword opzionale che può avere valore nonzero
o evenodd
. Questo specifica il modo in cui trattare le aree all’interno della forma poligonale che possono intersecarsi. Si veda la proprietà SVG fill-rule per i dettagli.
Definire una forma usando un’immagine#section5
Per definire una forma utilizzando un’immagina, tale immagine ha bisogno di un alpha channel da cui il browser può estrarre la forma.
Una forma è definita dai pixel i cui valori alfa sono maggiori di una certa soglia, che ha come valore di default 0.0 (completamente trasparente), oppure potete impostarla esplicitamente usando la proprietà shape-image-shreshold
. Quindi, qualunque pixel non trasparente sarà usato come parte della forma definita dall’immagine.
Un futuro livello di CSS Shapes potrebbe definire uno switch per utilizzare i dati di “luminance” da un’immagine invece dei dati alpha. Se questo accadesse, shape-image-treshold
verrebbe estesa per applicare la sua soglia o all’alpha o alla luminance, a seconda dello stato dello switch.
Useremo la seguente immagine per definire una forma su un elemento e fare in modo che il testo si posizioni attorno ad essa.

Usare la proprietà shape-outside
con il valore url()
che punta a questa immagine, possiamo far scorrere il contenuto attorno all’elemento con questa forma di foglia.
.leaf-shaped-element {
float: left;
width: 400px;
height: 400px;
shape-outside: url(leaf.png);
shape-margin: 15px;
shape-image-threshold: 0.5;
background: #009966 url(path/to/background-image.jpg);
mask-image: url(leaf.png);
}
Ovviamente, se aveste applicato un background all’elemento, il background avrebbe dovuto essere ritagliato all’esterno della forma definita. La proprietà mark-image
(con i prefissi appropriati) facente parte del Masking Module può fare proprio questo, dal momento che la proprietà clip-path
non prende un’immagine alpha come valore. Il risultato ha questo aspetto:

Se state creando forme complesse, potreste voler definire una forma usando un’immagine. Questo vi permette di usare un’immagine con un alpha channel in Photoshop invece che definire manualmente i punti.
Potreste anche voler usare un’immagine invece di una shape function quando avete più float o più aree di esclusione all’interno di un elemento – perché, per il momento, non potete dichiarare più forme su un elemento. Ma se l’immagine contiene più aree, il browser estrarrà queste aree dall’immagine e le userà.
CSS Shapes nel responsive design#section6
CSS Shapes può rientrare nel nostro workflow responsive? Ci viene in aiuto l’attuale specifica di shape-outside
, perché ci permette di specificare le dimensioni dell’elemento sia in percentuali sia in altre unità di lunghezza e i punti che definiscono una forma (parametri della funzione shape) possono essere anch’essi impostati in percentuali. Questo significa che un elemento con shape-outside
dovrebbe essere completamente responsive, proprio come qualunque altro float con dimensioni in percentuale.
shape-inside
non è ancora responsive ma solo perché è stata spostata nel Module Level 2. Molte delle sue attuali limitazioni verranno risolte nel prossimo livello.
Strumenti per la forma#section7
Creare forme complesse con le shape function può essere un compito scoraggiante, specialmente se ne state creando una con molti punti e coordinate usando polygon()
. Fortunatamente, il team della piattaforma web di Adobe sta lavorando su dei tool interattivi che renderanno questa operazione molto più semplice. Bear Travis ha creato una collezione di Shape Tools che ci permettono di creare delle forme poligonali in maniera visuale. Il tool genera poi una funzione di forma al posto nostro. Tutto ciò è utile, ma può essere limitante se volete creare una forma basata su un’immagine specifica, perché non ci sono modi con cui poter inserire l’immagine nel tool e poi crearne una forma.
Uno Shape Tool più avanzato ed interattivo è stato sviluppato dal team di Adobe Web Platform. Tale strumento è stato rilasciato recentemente come estensione dell’editor gratuito Brackets di Adobe. Permette di visualizzare ed editare le forme direttamente nel browser e ha una feature di “live preview” che aggiorna i valori di forma nello stylesheet quando li si cambia sulla pagina. In questo modo, si ha un feedback visivo istantaneo dei cambiamenti, permettendoci di vedere come le forme interagiscono con gli altri elementi sulla pagina.

Modifica di una forma poligonale direttamente nel browser con la modalità “live preview” di Brackets. Screen capture di Razvan Caliman.
Questo strumento sarà indispensabile perché faciliterà la creazione, la modifica e il debugging delle nostre forme. Razvan Caliman ha scritto un articolo sul blog di Brackets in cui spiega come utilizzare lo Shapes editor in Brackets.
Il futuro: CSS Exclusions#section8
La specifica CSS Shapes si trovava una volta nella specifica CSS Shapes and Exclusions, ma le due specifiche vennero separate. CSS Shapes definisce le proprietà shape-inside
e shape-outside
, mentre CSS Exclusions definirà delle proprietà che ci permetteranno di far scorrere il contenuto attorno agli elementi che non hanno float, come gli elementi con posizione assoluta. Ciò renderà possibile lo scorrere del contenuto attorno all’intera forma su lati diversi, come mostrato nell’immagine seguente:

In futuro, CSS Exclusions ci permetterà di far scorrere il testo attorno ad una forma come il “pullquote” (frase di articolo estratta e stampata a caratteri più grandi, ndr), come mostrato nel layout di questo magazine. Il pullquote potrà anche essere circolare e il testo gli si avvolgerà comunque attorno. Immagine di Justin Thomas Kay.
Saranno anche possibili layout simili con elementi di varie forme posizionati in maniera assoluta al centro di un articolo, con il testo che scorre attorno all’elemento su tutti i lati.
Spingersi oltre le Shapes#section9
L’attuale specifica di CSS Shapes non è altro che un primo passo. Ben presto, avremo nuove opzioni che ci daranno più controllo sulla creazione di forme e sul posizionamento del contenuto al loro interno e al di fuori di esse, rendendo molto più semplice per noi tradurre i nostri mockup in design “live” usando solo poche righe di codice. Ad oggi, gli editor della specifica si stanno concentrando sulla pubblicazione di shape-outside
e molto probabilmente vedremo le CSS Shapes in sempre più browser entro la fine del 2014.
Potete usare Shapes oggi come parte di un workflow basato sul progressive enhancement, sapendo che hanno dei fallback accettabili nei browser in cui non sono supportate. Ho recentemente cominciato ad applicarle al mio sito web e il fallback è decisamente “normale”. Per design più complessi, potete usare uno script per controllare se un browser supporta le Shapes e per fornire il fallback che volete se non lo sono. Potete anche estendere i test di Modernizr con questo script per vedere se shape-outside
è supportata, o scaricarne una “custom build” che includa questo test.
CSS Shapes ci permette di colmare una lacuna esistente tra stampa e web. Gli esempi in questo articolo sono semplici, ma possono costituire la base per la creazione di design complessi come un qualunque magazine o poster, senza doversi preoccupare se sarete in grado di riprodurli sullo schermo. Qualunque cosa vogliate esplorare, dai layout non rettangolari all’animazione delle Shapes, questo è il momento giusto per esplorare.
Illustrazioni: {carlok}
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