Chemins, formes, découpage et masquage

Le rendu HTML est basé sur le modèle de boîte, mais la vie (et la conception Web) ne se résument pas à des rectangles. Le CSS offre plusieurs façons de modifier les zones d'un élément qui sont affichées, ce qui permet aux développeurs de créer des designs adaptés à toutes les formes et tailles. L'écrêtage permet de créer des formes géométriques, tandis que le masquage affecte la visibilité au niveau des pixels.

Chemins et formes

CSS utilise des fonctions pour définir des formes. Nous abordons les informations générales sur les fonctions dans le module sur les fonctions CSS. Dans cette section, vous allez apprendre à créer des formes en CSS. Tous les exemples suivants utilisent les formes que vous créez avec la propriété clip-path, ce qui réduit la zone visible à ce qui se trouve à l'intérieur de la forme. Cela permet aux éléments de différer visuellement de la boîte de l'élément. Nous aborderons le clipping plus en détail ultérieurement.

Les formes définies en CSS peuvent être des formes de base (comme des cercles, des rectangles et des polygones) ou des chemins (qui peuvent définir des formes complexes et composées).

Formes de base

circle() et ellipse()

Les fonctions circle() et ellipse() définissent des formes rondes et ovales avec des rayons relatifs à un élément. La fonction circle() accepte une seule taille ou un seul pourcentage comme argument. Par défaut, les deux fonctions positionnent la forme par rapport au centre de l'élément. Les deux acceptent une position facultative après le mot clé at, qui peut être exprimée sous forme de longueurs, de pourcentages ou de mots clés de position.

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: circle(50%);
}

Lorsque la fonction circle() prend un argument de 50 %, un cercle parfait est affiché.

L'exemple précédent montre un chemin de détourage circulaire utilisant la fonction circle(). Notez qu'un rayon de 50% crée un cercle sur toute la largeur de l'élément. La fonction ellipse() accepte deux arguments représentant les rayons horizontal et vertical de la forme.

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: ellipse(50% 25%);
}

La fonction ellipse() produit une ellipse à partir d'arguments de pourcentage. Les arguments de 50 % et 25 % produisent une ellipse qui s'étend sur un rayon deux fois plus grand sur l'axe X que sur l'axe Y.

L'exemple précédent montre un chemin de détourage elliptique utilisant la fonction ellipse(). Notez qu'un rayon de 50 % crée une ellipse sur toute la largeur de l'élément. L'exemple suivant affiche la même ellipse positionnée avec son centre en haut de l'élément.

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: ellipse(50% 25% at center top);
}

rect() et inset()

Les fonctions rect() et inset() offrent différentes façons de définir un rectangle en définissant la position de ses côtés par rapport à ceux d'un élément. Cela vous permet de créer des rectangles qui diffèrent visuellement de la boîte par défaut de l'élément. Elles acceptent éventuellement le mot clé round pour créer un rectangle aux angles arrondis, en utilisant la même syntaxe que la propriété abrégée border-radius.

La fonction rect() définit la position des côtés supérieur et inférieur du rectangle par rapport au bord supérieur de l'élément, et des côtés gauche et droit par rapport au bord gauche de l'élément. Cette fonction accepte quatre unités de taille ou de pourcentage comme arguments définissant les côtés supérieur, droit, inférieur et gauche. Vous pouvez choisir la fonction rect() lorsque vous souhaitez un rectangle qui ne se redimensionne pas lorsque la taille de l'élément change ou qui conserve les mêmes proportions lorsque l'élément change.

.my-element {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: rect(15px 75px 45px 10px);
}

La fonction rect() accepte quatre arguments pour définir la taille d'un rectangle. Dans ce cas, les arguments sont 15 px, 75 px, 45 px et 10 px.

L'exemple précédent montre un chemin de détourage rectangulaire défini à l'aide de la fonction rect(). Les dimensions sont indiquées par rapport aux bords supérieur et gauche de l'élément, comme illustré dans le schéma.

La fonction inset() définit la position des côtés d'un rectangle par la distance vers l'intérieur à partir de chacun des côtés d'un élément. Cette fonction accepte un à quatre arguments de taille ou de pourcentage, ce qui vous permet de définir plusieurs côtés à la fois. Vous pouvez choisir la fonction inset() lorsque vous souhaitez un rectangle qui s'adapte à l'élément ou un rectangle qui se trouve à une distance fixe des bords de l'élément.

.my-element {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px);
}

La fonction inset() peut soustraire de la taille intrinsèque de l'élément. Dans ce diagramme, les arguments de cette fonction sont 15 px, 5 px, 15 px et 10 px.

L'exemple précédent montre un chemin de détourage rectangulaire défini à l'aide de la fonction inset(). Les dimensions sont indiquées par rapport aux côtés de l'élément.

Les fonctions rect() et inset() acceptent éventuellement le mot clé round pour créer un rectangle aux angles arrondis, en utilisant la même syntaxe que la propriété abrégée border-radius. L'exemple suivant montre des versions arrondies des rectangles affichés précédemment.

.rounded-rect {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px round 5px);
}

.rounded-inset {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px round 5px);
}

polygon()

Pour les autres formes, telles que les triangles, les pentagones, les étoiles, etc., la fonction polygon() vous permet de créer des formes en reliant plusieurs points par des lignes droites. La fonction polygon() accepte une liste de paires composées de deux unités de longueur ou de pourcentage. Chaque paire décrit un point du polygone : la première valeur correspond à la distance par rapport au bord gauche de l'élément, et la seconde à la distance par rapport au bord supérieur de l'élément. Vous n'avez pas besoin de fermer le polygone, car il sera complété en reliant le dernier point au premier.

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: polygon(
    50% 0,
    0 100%,
    100% 100%
  );
}

La fonction polygon() accepte un nombre variable d'arguments afin de dessiner des formes complexes. Dans ce cas, les arguments sont conçus de manière à créer un triangle.

L'exemple précédent crée un chemin de détourage triangulaire en définissant trois points.

Par défaut, la fonction polygon() affiche les zones qui se chevauchent comme remplies. Vous pouvez modifier ce comportement à l'aide d'un premier argument facultatif appelé "règle de remplissage". Pour alterner entre les zones remplies et non remplies, définissez la règle de remplissage sur evenodd. Pour utiliser la règle de remplissage par défaut, définissez-la sur nonzero.

L'exemple précédent montre la fonction polygon() avec des fonctions trigonométriques pour créer des polygones réguliers et des formes en étoile. Cela ne crée pas le plus grand polygone régulier possible qui s'insère dans un élément ni ne le centre. Nous vous laissons le soin de l'essayer. Les formes en étoile de cet exemple illustrent également les règles de remplissage nonzero et evenodd.

Formes complexes

Lorsque les fonctions de forme de base ne suffisent pas à décrire une forme complexe, CSS fournit des fonctions qui utilisent une syntaxe plus sophistiquée pour décrire des caractéristiques telles que les courbes et les lignes. Ces fonctions sont également utiles pour les formes composées (formes composées de plusieurs formes, comme un cercle avec un trou).

path()

La fonction path() accepte une chaîne de syntaxe de tracé SVG pour décrire une forme. Cela permet de créer des formes complexes à l'aide d'instructions décrivant les lignes et les courbes qui composent la forme. Il peut être compliqué de modifier directement la syntaxe SVG. Nous vous recommandons donc d'envisager d'utiliser un éditeur visuel dédié qui peut exporter la syntaxe lorsque vous créez des formes avec la fonction path().

La fonction path() n'utilise pas d'unités de dimensionnement CSS. Toutes les valeurs sont interprétées comme des pixels. Cela signifie que les formes créées avec la fonction path ne sont pas adaptées à la taille de l'élément ou du conteneur. Nous vous recommandons d'utiliser path() uniquement pour les formes dont les dimensions sont fixes.

shape()

La fonction shape() utilise une syntaxe de commande pour décrire une forme, semblable à la fonction path(). Toutefois, les commandes de la fonction shape() sont en CSS natif et peuvent utiliser des unités de taille CSS. Cela permet de redimensionner de manière responsive les formes définies à l'aide de la fonction shape().

L'exemple précédent utilise les fonctions path() et shape() pour définir une forme de cœur et un cercle avec un trou au centre. L'exemple utilise la même valeur en pixels pour les deux fonctions, mais les fonctions shape() auraient pu utiliser d'autres unités de taille CSS, telles que des pourcentages ou des unités relatives au conteneur.

Bornage

Le clipping définit les zones d'un élément qui sont visibles, comme lorsqu'on découpe une image dans un magazine. La propriété clip-path définit le chemin utilisé pour définir la zone de découpe.

Comme vous l'avez vu dans les exemples de la section précédente, n'importe quelle fonction de forme ou de chemin de base peut être utilisée comme clip-path. La propriété clip-path est également compatible avec les chemins d'accès définis dans un élément clipPath SVG, qui peut être intégré ou dans un fichier distinct.

Voici comment le rognage peut affecter une image en particulier : dans cette image, une photo de chaton est rognée en forme de cercle et en forme de tracé de rognage complexe qui décrit le chaton dans son intégralité.

Le diagramme précédent montre comment l'ajout d'un clip-path à un élément d'image modifie la zone visible de l'image. Le chemin de masquage supérieur utilise la fonction circle(), tandis que celui du bas utilise un clipPath SVG. Notez que le cercle créé à l'aide de la fonction circle() est centré sur l'élément par défaut.

La propriété clip-path n'accepte qu'un seul chemin d'accès. Pour découper un élément avec plusieurs formes qui ne se chevauchent pas, utilisez les fonctions path() ou shape() pour définir un chemin composé, ou utilisez un clipPath SVG. Une autre option pour les scénarios complexes consiste à utiliser le masquage au lieu du découpage, que nous aborderons dans une section ultérieure.

Découper avec des formes

Pour effectuer un écrêtage à l'aide d'une fonction de forme ou de chemin de base, définissez la propriété clip-path sur la valeur renvoyée par la fonction, comme dans les exemples précédents. Chaque fonction positionne la forme de découpage différemment par rapport à l'élément. Consultez donc la référence pour chaque fonction.

Dans l'exemple précédent, deux éléments ont un clip-path circulaire appliqué à l'aide de la classe .clipped. Notez que clip-path est positionné par rapport à chaque élément et que le texte dans clip-path ne se réorganise pas pour suivre la forme.

Zone de référence d'un tracé de détourage

Par défaut, le chemin de masquage d'un élément inclut sa bordure. Lorsque vous utilisez l'une des fonctions de forme de base, vous pouvez définir le cadre de référence du chemin de rognage pour n'inclure que la zone de l'élément à l'intérieur de la bordure. Les valeurs valides pour le cadre de référence sont stroke-box (par défaut) et fill-box (pour inclure uniquement la zone à l'intérieur de la bordure).

L'exemple précédent montre des éléments avec une bordure épaisse (20px), chacun utilisant la fonction inset() pour définir la clip-path. L'élément qui effectue le clipping par rapport à la bordure de l'élément affiche toujours une partie de la bordure. Les éléments qui sont rognés par rapport à la zone située à l'intérieur de la bordure n'affichent aucune bordure et sont plus petits, même avec la même valeur d'encart.

Découpage avec des graphiques

Un tracé de détourage peut être défini dans un document SVG, intégré au document HTML ou référencé en externe. Cela peut être utile pour définir des chemins de détourage complexes créés dans des programmes graphiques ou des chemins de détourage qui combinent plusieurs formes.

<img id="kitten" src="kitten.png">

<svg>
  <defs>
    <clipPath id="kitten-clip-shape">
      <circle cx="130" cy="175" r="100" />
    </clipPath>
  </defs>
</svg>

<style>
  #kitten {
    clip-path: url(#kitten-clip-shape);
  }
</style>

Dans l'exemple précédent, le clipPath avec un id de kitten-clip-shape est appliqué à l'élément <img>. Dans ce cas, le document SVG est intégré au code HTML. Si le document SVG est un fichier externe nommé kitten-clipper.svg, le clipPath sera référencé en tant que url(kitten-clipper.svg#kitten-clip-shape).

Masquage

Le masquage est une autre méthode permettant de définir les zones d'un élément qui sont affichées ou masquées. Alors que le découpage utilise des formes ou des chemins de base, le masquage utilise les pixels d'une image ou d'un dégradé pour déterminer la visibilité. Contrairement au clipping, le masquage permet de rendre certaines zones d'un élément partiellement transparentes. Plusieurs images de masque peuvent être appliquées à un élément pour produire différents effets.

Pour appliquer un masque, définissez la propriété mask-image. Cette propriété accepte une ou plusieurs images, dégradés ou références à des éléments <mask> dans un document SVG. Vous pouvez appliquer plusieurs images de masque en les séparant par des virgules.

.my-element {
  mask-image: url(my-mask.png),
              linear-gradient(black 0%, transparent 100%);
}

Dans l'exemple précédent, .my-element est masqué à l'aide d'une image PNG, suivie d'un dégradé linéaire. Par défaut, plusieurs masques sont ajoutés pour créer le masque final.

L'exemple précédent montre une image avec une ou plusieurs masques appliqués. Activez chaque masque pour voir comment ils se combinent pour produire l'effet final.

Masquage alpha et de luminance

Vous pouvez appliquer un masque à l'aide de la alpha ou de la luminance de l'image. Lorsque vous masquez un élément en fonction de alpha, la transparence de chaque pixel de l'image de masque est appliquée à l'élément, en ignorant toute information de couleur de ce pixel. Lorsque le masquage est basé sur luminance, la transparence et la valeur de chaque pixel (luminosité ou obscurité) sont appliquées à l'élément. Le masquage par luminance considère les couleurs claires comme visibles et les couleurs foncées comme invisibles.

Pour définir le mode de masquage, utilisez la propriété mask-mode. Par défaut, la propriété mask-mode est définie sur match-source, ce qui définit un mode en fonction du type d'image de masque. Pour les images et les dégradés, la valeur par défaut est alpha. Pour les masques SVG, la valeur par défaut est la valeur de la propriété mask-type de l'élément <mask> ou luminance si aucune propriété mask-type n'est définie.

Dans l'exemple précédent, un motif de test affichant différentes valeurs de couleur et alpha est utilisé comme masque. En activant ou désactivant mask-mode, vous pouvez voir comment le mode alpha est basé sur la transparence, tandis que le mode luminance est basé à la fois sur la luminosité et la transparence des couleurs.

Propriétés de masquage supplémentaires

Le CSS fournit des propriétés supplémentaires pour affiner le comportement de vos masques. Chacune des propriétés accepte une liste de valeurs séparées par une virgule, qui seront mises en correspondance avec la liste des masques définis par la propriété mask-image. S'il y a moins de valeurs que de masques, la liste se répète jusqu'à ce qu'une valeur ait été définie pour chaque masque. S'il y a plus de valeurs que de masques, les valeurs excédentaires sont ignorées.

Propriété Description
mask-clip

Définit la boîte de référence à laquelle les masques d'éléments sont appliqués. La valeur par défaut est border-box..

mask-composite

Définit l'interaction entre les masques lorsque plusieurs masques sont appliqués au même élément. La valeur par défaut est add.

mask-origin

Définit le cadre de référence qui sert d'origine à un masque. La valeur par défaut est border-box. Il se comporte de la même manière que background-origin et accepte les mêmes mots clés.

mask-position

Définit la position d'un masque par rapport à mask-origin. Accepte les valeurs de mot clé de position telles que top ou center, les pourcentages, les unités de taille ou les valeurs relatives à un mot clé de position. Il se comporte de la même manière que background-position et accepte les mêmes types d'arguments.

mask-repeat

Définit la façon dont un masque se répète si l'élément masqué est plus grand que le masque. La valeur par défaut est repeat. Il se comporte de la même manière que background-repeat et accepte les mêmes types d'arguments.

mask-size

Définit la façon dont un masque est redimensionné par rapport à la taille de l'élément masqué. La valeur par défaut est auto. Il se comporte de la même manière que background-size et accepte les mêmes types d'arguments.

Abréviation du masque

Vous pouvez définir plusieurs propriétés de masque à la fois avec le raccourci de masque. Cela peut simplifier la définition de plusieurs masques en regroupant toutes les propriétés de chaque masque. Le raccourci de masque équivaut à définir ces propriétés dans l'ordre : mask-image, mask-mode, mask-position, mask-size, mask-repeat, mask-origin, mask-clip et mask-composite. Toutes les propriétés ne doivent pas être incluses. Celles qui ne le sont pas seront réinitialisées à leur valeur initiale. Comme vous pouvez ajouter jusqu'à huit propriétés par masque, il peut être utile de disposer d'une référence complète.

.longhand {
  mask-image: linear-gradient(white, black),
              linear-gradient(90deg, black, transparent);
  mask-mode: luminance, alpha;
  mask-position: bottom left, top right;
  mask-size: 50% 50%, 30% 30%;
}

.shorthand {
  mask: linear-gradient(white, black) luminance bottom left / 50% 50%,
        linear-gradient(90deg, black, transparent) alpha top right / 30% 30%;
}

Dans l'exemple précédent, deux masques sont appliqués à chaque classe. La première utilise des propriétés individuelles, tandis que la seconde utilise le raccourci mask. Les deux styles sont équivalents.

Texte flottant autour d'éléments flottants

Lorsque vous découpez ou masquez un élément, vous ne modifiez que la zone visible à l'intérieur de sa boîte, mais la boîte elle-même reste inchangée. Cela signifie qu'un élément flottant affecte le flux du document en fonction de son cadre de sélection d'origine, et non des parties visibles de l'élément. Pour définir le flux autour d'un élément, utilisez la propriété shape-outside avec le chemin de découpe.

La propriété shape-outside définit la forme autour de laquelle le contenu s'affichera autour d'un élément. Cette forme peut être l'une des fonctions de forme de base, mais pas les formes définies à l'aide des fonctions path() ou shape(), ni un clipPath défini dans un document SVG.

La propriété shape-outside accepte également une image ou un dégradé. Comme pour le masquage, les limites de la forme seront déterminées par la transparence de l'image ou du dégradé. La propriété shape-image-threshold définit les niveaux de transparence considérés à l'intérieur de la forme.

Formes dans une animation

Animer clip-path

Vous pouvez animer la propriété clip-path, en effectuant une transition d'une forme à l'autre. Vous devez utiliser la même fonction de forme pour chaque image clé afin de produire des animations fluides. Lorsque vous utilisez les fonctions polygon() ou shape(), le même nombre de points doit être utilisé dans chaque image clé.

Dans l'exemple précédent, le clip-path d'un élément passe d'un pentagone à une étoile définie à l'aide de la fonction polygon(). L'exemple utilise la règle de remplissage evenodd pour montrer comment les points animés créent des zones qui se chevauchent.

Animer avec offset-path

Vous pouvez également animer des éléments le long des chemins créés avec ces fonctions de forme. La propriété offset-path définit la forme à utiliser comme chemin d'accès, et offset-distance définit la position le long de ce chemin. Vous pouvez également utiliser la fonction ray() avec la propriété offset-path pour animer un élément le long d'une ligne droite.

L'exemple précédent montre comment utiliser le même polygone pour un clip-path et un offset-path. L'animation utilise offset-distance pour déplacer les petites étoiles le long du même polygone que celui utilisé par la grande étoile comme clip-path.

Vérifier que vous avez bien compris

Quelles sont les fonctions de forme valides ?

circle()
Bonne réponse !
square()
Pas tout à fait.
hexagon()
Pas tout à fait.
polygon()
Bonne réponse !
rectangle()
Pas tout à fait.
inset()
Bonne réponse !

Vrai ou faux : Les formes définies avec la fonction path() peuvent être définies à l'aide de pourcentages

Vrai
Pas tout à fait.
Faux
Bonne réponse !

Vrai ou faux : Définir le tracé de détourage d'un élément ne modifie pas le flux de texte autour de cet élément.

Vrai
Bonne réponse !
Faux
Pas tout à fait.

Quels éléments peuvent être utilisés comme tracé de détourage ?

Forme de base
Bonne réponse !
Un élément clipMask SVG
Bonne réponse !
Image bitmap
Pas tout à fait.
Dégradé
Pas tout à fait.

Laquelle des options suivantes peut être utilisée comme masque ?

Image bitmap
Bonne réponse !
Dégradé
Bonne réponse !
Élément de masque SVG
Bonne réponse !
Une forme de base, comme circle() ou rect()
Pas tout à fait.