Encapsuler du contenu autour de chemins personnalisés
Pendant longtemps, les concepteurs Web ont été contraints de créer en respectant les contraintes du rectangle. La plupart des contenus sur le Web sont toujours enfermés dans des cases simples, car la plupart des tentatives créatives de mise en page non rectangulaire se terminent par de la frustration. Cela va changer avec l'introduction des formes CSS, disponibles à partir de Chrome 37. Les formes CSS permettent aux concepteurs Web d'encapsuler le contenu autour de chemins personnalisés, tels que des cercles, des ellipses et des polygones, et ainsi de s'affranchir des contraintes du rectangle.
Les formes peuvent être définies manuellement ou inférées à partir d'images.
Prenons un exemple très simple.
Vous avez peut-être été aussi naïf que moi lorsque vous avez flotté une image avec des parties transparentes, en vous attendant à ce que le contenu se plie et remplisse les espaces, mais vous avez été déçu par la forme de pliage rectangulaire qui persiste autour de l'élément. Les formes CSS peuvent être utilisées pour résoudre ce problème.

<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 déclaration CSS shape-outside: url(image.png)
indique au navigateur d'extraire une forme de l'image.
La propriété shape-image-threshold
définit le niveau d'opacité minimal des pixels qui seront utilisés pour créer la forme. Sa valeur doit être comprise entre 0.0
(totalement transparent) et 1.0
(totalement opaque). shape-image-threshold: 0.5
signifie donc que seuls les pixels dont l'opacité est d'au moins 50% seront utilisés pour créer la forme.
La propriété float
est essentielle ici. Bien que la propriété shape-outside
définisse la forme de la zone autour de laquelle le contenu sera mis en forme, sans le flottant, vous ne verrez pas les effets de la forme.
Les éléments ont une zone de flottaison de l'autre côté de leur valeur float
. Par exemple, si un élément contenant une image de tasse de café est flottant à gauche, la zone flottante sera créée à droite de la tasse. Même si vous pouvez créer une image avec des espaces de chaque côté, le contenu ne s'enroule que autour de la forme sur le côté opposé désigné par la propriété float, à gauche ou à droite, mais jamais les deux.
À l'avenir, vous pourrez utiliser shape-outside
sur des éléments qui ne sont pas flottants avec l'introduction des exclusions CSS.
Créer des formes manuellement
En plus d'extraire des formes à partir d'images, vous pouvez également les coder manuellement. Vous pouvez choisir parmi quelques valeurs fonctionnelles pour créer des formes: circle()
, ellipse()
, inset()
et polygon()
. Chaque fonction de forme accepte un ensemble de coordonnées et est associée à un cadre de référence qui établit le système de coordonnées. Nous reviendrons sur les encadrés de référence dans un instant.
Fonction circle()

La notation complète d'une valeur de forme de cercle est circle(r at cx cy)
, où r
correspond au rayon du cercle, tandis que cx
et cy
sont les coordonnées du centre du cercle sur les axes X et Y. Les coordonnées du centre du cercle sont facultatives. Si vous les omettez, le centre de l'élément (l'intersection de ses diagonales) est utilisé par défaut.
.element{
shape-outside: circle(50%);
width: 300px;
height: 300px;
float: left;
}
Dans l'exemple ci-dessus, le contenu s'affiche autour de l'extérieur d'un chemin circulaire. L'argument unique 50%
spécifie le rayon du cercle, qui, dans ce cas précis, correspond à la moitié de la largeur ou de la hauteur de l'élément. Les dimensions de l'élément affectent le rayon du cercle. Il s'agit d'un exemple de base de la façon dont les formes CSS peuvent être responsives.
Avant d'aller plus loin, notez que les formes CSS n'affectent que la forme de la zone de flottaison autour d'un élément. Si l'élément comporte un arrière-plan, celui-ci ne sera pas rogné par la forme. Pour obtenir cet effet, vous devez utiliser les propriétés du masquage CSS : clip-path ou mask-image. La propriété clip-path
est très pratique, car elle suit la même notation que les formes CSS. Vous pouvez donc réutiliser les valeurs.

Les illustrations de ce document utilisent le masquage pour mettre en évidence la forme et vous aider à comprendre les effets.
Revenez à la forme circulaire.
Lorsque vous utilisez des pourcentages pour le rayon du cercle, la valeur est en fait calculée à l'aide d'une formule légèrement plus complexe: sqrt(width^2 + height^2) / sqrt(2). Il est utile de comprendre cela, car cela vous aidera à imaginer la forme du cercle qui en résultera si les dimensions de l'élément ne sont pas égales.
Tous les types d'unités CSS peuvent être utilisés dans les coordonnées de la fonction de forme (px, em, rem, vw, vh, etc.). Vous pouvez choisir celle qui est suffisamment flexible ou rigide pour répondre à vos besoins.
Vous pouvez ajuster la position du cercle en définissant des valeurs explicites pour les coordonnées de son centre.
.element{
shape-outside: circle(50% at 0 0);
}
Le centre du cercle est ainsi placé à l'origine du système de coordonnées. Quel est le système de coordonnées ? C'est là que nous introduisons les encadrés de référence.
Boîtes de référence pour les formes CSS
La zone de référence est une zone virtuelle autour de l'élément, qui établit le système de coordonnées utilisé pour dessiner et positionner la forme. L'origine du système de coordonnées se trouve dans son coin supérieur gauche, l'axe X pointant vers la droite et l'axe Y vers le bas.

N'oubliez pas que shape-outside
modifie la forme de la zone flottante autour de laquelle le contenu sera mis en forme. La zone de flottaison s'étend jusqu'aux bords extérieurs de la zone définie par la propriété margin
. Il s'agit de la margin-box
, qui est la zone de référence par défaut d'une forme si aucune n'est explicitement mentionnée.
Les deux déclarations CSS suivantes donnent le même résultat:
.element{
shape-outside: circle(50% at 0 0);
/* identical to: */
shape-outside: circle(50% at 0 0) margin-box;
}
Nous n'avons pas encore défini de marge pour l'élément. À ce stade, nous pouvons supposer que l'origine du système de coordonnées et le centre du cercle se trouvent dans le coin supérieur gauche de la zone de contenu de l'élément. Ce comportement change lorsque vous définissez une marge:
.element{
shape-outside: circle(50% at 0 0) margin-box;
margin: 100px;
}
L'origine du système de coordonnées se trouve désormais en dehors de la zone de contenu de l'élément (100 pixels vers le haut et 100 pixels vers la gauche), tout comme le centre du cercle. La valeur calculée du rayon du cercle augmente également pour tenir compte de l'augmentation de la surface du système de coordonnées établi par la zone de référence margin-box
.


Une seule zone de référence peut être utilisée à la fois avec une déclaration shape-outside
. Chaque zone de référence influence la forme de manière différente et parfois subtile. Un autre article vous aide à comprendre les zones de référence pour les formes CSS.
Fonction ellipse()

Les ellipses ressemblent à des cercles écrasés. Elles sont définies comme ellipse(rx ry at cx cy)
, où rx
et ry
sont les rayons de l'ellipse sur les axes X et Y, tandis que cx
et cy
sont les coordonnées du centre de l'ellipse.
.element{
shape-outside: ellipse(150px 300px at 50% 50%);
width: 300px;
height: 600px;
}
Les valeurs de pourcentage seront calculées à partir des dimensions du système de coordonnées. Aucune formule mathématique n'est requise. Vous pouvez omettre les coordonnées du centre de l'ellipse. Elles seront alors déduites du centre du système de coordonnées.
Les rayons sur les axes X et Y peuvent également être définis à l'aide de mots clés : farthest-side
génère un rayon égal à la distance entre le centre de l'ellipse et le côté du cadre de référence le plus éloigné, tandis que closest-side
signifie exactement l'inverse : utilisez la distance la plus courte entre le centre et un côté.
.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;
}
Cela peut être utile lorsque les dimensions de l'élément (ou de la zone de référence) peuvent changer de manière imprévisible, mais que vous souhaitez que la forme de l'ellipse s'adapte.
Les mêmes mots clés farthest-side
et closest-side
peuvent également être utilisés pour le rayon dans la fonction de forme circle()
.
Fonction polygone()

Si les cercles et les ellipses sont trop limités, la fonction de forme de polygone offre une multitude d'options. Le format est polygon(x1 y1, x2 y2, ...)
, dans lequel vous spécifiez des paires de coordonnées x et y pour chaque sommet (point) d'un polygone. Le nombre minimal de paires pour spécifier un polygone est de trois, soit un triangle.
.element{
shape-outside: polygon(0 0, 0 300px, 300px 600px);
width: 300px;
height: 600px;
}
Les sommets sont placés sur le système de coordonnées. Pour les polygones responsifs, vous pouvez utiliser des valeurs de pourcentage pour certaines ou toutes les coordonnées.
.element{
/* polygon responsive to font-size*/
shape-outside: polygon(0 0, 0 100%, 100% 100%);
width: 20em;
height: 40em;
}
Un paramètre fill-rule
facultatif, importé depuis le format SVG, indique au navigateur comment considérer l'intérieur d'un polygone en cas de tracés s'intersectant ou de formes fermées. Joni Trythall explique très bien comment fonctionne la propriété fill-rule dans SVG. Si elle n'est pas définie, la valeur par défaut de fill-rule
est nonzero
.
.element{
shape-outside: polygon(0 0, 0 100%, 100% 100%);
/* identical to: */
shape-outside: polygon(nonzero, 0 0, 0 100%, 100% 100%);
}
Fonction inset()
La fonction de forme inset()
vous permet de créer des formes rectangulaires autour desquelles encapsuler le contenu. Cela peut sembler contre-intuitif compte tenu de la prémisse initiale selon laquelle les formes CSS libèrent le contenu Web des boîtes simples. C'est très possible. Je n'ai pas encore trouvé de cas d'utilisation de inset()
qui ne soit pas déjà réalisable avec des flottants et des marges ou avec un polygon()
. Toutefois, inset()
fournit une expression plus lisible pour les formes rectangulaires que polygon()
.
La notation complète d'une fonction de forme en retrait est inset(top right bottom left border-radius)
. Les quatre premiers arguments de position sont des décalages vers l'intérieur à partir des bords de l'élément. Le dernier argument correspond au rayon de la bordure de la forme rectangulaire. Il est facultatif, vous pouvez donc l'ignorer. Il suit la notation abrégée border-radius
que vous utilisez déjà en CSS.
.element{
shape-outside: inset(100px 100px 100px 100px);
/* yields a rectangular shape which is 100px inset on all sides */
float: left;
}
Créer des formes à partir de rectangles de référence
Si vous ne spécifiez pas de fonction de forme à la propriété shape-outside
, vous pouvez autoriser le navigateur à dériver une forme à partir de la zone de référence de l'élément. La zone de référence par défaut est margin-box
. Rien d'extraordinaire jusqu'à présent, car c'est ainsi que fonctionnent déjà les flottants. Toutefois, en appliquant cette technique, vous pouvez réutiliser la géométrie d'un élément. Examinons la propriété border-radius
.
Si vous l'utilisez pour arrondir les angles d'un élément flottant, vous obtenez l'effet de découpe, mais la zone flottante reste rectangulaire. Ajoutez shape-outside: border-box
pour englober le contour créé par border-radius
.

.element{
border-radius: 50%;
shape-outside: border-box;
float: left;
}
Bien entendu, vous pouvez utiliser toutes les cases de référence de cette manière. Voici une autre utilisation des formes dérivées : les citations en retrait.

Vous pouvez obtenir l'effet de citation décalée en n'utilisant que les propriétés float et margin. Pour ce faire, vous devez placer l'élément citation dans l'arborescence HTML au point où vous souhaitez qu'il s'affiche.
Voici comment obtenir le même effet de citation décalée avec plus de flexibilité:
.pull-quote{
shape-outside: content-box;
margin-top: 200px;
float: left;
}
Nous définissons explicitement la zone de référence content-box
pour le système de coordonnées de la forme. Dans ce cas, la quantité de contenu de la citation détermine la forme autour de laquelle le contenu extérieur s'encapsulera. La propriété margin-top
est utilisée ici pour positionner (décaler) la citation, quelle que soit sa position dans l'arborescence HTML.
Marge de la forme
Vous remarquerez que l'encapsulage du contenu autour d'une forme peut le frotter trop près de l'élément. Vous pouvez ajouter un espacement autour de la forme à l'aide de la propriété shape-margin
.
.element{
shape-outside: circle(40%);
shape-margin: 1em;
float: left;
}
L'effet est semblable à celui que vous connaissez avec la propriété margin
standard, mais shape-margin
n'affecte que l'espace autour de la valeur shape-outside
. L'espacement n'est ajouté autour de la forme que s'il y a suffisamment d'espace dans le système de coordonnées. C'est pourquoi, dans l'exemple ci-dessus, le rayon du cercle est défini sur 40%, et non sur 50%. Si le rayon était défini sur 50%, le cercle aurait occupé tout l'espace du système de coordonnées, ne laissant aucune place à l'effet de shape-margin
. N'oubliez pas que la forme est finalement limitée à la margin-box
de l'élément (l'élément plus son margin
environnant). Si la forme est plus grande et déborde, elle sera recadrée sur la margin-box
, et vous obtiendrez une forme rectangulaire.
Il est important de comprendre que shape-margin
n'accepte qu'une seule valeur positive. Il n'a pas de notation manuscrite. À quoi sert la marge supérieure de la forme pour un cercle ?
Animer des formes
Vous pouvez combiner des formes CSS avec de nombreuses autres fonctionnalités CSS, telles que les transitions et les animations. Toutefois, je dois souligner que les utilisateurs trouvent très gênant que la mise en page du texte change pendant qu'ils lisent. Si vous décidez d'animer des formes, soyez particulièrement attentif à l'expérience.
Vous pouvez animer les rayons et les centres des formes circle()
et ellipse()
, à condition qu'ils soient définis dans des valeurs que le navigateur peut interpoler. Il est possible de passer de circle(30%)
à circle(50%)
. Toutefois, l'animation entre circle(closest-side)
et circle(farthest-side)
bloque le navigateur.
.element{
shape-outside: circle(30%);
transition: shape-outside 1s;
float: left;
}
.element:hover{
shape-outside: circle(50%);
}

Vous pouvez obtenir des effets plus intéressants lorsque vous animez des formes polygon()
. Notez que le polygone doit avoir le même nombre de sommets entre les deux états d'animation. Le navigateur ne peut pas interpoler si vous ajoutez ou supprimez des sommets.
Une astuce consiste à ajouter le nombre maximal de sommets dont vous avez besoin et à les regrouper dans l'état d'animation où vous souhaitez que la forme ait moins d'arêtes visibles.
.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%);
}

Mettre en forme le contenu dans une forme

La version initiale de la spécification des formes CSS incluait une propriété shape-inside
qui permettait d'encapsuler du contenu dans une forme. Il y a même eu des implémentations dans Chrome et Webkit pendant un certain temps. Toutefois, encapsuler du contenu positionné de manière arbitraire dans un chemin personnalisé nécessite beaucoup plus d'efforts et de recherches pour couvrir tous les scénarios possibles et éviter les bugs. C'est pourquoi la propriété shape-inside
a été reportée à CSS Shapes Level 2 et que les implémentations correspondantes ont été retirées.
Toutefois, avec un peu d'effort et de compromis, vous pouvez toujours obtenir l'effet d'encapsulation du contenu dans une forme personnalisée. La solution consiste à utiliser deux éléments flottants avec shape-outside
, positionnés de chaque côté d'un conteneur. Le compromis est que vous devez utiliser un ou deux éléments vides qui n'ont aucune signification sémantique, mais qui servent de supports pour créer l'illusion d'une forme à l'intérieur.
<div>
<div class='left-shape'></div>
<div class='right-shape'></div>
Lorem ipsum...
</div>
La position des éléments de strut .left-shape
et .right-shape
en haut du conteneur est importante, car ils seront flottants à gauche et à droite pour encadrer le contenu.
.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%;
}

Ce style fait que les deux poutres flottantes occupent tout l'espace de l'élément, mais les propriétés shape-outside
dégagent de l'espace pour le reste du contenu.
Si le navigateur n'est pas compatible avec les formes CSS, cela aura des effets indésirables en poussant tout le contenu vers le bas. C'est pourquoi il est important d'utiliser cette fonctionnalité de manière progressive.
Dans les exemples d'animation de forme précédents, vous remarquerez que le déplacement du texte peut être gênant. Tous les cas d'utilisation ne justifient pas l'utilisation d'une forme animée. Vous pouvez toutefois animer d'autres propriétés qui interagissent avec les formes CSS pour ajouter des effets là où cela est pertinent.
Dans la démonstration des formes CSS Alice au pays des merveilles, nous avons utilisé la position de défilement pour modifier la marge supérieure du contenu. Le texte est coincé entre deux éléments flottants. Lorsqu'il descend, il doit se recomposer en fonction de la shape-outside
des deux éléments flottants. Cela donne l'impression que le texte descend dans le terrier du lapin, ce qui renforce l'expérience de narration. à la limite du sans frais ? Peut-être. Mais ça a l'air cool.
Comme la mise en page du texte est effectuée en mode natif par le navigateur, les performances sont meilleures qu'avec une solution JavaScript. Toutefois, modifier la marge supérieure lors du défilement déclenche de nombreux événements de redisposition et de peinture, ce qui peut réduire considérablement les performances. À utiliser avec précaution ! Toutefois, l'utilisation de formes CSS sans les animer n'entraîne pas de baisse de performances perceptible.
Amélioration progressive
Commencez par supposer que le navigateur n'est pas compatible avec les formes CSS, puis ajoutez des éléments lorsque vous détectez la fonctionnalité. Modernizr est une bonne solution pour effectuer la détection de fonctionnalités. Un test est disponible pour les formes CSS dans la section "Non-core detects" (Détections non principales).
Certains navigateurs fournissent la détection de fonctionnalités en CSS via la règle @supports
, sans avoir besoin de bibliothèques externes. Google Chrome, qui est également compatible avec les formes CSS, comprend la règle @supports
. Voici comment l'utiliser pour améliorer progressivement:
.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 a écrit plus en détail sur l'utilisation de la règle CSS @supports.
Disambiguation des exclusions CSS
Ce que nous appelons aujourd'hui "formes CSS" s'appelait "exclusions et formes CSS" au début de la spécification. Ce changement de dénomination peut sembler être une nuance, mais il est en réalité très important. Les exclusions CSS, désormais spécifiées séparément, permettent d'encapsuler le contenu autour d'éléments positionnés de manière arbitraire, sans avoir besoin d'une propriété de flottaison. Imaginez encapsuler du contenu autour d'un élément positionné de manière absolue. Il s'agit d'un cas d'utilisation des exclusions CSS. Les formes CSS ne définissent que le chemin autour duquel le contenu sera mis en forme.
Les formes et les exclusions ne sont donc pas la même chose, mais elles se complètent. Les formes CSS sont disponibles dans les navigateurs, tandis que les exclusions CSS ne sont pas encore implémentées avec l'interaction des formes.
Outils pour travailler avec les formes CSS
Vous pouvez créer des tracés dans des outils d'authoring d'images classiques, mais aucun d'entre eux n'exporte la syntaxe requise pour les valeurs des formes CSS au moment de la rédaction de cet article. Même si c'était le cas, travailler de cette manière ne serait pas très pratique.
Les formes CSS sont destinées à être utilisées dans le navigateur, où elles réagissent aux autres éléments de la page. Il est très utile de visualiser les effets de la modification de la forme sur le contenu qui l'entoure. Plusieurs outils sont à votre disposition pour vous aider dans ce workflow:
Brackets: l'extension Éditeur de formes CSS pour Brackets utilise le mode d'aperçu en direct de l'éditeur de code pour superposer un éditeur interactif permettant de modifier les valeurs de forme.
Google Chrome: l'extension Éditeur de formes CSS pour Google Chrome étend les outils pour les développeurs du navigateur avec des commandes permettant de créer et de modifier des formes. Il place un éditeur interactif au-dessus de l'élément sélectionné.
L'outil d'inspection de Google Chrome est compatible avec la mise en surbrillance des formes. Pointez sur un élément avec une propriété shape-outside
. Il s'illumine pour illustrer la forme.
Formes à partir d'images: si vous préférez générer des images et demander au navigateur d'en extraire des formes, Rebecca Hauck a rédigé un bon tutoriel pour Photoshop.
Polyfill: Google Chrome est le premier grand navigateur à proposer les formes CSS. Cette fonctionnalité sera bientôt disponible sur iOS 8 et Safari 8 d'Apple. D'autres fournisseurs de navigateurs pourraient l'envisager à l'avenir. En attendant, un polyfill CSS Shapes est disponible pour fournir une compatibilité de base.
Conclusion
Sur un Web où le contenu est principalement enfermé dans des cases simples, les formes CSS permettent de créer une mise en page expressive, comblant ainsi l'écart de fidélité entre la conception Web et la conception imprimée. Bien sûr, les formes peuvent être utilisées de manière abusive et créer des distractions. Toutefois, lorsqu'elles sont appliquées avec goût et bon sens, les formes peuvent améliorer la présentation du contenu et attirer l'attention de l'utilisateur de manière unique.
Je vous laisse avec une collection de travaux d'autres personnes, principalement issus de la presse, qui illustrent des utilisations intéressantes de la mise en page non rectangulaire. J'espère que cet article vous inspirera à essayer les formes CSS et à tester de nouvelles idées de conception.
Merci à Pearl Chen, Alan Stearns et Zoltan Horvath d'avoir relu cet article et de nous avoir fourni des informations précieuses.