Arrondir les angles

Nantes, le 8 mars 2016.

C’est depuis fin 2010 qu’il est possible de réaliser simplement via CSS des bordures arrondies. Pourtant, dans la plupart des cas, nous n’en faisons qu’un usage limité, au point d’être un peu perdus quand il s’agit de sortir des sentiers battus.

Je vous propose donc de (re) voir en détail son fonctionnement.


Le cas classique sur lequel on vient buter c’est l’effet « pilule » sur les CTA.

On s’imagine qu’avec un rectangle et un `border-radius à 50 % et ça va être bon, mais on déchante vite :

On obtient une ellipse à la place de la forme oblongue souhaitée. Pourquoi ?

Un peu de mathématiques pour commencer

border-radius ne sait travailler qu’avec des ellipses – nous verrons cela en détail plus loin. Il nous faut donc bien définir ce sujet.


Qu’est-ce qu’une ellipse ?

En géométrie spatiale, les ellipses sont formées par l’intersection d’un cône avec un plan.

En géométrie plane, il s’agit à partir de deux points (dit foyers) de tracer une courbe dont les points sont tous éloignés des foyers par une somme de leurs distances constante.

Je vous conseille vivement cette vidéo de Mickaël Launay sur les coniques pour mieux visualiser tout ça. Elle fait sept minutes, c’est à la fois complet, intéressant et rapide.


On peut ensuite définir la taille d’une ellipse par ses deux rayons : le grand et le petit.

Des écritures raccourcies

Après la théorie, premier écueil : la bonne compréhension de la syntaxe.

border-radius: 50% signifie en effet beaucoup de choses. Il s’agit de trois cas particuliers simultanés :

  1. les quatre angles ont les mêmes arrondis ;
  2. les quatre arrondis sont formés par des ellipses dont les rayons ont les mêmes tailles ;
  3. les tailles des ellipses sont relatives.

Voyons ça point par point.

1. Les quatre angles ont les mêmes arrondis

border-radius est en effet la combinaison de :

  • border-top-left-radius ;
  • border-top-right-radius ;
  • border-bottom-left-radius ;
  • et border-bottom-right-radius.

border-radius: 50% est donc une écriture raccourcie de :

border-top-left-radius:     50%;
border-top-right-radius:    50%;
border-bottom-left-radius:  50%;
border-bottom-right-radius: 50%;

2. Les quatre arrondis sont formés par des ellipses dont les rayons ont les mêmes tailles

Nous avons vu plus haut que les ellipses pouvaient se définir avec deux rayons. Ce sont ses deux rayons qui sont attendus côté CSS car border-radius fonctionne ainsi : il ne sait dessiner que des ellipses.

border-top-left-radius: 50% est donc à nouveau une écriture raccourcie. Elle signifie en fait que les deux rayons de l’ellipse sont identiques.

Cela équivaut à écrire border-top-left-radius: 50% 50%;

  • La valeur de gauche correspond au rayon sur l’axe horizontal ;
  • la valeur de droite correspond au rayon sur l’axe vertical.

Le tout combiné donne donc :

border-top-left-radius:     50% 50%;
border-top-right-radius:    50% 50%;
border-bottom-left-radius:  50% 50%;
border-bottom-right-radius: 50% 50%;

3. Les tailles des ellipses sont relatives

Notre rectangle fait 300 pixels sur 100 pixels. La valeur relative à 50 % sera donc une fois calculée :

  • de 150 pixels horizontalement ;
  • de 50 pixels verticalement.

Soit une équivalence à :

border-top-left-radius:     150px 50px;
border-top-right-radius:    150px 50px;
border-bottom-left-radius:  150px 50px;
border-bottom-right-radius: 150px 50px;

Cela trace donc quatre morceaux d’ellipses identiques ayant pour grand rayon 150px et petit rayon 50px. Ce sont ses quatre morceaux qui forment alors une – nouvelle – ellipse, complète cette fois, et de même taille.


Détaillons maintenant un peu plus la syntaxe des coins arrondis CSS.

Syntaxe avancée

Les coins arrondis sont donc réalisés à partir d’ellipses, ou – dans le cas où leurs rayons sont égaux – de cercles.
Chaque angle est donc défini par un couple de valeurs, ou – si ses tailles sont identiques – d’une valeur unique.

border-top-left-radius: 30px; // un cercle
border-top-left-radius: 10px 20px; // une ellipse

Nous avons vu également qu’il était possible de cibler directement les quatre angles.

border-radius: 30px; // quatre cercles

Voyons maintenant comment définir (avec une seule déclaration) quatre angles, tous avec des ellipses différentes.

border-radius: 10px 20px 30px 40px / 50px 60px 70px 80px;

Tout comme précédemment, nous allons retrouver :

  • à gauche, les valeurs qui correspondent aux rayons sur l’axe horizontal ;
  • à droite, les valeurs correspondent aux rayons sur l’axe vertical.

Mais vous noterez cette fois que les valeurs sont séparées par une barre oblique. Elle permet de réaliser de nouveaux raccourcis, comme nous allons le voir.


Vous connaissez sans doute les propriétés raccourcies pour les marges :

  1. margin: 10px;
  2. margin: 10px 20px;
  3. margin: 10px 20px 30px;
  4. margin: 10px 20px 30px 40px;

Dans chaque cas on vient cibler :

  1. les quatre côtés ;
  2. les côtés opposés deux à deux, en commençant par ceux du haut et du bas ;
  3. le côté du haut, les côtés opposés, et le côté du bas ;
  4. les côtés un à un, en commençant par celui du haut et en tournant dans le sens des aiguilles d’une montre.

Et bien il en va de même pour les angles :

  1. si une valeur est passée, les quatre angles sont ciblés ;
  2. si deux valeurs sont passées, les angles opposés sont ciblés deux à deux, en partant de l’angle supérieur gauche et de l’angle inférieur droit ;
  3. si trois valeurs sont passées, l’angle supérieur gauche est ciblé, plus les deux angles opposés, puis l’angle inférieur droit ;
  4. si quatre valeurs sont passées, les quatre angles sont ciblés un à un, en partant de l’angle supérieur gauche et en tournant dans le sens des aiguilles d’une montre.

On pourra donc – grâce à la barre oblique – écrire des syntaxes de ce type :

border-radius: 10px 40px / 50px 70px 80px;
border-radius: 10px 40px / 50px 80px;
border-radius: 10px / 50px 60px 70px 80px;

En une déclaration, on vient donc :

  • cibler tous les coins de l’élément ;
  • définir les rayons horizontaux des ellipses (éventuellement regroupés) ;
  • définir les rayons verticaux des ellipses (éventuellement regroupés).

Au passage, notez que le mot clef inherit ne pourra être passé qu’a l’ensemble de la propriété : il est impossible de redéfinir uniquement le rayon vertical (ou horizontal) d’une des ellipses.

Valeurs limites

Quelles tailles pouvons-nous donner aux ellipses ?

Elles peuvent être définies avec des unités relatives ou des unités absolues, les précédents exemples l’illustrent. (Contrairement aux bordures qui n’acceptent pas les tailles en pourcentages.)

Il est intéressant de noter que les ellipses peuvent être plus grandes que les boîtes qui les contiennent. Ainsi border-top-left-radius: 100%; fera apparaître le quart d’une ellipse quatre fois plus grande que sa boîte (et nous n’en voyons qu’une portion).

Mais il y a une limite supplémentaire… Ajoutons une seconde ellipse pour la visualiser.

On voit sur cette animation que si la taille de l’ellipse du coin supérieur droit est augmentée, la taille de l’ellipse initiale (sur le coin supérieur gauche) est automatiquement réduite.

L’explication de ce phénomène peu connu est détaillée dans les spécifications : un facteur de réduction est appliqué à l’ensemble des ellipses d’une boîte, de manière à ce que les tailles de deux ellipses adjacentes ne soient jamais supérieures à la taille de leur côté.

Dans cet exemple :

  1. initialement, le rayon de l’ellipse est à 100 % ;
  2. il est ensuite additionné à une seconde ellipse qui souhaite elle aussi faire 100 % ;
  3. on a donc une somme théorique à 200 % ;
  4. le facteur de réduction qui sera alors appliqué sera de 2 ;
  5. et les ellipses n’auront donc effectivement que des rayons à 50 %.

C’est pour cette raison que faire varier un border-radius: 50% à border-radius: 100% n’a aucun impact visuel.


Dans cet autre exemple :

  1. on ajoute 50 % et 100 % ;
  2. le facteur de réduction passe donc cette fois à 1,5 ;
  3. on constate bien qu’il s’applique également bien à l’angle inférieur droit ;
  4. cette ellipse passe précisément d’un rayon de 200 pixels à 133.333 pixels (200 ÷ 1,5).

Le style de la bordure

Un rapide rappel pour finir sur les possibilités graphiques pouvant être appliquées aux bordures. Pas moins de dix styles sont disponibles (en comptant hidden, une variante de none).

Historiquement, il n’était pas possible de réaliser des coins arrondis (en pur CSS), beaucoup de ses styles ont donc plus de sens sur des boîtes carrées. Avec des angles arrondis, certains résultats deviennent même douteux et ne serviront sans doute que très rarement.

À cette date, Firefox peine encore à implémenter des versions brisées des contours. Mais la résolution du bug est proche !

Les autres navigateurs (depuis IE 9) s’en sortent très bien, et aucun ne nécessite l’usage d’un quelconque préfixe.

Et notre pilule ?

Les possibilités offertes sont nombreuses et permettent de réaliser des formes très variées.

Mais avons-nous maintenant de quoi réaliser notre exemple initial, le fameux effet « pilule » ?

Définir les ellipses à l’aide de pourcentages ne fonctionne pas… Essayons donc avec une unité proportionnelle à la taille du texte.

OK. Mais que ce passe-t-il si le texte est amené à passer sur plusieurs lignes ? Adieu notre belle forme oblongue…

Nous avons cependant vu également que les ellipses avaient une valeur limite. Aussi, en précisant un rayon exagérément grand, on sait par avance qu’il ne sera jamais supérieur à 50 % s’il est appliqué sur les quatre angles.

Voilà qui fait notre affaire : quel que soit le nombre de lignes, nous pouvons conserver notre forme.


En espérant que ce billet vous aura permis de… faire passer la pilule sur ces aspects un peu techniques des angles arrondis.

Gloup.

Vincent.

0 commentaire.

Laisser un commentaire