Cette page a été traduite à partir de l'anglais par la communauté. Vous pouvez contribuer en rejoignant la communauté francophone sur MDN Web Docs.

View in English Always switch to English

Propriété CSS border-shape

Disponibilité limitée

Cette fonctionnalité n'est pas Compatible car elle ne fonctionne pas dans certains des navigateurs les plus utilisés.

Want more browser support for this feature? Tell us why.

Expérimental: Il s'agit d'une technologie expérimentale.
Vérifiez attentivement le tableau de compatibilité des navigateurs avant de l'utiliser en production.

La propriété CSS border-shape définit la forme de la bordure d'un élément en utilisant des valeurs <basic-shape>.

Syntaxe

css
/* Mot-clé */
border-shape: none;

/* Une seule valeur <basic-shape> */
border-shape: circle(50%);
border-shape: rect(10px 460px 130px 20px round 20px);
border-shape: shape(
  from 5% 0.5rem,
  arc to 80px 1pt of 10% ccw large rotate 25deg
);

/* Deux valeurs <basic-shape> */
border-shape: circle(50%) ellipse(40% 30%);
border-shape: polygon(0% 0%, 0% 100%, 100% 0%)
  polygon(10% 10%, 10% 70%, 70% 10%);

/* Valeurs <basic-shape> et <geometry-box> */
border-shape: circle(50%) border-box ellipse(40% 30%) view-box;
border-shape: rect(5px 198px 189px 0px round 20px) view-box circle(50%);
border-shape: path(
    "M 35,95 C 35,50 60,15 100,20 C 120,5 160,5 180,22 C 200,5 250,5 270,22 C 295,5 340,5 360,22 C 395,10 440,35 440,75 C 455,90 450,120 430,128 C 400,145 360,145 330,130 C 300,145 260,145 230,130 C 200,145 160,145 130,130 C 80,142 35,120 35,95 Z"
  )
  view-box;

/* Valeurs globales */
border-shape: inherit;
border-shape: initial;
border-shape: revert;
border-shape: revert-layer;
border-shape: unset;

La propriété border-shape peut être définie en utilisant le mot-clé none, ou une ou deux définitions de forme séparées par des espaces, chacune consistant en une valeur <basic-shape> ou une valeur <basic-shape> et une valeur <geometry-box>.

Valeurs

none

Définit qu'aucune forme de bordure n'est définie. Il s'agit de la valeur initiale.

<basic-shape>

Définit la forme de la bordure en utilisant l'une des fonctions <basic-shape>.

<geometry-box> Facultatif

Définit la boîte de référence par rapport à laquelle la forme de la bordure est dessinée. Si elle n'est pas incluse, la boîte de géométrie de référence de la forme par défaut est :

  • half-border-box si une seule forme de base est définie, ce qui signifie que toute bordure définie est dessinée au-dessus du chemin de la forme, le chemin passant par son centre.
  • border-box pour la première forme (externe) et padding-box pour la deuxième forme (interne) si deux formes de base sont définies. La bordure occupe alors la zone entre les deux formes.

Description

La propriété border-shape peut être appliquée aux éléments pour créer des conteneurs de forme précise, tels que des bulles de dialogue, comme illustré ici, ou des infobulles abstraites, sans avoir à utiliser de solutions de contournement.

Notez comment la border-shape appliquée s'accorde bien avec la bordure (border) et l'ombre (box-shadow) définies sur l'élément — elles suivent la forme de la bordure.

Prise en charge des fonctions de forme

Vous pouvez définir la border-shape d'un élément (y compris celle d'un élément en ligne ou pseudo-élément) en utilisant l'une des fonctions <basic-shape>. Ces fonctions incluent :

  • inset(), rect() et xywh() : Fournissent différentes façons de définir des formes rectangulaires de base.
  • circle() : Définit des formes circulaires.
  • ellipse() : Définit des formes elliptiques.
  • path() : Définit tout type de forme en utilisant la syntaxe de chaîne de caractères de chemin SVG. La syntaxe SVG path a des limitations — elle ne peut utiliser que des valeurs en pixels et le chemin doit être défini comme une seule chaîne de caractères, donc les propriétés personnalisées ne peuvent pas être incluses avec var(). Il est conseillé d'utiliser shape() à la place.
  • polygon() : Définit tout type de polygone à l'aide de paires de coordonnées de sommets. Si la forme souhaitée comporte des courbes lisses, il est recommandé d'utiliser la fonction shape().
  • shape() : Définit tout type de forme. La syntaxe de shape() est plus compatible avec CSS que celle de path() et résout ses limitations.

Vous pouvez également inclure un mot-clé optionnel <geometry-box> après chaque valeur <basic-shape> pour définir la boîte de référence par rapport à laquelle les formes doivent être dessinées.

Modes de trait et de remplissage

La propriété border-shape a les deux modes suivants :

  • Si une seule <basic-shape> est fournie dans la valeur, cette forme définit la forme de la bordure de l'élément, les styles de bordure définis étant dessinés comme un trait autour de la forme, comme illustré dans l'exemple précédent. C'est ce qu'on appelle le mode trait.
  • Si deux <basic-shape> sont fournis dans la valeur, la première forme définit la limite extérieure de la bordure, la deuxième forme définit la limite intérieure de la bordure, et toute couleur de bordure définie remplit la zone entre les deux limites. C'est ce qu'on appelle le mode remplissage.

Note : Évitez de définir une forme pour la limite intérieure qui soit plus grande que la limite extérieure. Si vous le faites, la zone de la bordure ne s'affiche pas correctement ; vous risquez de ne voir aucun remplissage de bordure ou qu'une forme soit affichée derrière l'autre.

Effet sur la disposition et le rendu

La propriété border-shape crée un effet purement visuel — la disposition de l'élément est toujours calculée en utilisant la définition de boîte rectangulaire sous-jacente, et le flux de contenu n'est pas affecté.

Le contenu et l'arrière-plan de l'élément sont découpés par la propriété border-shape (la forme intérieure en mode remplissage). Lorsque la border-shape définie a la même taille ou est plus petite que le contenu/l'arrière-plan, vous n'avez pas besoin d'ajuster la boîte de référence, sauf si vous souhaitez créer un certain effet de décalage. Cependant, lorsque la border-shape définie est plus grande que le contenu/l'arrière-plan, vous pouvez voir des écarts entre le bord de l'arrière-plan et la ou les formes. Dans ce cas, vous devez peut-être utiliser une boîte de référence différente pour corriger l'affichage (voir Gérer les border-shapes plus grandes que l'arrière-plan de l'élément pour plus d'informations).

Limitations sur les styles de bordure appliqués aux formes de bordure

Tous les styles de bordure ne sont pas appliqués aux éléments ayant la propriété border-shape définie. La liste suivante explique comment chaque propriété est affectée :

  • border-color : Cette propriété est appliquée. Cependant, lorsque plusieurs bordures d'éléments ont des couleurs différentes appliquées, le navigateur choisit le premier bord avec une couleur de bordure, dans l'ordre suivant :

    • Bord du bloc de début
    • Bord en ligne de début
    • Bord du bloc de fin
    • Bord en ligne de fin

    Le navigateur applique ensuite la couleur de bordure de ce bord à l'ensemble de la border-shape rendue.

  • border-image : N'est pas appliquée.

  • border-style : N'est pas appliquée. Toutes les bordures sont rendues avec un style solid.

  • border-width : En mode trait, border-width est appliqué directement à la border-shape rendue. Lorsque plusieurs bords ont des largeurs de bordure différentes, le navigateur choisit une largeur à appliquer à l'ensemble de la bordure en utilisant le même processus que celui décrit pour border-color.

    En mode remplissage, la zone de la bordure est définie par la différence entre les zones des formes extérieure et intérieure ; par conséquent, border-width n'a pas d'effet direct sur la largeur de la bordure rendue. Cependant, il a un effet indirect — il affecte toujours la taille des boîtes de référence par rapport auxquelles les formes sont dessinées (sauf si vous définissez leur <geometry-box> sur content-box ou padding-box). Vous devez donc toujours tenir compte du border-width défini sur l'élément sous-jacent lors de l'utilisation du mode remplissage.

Par exemple, si un élément a les déclarations suivantes appliquées :

css
border-shape: rect(5px 198px 189px 0px round 20px);
border-bottom: 30px dashed blue;
border-left: 40px dotted hotpink;
border-right: 50px double yellow;

La boîte rendue a une bordure rectangulaire avec des coins arrondis. Le style de la bordure est solid, car les autres styles sont ignorés. La largeur et la couleur de la bordure sont respectivement de 40px et hotpink — c'est dû au fait que la propriété border-left applique des styles au bord de début en ligne (en supposant que la page a un writing-mode horizontal), qui est le premier bord avec des styles de bordure ; celui-ci est choisi par le navigateur selon la liste de priorité décrite précédemment.

Interaction avec border-radius et corner-shape

Les propriétés border-radius et corner-shape sont incompatibles avec border-shape. Lorsqu'une border-shape est définie sur un élément, tout border-radius défini est ignoré, donc corner-shape n'a également aucun effet. Les propriétés border-shape et border-radius/corner-shape ont des effets différents et sont utilisées séparément.

Si vous souhaitez utiliser des coins façonnés dans une border-shape, vous devez les dessiner directement dans la forme.

border-shape contre clip-path

La propriété clip-path prend des valeurs similaires à border-shape et produit des effets similaires. Les deux propriétés peuvent être utilisées pour changer la forme d'un élément et donc la zone cliquable de l'élément, modifiant la limite à l'intérieur de laquelle les effets :hover et les évènements liés au pointeur sont activés.

Cependant, il existe une différence fondamentale dans le fonctionnement des deux propriétés :

  • clip-path masque la zone de l'élément qui se trouve en dehors de la région définie par la forme fournie.
  • border-shape modifie le rendu visuel de l'élément afin qu'il se trouve à l'intérieur de la région définie par la forme fournie.

Cela signifie que border-shape découpe le contenu de l'élément tout en laissant la propriété overflow contrôler son affichage, tandis que clip-path masque complètement le contenu de l'élément, de sorte que le contrôle du débordement n'est pas possible.

De plus, des propriétés telles que box-shadow et outline ne suivent pas la forme créée par clip-path — elle coupe l'extérieur de l'élément, ce qui signifie que ces effets sont tronqués de manière disgracieuse ou supprimés complètement. La propriété border-shape, en revanche, crée une bordure de forme différente qui est suivie correctement par ces effets.

Gérer les border-shapes plus grandes que l'arrière-plan de l'élément

Comme mentionné précédemment, un problème avec border-shape est que lorsque vous définissez une forme qui est plus grande que le contenu/l'arrière-plan de l'élément, vous pouvez vous retrouver avec un écart entre l'arrière-plan et la bordure.

La méthode recommandée pour résoudre ce problème consiste à définir la <geometry-box> de référence sur content-box, puis à utiliser padding pour combler les écarts entre le contenu et la bordure. Par exemple :

css
border-shape: shape(
    from 0% 0%,
    hline to 33%,
    arc by 33% 0% of 16% 20% small cw,
    hline to 100%,
    line to 100% 33%,
    arc by 0% 33% of 20% 16% small cw,
    line to 100% 100%,
    hline to 66%,
    arc by -33% 0% of 16% 20% small ccw,
    hline to 0%,
    line to 0% 66%,
    arc by 0% -33% of 20% 16% small ccw,
    close
  )
  content-box;
padding: 24px;

De cette façon, le padding est défini à l'extérieur de la forme, ce qui la fait rétrécir et force l'arrière-plan à remplir les parties de la forme qui dépassent de la zone de contenu. Vous pouvez voir cette technique en action dans notre exemple de menu de navigation en forme de pièce de puzzle irrégulière.

Définition formelle

Valeur initialenone
Applicabilitétous les éléments
Héritéenon
Valeur calculéecomme défini
Type d'animationpar type de valeur calculée

Syntaxe formelle

border-shape = 
none |
[ <basic-shape> <geometry-box>? ]{1,2}

<basic-shape> =
<basic-shape-rect> |
<circle()> |
<ellipse()> |
<polygon()> |
<path()> |
<shape()>

<geometry-box> =
<shape-box> |
fill-box |
stroke-box |
view-box

<basic-shape-rect> =
<inset()> |
<rect()> |
<xywh()>

<circle()> =
circle( <radial-size>? [ at <position> ]? )

<ellipse()> =
ellipse( <radial-size>? [ at <position> ]? )

<polygon()> =
polygon( <'fill-rule'>? [ round <length> ]? , [ <length-percentage> <length-percentage> ]# )

<path()> =
path( <'fill-rule'>? , <string> )

<shape()> =
shape( <'fill-rule'>? from <position> , <shape-command># )

<shape-box> =
<visual-box> |
margin-box |
half-border-box

<inset()> =
inset( <length-percentage>{1,4} [ round <'border-radius'> ]? )

<rect()> =
rect( <top> , <right> , <bottom> , <left> )

<xywh()> =
xywh( <length-percentage>{2} <length-percentage [0,∞]>{2} [ round <'border-radius'> ]? )

<radial-size> =
<radial-extent> |
<length [0,∞]> |
<length-percentage [0,∞]>{2}

<position> =
<position-one> |
<position-two> |
<position-four>

<fill-rule> =
nonzero |
evenodd

<length-percentage> =
<length> |
<percentage>

<shape-command> =
<move-command> |
<line-command> |
close |
<horizontal-line-command> |
<vertical-line-command> |
<curve-command> |
<smooth-command> |
<arc-command>

<visual-box> =
content-box |
padding-box |
border-box

<border-radius> =
<length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]?

<radial-extent> =
closest-corner |
closest-side |
farthest-corner |
farthest-side

<position-one> =
left |
center |
right |
top |
bottom |
x-start |
x-end |
y-start |
y-end |
block-start |
block-end |
inline-start |
inline-end |
<length-percentage>

<position-two> =
[ left | center | right | x-start | x-end ] && [ top | center | bottom | y-start | y-end ] |
[ left | center | right | x-start | x-end | <length-percentage> ] [ top | center | bottom | y-start | y-end | <length-percentage> ] |
[ block-start | center | block-end ] && [ inline-start | center | inline-end ] |
[ start | center | end ]{2}

<position-four> =
[ [ left | right | x-start | x-end ] <length-percentage> ] && [ [ top | bottom | y-start | y-end ] <length-percentage> ] |
[ [ block-start | block-end ] <length-percentage> ] && [ [ inline-start | inline-end ] <length-percentage> ] |
[ [ start | end ] <length-percentage> ]{2}

<move-command> =
move <command-end-point>

<line-command> =
line <command-end-point>

<horizontal-line-command> =
hline [ to [ <length-percentage> | left | center | right | x-start | x-end ] | by <length-percentage> ]

<vertical-line-command> =
vline [ to [ <length-percentage> | top | center | bottom | y-start | y-end ] | by <length-percentage> ]

<curve-command> =
curve [ [ to <position> with <control-point> [ / <control-point> ]? ] | [ by <coordinate-pair> with <relative-control-point> [ / <relative-control-point> ]? ] ]

<smooth-command> =
smooth [ [ to <position> [ with <control-point> ]? ] | [ by <coordinate-pair> [ with <relative-control-point> ]? ] ]

<arc-command> =
arc <command-end-point> [ [ of <length-percentage>{1,2} ] && <arc-sweep>? && <arc-size>? && [ rotate <angle> ]? ]

<command-end-point> =
to <position> |
by <coordinate-pair>

<control-point> =
<position> |
<relative-control-point>

<coordinate-pair> =
<length-percentage>{2}

<relative-control-point> =
<coordinate-pair> [ from [ start | end | origin ] ]?

<arc-sweep> =
cw |
ccw

<arc-size> =
large |
small

Exemples

Utilisation simple de border-shape en mode trait

Cet exemple montre comment utiliser border-shape en mode trait.

HTML

Le balisage pour cet exemple contient un seul élément HTML <p>.

html
<p>Cercle</p>

CSS

Nous donnons à la boîte une largeur (width) de fit-content et un rapport d'aspect (aspect-ratio) de 1/1 pour que le contenu s'adapte parfaitement à l'intérieur d'un carré. Nous définissons également une bordure (border) noire épaisse et une ombre (box-shadow) avant de définir une forme de bordure (border-shape) de circle(50%) pour créer une bordure circulaire qui s'adapte parfaitement au contenu et à l'arrière-plan.

css
p {
  width: fit-content;
  aspect-ratio: 1/1;
  border: 15px solid black;
  box-shadow: 5px 5px 10px rgb(0 0 0 / 0.5);
  border-shape: circle(50%);
}

Résultat

Notez comment la bordure (border) et l'ombre (box-shadow) suivent parfaitement la forme définie.

Utilisation simple de border-shape en mode remplissage

Cet exemple s'appuie sur le précédent et montre comment utiliser border-shape en mode remplissage pour créer une bordure remplie irrégulière.

Le HTML est le même que dans l'exemple précédent.

CSS

Le CSS est le même que dans l'exemple précédent, sauf que cette fois nous colorions la bordure en hotpink et que nous incluons deux définitions de <basic-shape> à l'intérieur de la valeur border-shape. Il y a un rectangle extérieur qui couvre toute la zone du contenu et un cercle intérieur identique à celui de l'exemple précédent.

css
p {
  width: fit-content;
  aspect-ratio: 1/1;
  border: 15px solid hotpink;
  box-shadow: 5px 5px 10px rgb(0 0 0 / 0.5);
  border-shape: rect(0% 100% 100% 0% round 20px) circle(50%);
}

Résultat

Notez comment cette fois, la bordure couvre la zone entre le rectangle et le cercle, et elle adopte la couleur définie dans la déclaration border.

Comparer les valeurs de border-shape

Dans cet exemple, nous vous permettons de sélectionner différentes valeurs de border-shape à appliquer à un élément, afin que vous puissiez comparer et contraster leur rendu.

HTML

Le HTML est similaire à celui de l'exemple précédent, sauf que cette fois nous incluons un peu plus de texte dans l'élément <p>. Nous avons également inclus un élément HTML <select> afin que vous puissiez choisir différentes classes à appliquer au <p> avec JavaScript (nous avons masqué à la fois le <select> et le JavaScript pour plus de concision).

html
<p>Bienheureux sont les fromagers.</p>

Les classes définissent différentes valeurs de border-shape sur l'élément <p>. Pour commencer, une class de ellipse est définie sur l'élément <p>, donc initialement il a un border-shape de type ellipse().

CSS

Dans le CSS, nous donnons à la boîte une largeur (width) de 550px, une bordure (border) noire épaisse et une ombre (box-shadow).

css
p {
  width: 550px;
  border: 15px solid black;
  box-shadow: 5px 5px 10px rgb(0 0 0 / 0.5);
}

Ensuite, nous définissons les règles pour chacune des classes qui sont appliquées lorsque vous sélectionnez les différentes options dans l'élément <select>.

css
.circle {
  border-shape: circle(60%);
}

.ellipse {
  border-shape: ellipse(50% 40%);
}

.inset {
  border-shape: inset(10px 20px 10px 20px round 20px);
}

.path {
  border-shape: path(
      "M 35,95 C 35,50 60,15 100,20 C 120,5 160,5 180,22 C 200,5 250,5 270,22 C 295,5 340,5 360,22 C 460,10 477,35 496,75 C 515,157 450,120 430,128 C 400,145 360,145 330,130 C 300,145 260,145 230,130 C 200,145 160,145 130,130 C 80,142 35,120 35,95 Z"
    )
    view-box;
}

.polygon {
  border-shape: polygon(0% 60%, 0% 85%, 8% 100%, 18% 88%, 30% 100%, 42% 88%, 55% 100%, 68% 88%, 80% 100%, 86% 88%, 90% 75%, 100% 60%, 90% 30%, 85% 5%, 75% 18%, 65% 3%, 52% 16%, 40% 3%, 27% 16%, 15% 3%, 5% 18%) view-box;
}

.rect {
  border-shape: rect(10px 500px 130px 20px round 20px);
}

.shape {
  border-shape: shape(
    from 0% 64.5%,
    curve to 15.71% 8.26% with 0% 30.76%/6.04% 4.51%,
    curve to 35.05% 9.76% with 20.55% -2.99%/30.21% -2.99%,
    curve to 56.8% 9.76% with 39.88% -2.99%/51.97% -2.99%,
    curve to 78.56% 9.76% with 62.84% -2.99%/73.72% -2.99%,
    curve to 97.89% 49.5% with 87.02% 0.76%/97.89% 19.51%,
    curve to 95.47% 89.25% with 101.52% 60.75%/100.31% 83.25%,
    curve to 71.3% 90.75% with 88.22% 102%/78.56% 102%,
    curve to 47.13% 90.75% with 64.05% 102%/54.38% 102%,
    curve to 22.96% 90.75% with 39.88% 102%/30.21% 102%,
    curve to 0% 64.5% with 10.88% 99.75%/0% 83.25%,
    close
  );
}

.two-polygons {
  border-shape: polygon(0% 60%, 0% 85%, 8% 100%, 18% 88%, 30% 100%, 42% 88%, 55% 100%, 68% 88%, 80% 105%, 86% 88%, 91% 75%, 101% 60%, 93% 30%, 86% 5%, 75% 18%, 65% 3%, 52% 16%, 40% 3%, 27% 16%, 15% 3%, 5% 18%)
    polygon(0% 55%, 0% 90%, 6% 104%, 17% 93%, 30% 100%, 43% 93%, 56% 102%, 69% 93%, 81% 102%, 88% 93%, 94% 78%, 100% 58%, 94% 24%, 88% -2%, 76% 13%, 64% -4%, 51% 11%, 39% -4%, 26% 11%, 13% -4%, 3% 13%);
}

.xywh {
  border-shape: xywh(5% 5% 90% 90% round 20px);
}

Résultat

Sélectionnez différentes options dans le menu déroulant pour voir comment les différentes formes de bordure sont rendues. À tout moment, n'hésitez pas à utiliser les outils de développement de votre navigateur pour inspecter les valeurs de border-shape appliquées à l'élément <p> et les modifier pour vous faire une idée de leur fonctionnement.

Animer une border-shape

Cet exemple montre comment vous pouvez animer la propriété border-shape.

HTML

Le même élément <p> est utilisé que dans l'exemple précédent, sauf que cette fois nous avons inclus un attribut tabindex afin qu'il puisse être sélectionné par le clavier.

html
<p tabindex="0">Bienheureux sont les fromagers.</p>

CSS

Pour cet exemple, nous appliquons une border-shape de type polygon() à l'élément <p>.

css
p {
  width: 550px;
  border: 15px solid black;
  box-shadow: 5px 5px 10px rgb(0 0 0 / 0.5);
  border-shape: polygon(0% 60%, 0% 85%, 8% 100%, 18% 88%, 30% 100%, 42% 88%, 55% 100%, 68% 88%, 80% 100%, 86% 88%, 90% 75%, 100% 60%, 90% 30%, 85% 5%, 75% 18%, 65% 3%, 52% 16%, 40% 3%, 27% 16%, 15% 3%, 5% 18%) view-box;
}

Nous appliquons également une animation aux états :hover et :focus de l'élément <p>, de sorte que lorsque l'élément est survolé ou sélectionné, il anime en douceur les deux formes de bordure polygonales de manière infinie.

css
p:hover,
p:focus {
  animation: morph 1s ease-in-out infinite alternate;
}

@keyframes morph {
  from {
    border-shape: polygon(0% 60%, 0% 85%, 8% 100%, 18% 88%, 30% 100%, 42% 88%, 55% 100%, 68% 88%, 80% 100%, 86% 88%, 90% 75%, 100% 60%, 90% 30%, 85% 5%, 75% 18%, 65% 3%, 52% 16%, 40% 3%, 27% 16%, 15% 3%, 5% 18%) view-box;
  }
  to {
    border-shape: polygon(0% 55%, 0% 90%, 6% 104%, 17% 93%, 30% 100%, 43% 93%, 56% 102%, 69% 93%, 81% 102%, 88% 93%, 94% 78%, 100% 58%, 94% 24%, 88% -2%, 76% 13%, 64% -4%, 51% 11%, 39% -4%, 26% 11%, 13% -4%, 3% 13%) view-box;
  }
}

Résultat

Survolez ou sélectionnez le paragraphe pour voir l'animation.

Spécifications

Spécification
CSS Borders and Box Decorations Module Level 4
# border-shape

Compatibilité des navigateurs

Voir aussi