Utiliser shape() pour le recadrage responsif

Publié le 8 avril 2025

La propriété clip-path vous permet de modifier la forme d'un élément en le recouvrant d'un cercle, d'un polygone ou même d'un tracé SVG. Toutefois, avant Chrome 135 et Safari 18.4, vous deviez choisir entre des polygones responsifs et des formes plus complexes qui ne sont pas responsifs à l'aide de tracés SVG. Avec la nouvelle fonction shape(), un clip-path peut découper l'élément dans une forme non polygonale qui est également responsive.

Browser Support

  • Chrome: 135.
  • Edge: 135.
  • Firefox Technology Preview: supported.
  • Safari: 18.4.

Source

Créer une forme de drapeau

Par exemple, comparez la création d'une forme de drapeau avec clip-path: path() et clip-path: shape().

Forme de drapeau vert avec des lignes incurvées en haut et en bas.

Une forme de drapeau n'est pas exactement un polygone, car ses bordures supérieure et inférieure sont des courbes Bézier cubiques plutôt que des lignes droites ou des coins arrondis.

Créer l'indicateur avec clip-path: path()

Une forme comme ce drapeau peut être représentée à l'aide d'un tracé SVG:

.flag {
  clip-path: path(
    "M 0 20 \
     C 25 0 75 40 100 20 \
     V 80 \
     C 75 100 25 60 0 80 \
     z");
}

Pour simplifier, un tracé SVG est une série de commandes de tracé:

  1. Déplacez-vous vers 0, 20.
  2. Courbe vers 100, 20, à l'aide de points de contrôle (25,0 et 75, 40).
  3. Ligne verticale jusqu'à 80.
  4. Courbe vers 0, 80, à l'aide de points de contrôle (75,100 et 25,50).
  5. Fermez le tracé (ligne jusqu'à 0,20).

Cela dessine une forme de drapeau, mais toutes les unités sont en pixels. Le SVG peut mettre à l'échelle ces pixels dans une zone de vision, mais de manière à ce que cela ressemble toujours à une échelle géométrique de l'ensemble de la forme.

Par exemple, si vous souhaitez que l'ensemble du rectangle soit mis à l'échelle, mais que la hauteur et la largeur des courbes restent de 20 pixels, le SVG ne sera pas à la hauteur de la tâche.

Créer l'indicateur avec shape()

Comparez le même résultat à l'aide de shape(). La fonction de forme accepte une série de commandes, semblables aux commandes de tracé SVG. Toutefois, ces commandes acceptent des longueurs et des pourcentages CSS, dans n'importe quelle unité CSS.

Le CSS suivant convertit l'indicateur en shape() avec des unités de pourcentage:

.flag {
  clip-path: shape(from 0% 20%,
     curve to 100% 20% with 25% 0% / 75% 40%,
     vline to 80%,
     curve to 0% 80% with 75% 100% / 25% 60%,
     close
  );
}

Réactivité

Avec la gamme complète de longueurs CSS disponibles, vous pouvez choisir celles à utiliser pour chaque coordonnée.

Par exemple, pour que la taille totale de l'indicateur soit mise à l'échelle en fonction de la taille de l'élément, mais que la hauteur de la courbe reste constante, procédez comme suit:

.flag {
  clip-path: shape(from 0% 20px,
     curve to 100% 20px with 25% 0% / 75% 40px,
     vline to calc(100% - 20px),
     curve to 0% calc(100% - 20px) 
           with 75% 100% / 25% calc(100% - 40px),
     close
  );
}

Ajouter des propriétés et des animations personnalisées

La forme étant désormais définie en CSS, vous pouvez également utiliser des propriétés personnalisées pour manipuler facilement la hauteur:

.flag {
  --wave-height: 40px;
  clip-path: shape(
    from 0px var(--wave-height),
    curve to 100% var(--wave-height) 
          with 25% 0px / 75% calc(var(--wave-height) * 2),
    vline to calc(100% - var(--wave-height)),
    curve to 0 calc(100% - var(--wave-height))
          with 75% 100% / 25% calc(100% - var(--wave-height) * 2),
    close
  )
}

Vous pouvez même animer la propriété CSS à l'aide du descripteur @property et la fixer pour qu'elle ne dépasse pas:

@property --animated-wave-height {
  syntax: "<length>";
  inherits: false;
  initial-value: 40px;
}

@keyframes curve {
  from { --animated-wave-height: 0px; }
  to { --animated-wave-height: 180px; }
}

.flag {
  width: 600px;
  height: 400px;
  background: green;
  animation: curve 1s infinite alternate;
  --wave-height: calc(min(var(--animated-wave-height, 40px), 40%));
  clip-path: shape(
    from 0px var(--wave-height),
    curve to 100% var(--wave-height)
          with 25% 0px / 75% calc(var(--wave-height) * 2),
    vline to calc(100% - var(--wave-height)),
    curve to 0 calc(100% - var(--wave-height)) 
          with 75% 100% / 25% calc(100% - var(--wave-height) * 2),
    close
  )
}

Essayer la démo

Dans Chrome 135 ou Safari 18.4, vous pouvez voir la forme d'icône animée créée à l'aide de clip-path: shape() dans cette démonstration CodePen.

Résumé

clip-path: shape() vous permet de découper votre élément à l'aide de formes arbitraires et réactives, ce qui n'était auparavant possible qu'à l'aide de techniques telles que les dégradés coniques ou les SVG construits en JavaScript.

Consultez la spécification pour connaître la syntaxe complète.

Pour le moment, il ne fonctionne que pour clip-path. À l'avenir, nous envisageons d'utiliser ce type de forme pour définir la forme de la bordure de l'élément, ce qui ouvrirait encore plus de possibilités d'expression non rectangulaires.