Animations de bordure CSS

Examiner plusieurs façons d'animer une bordure en CSS

Définir des bordures

Il existe plusieurs méthodes pour définir une bordure sur un élément: border, outline et box-shadow. Comme expliqué dans l'article The 3 CSS Methods for Using Element Borders de Stephanie Eckles, chaque approche présente des avantages et des inconvénients, en particulier en ce qui concerne l'animation des bordures. La principale raison de ne pas utiliser un border CSS approprié est pour les animations.

Animations de bordure à l'aide de outline-offset de Kevin J. Powell

Un article qui a récemment attiré mon attention est Fantastic CSS border animation, dans lequel l'auteur Coco a exploré d'autres options. En injectant du contenu généré à l'aide de ::before et ::after, ils créent une fausse bordure qui est ensuite animée.

Ce qui me ressort le plus, ce sont les visualisations animées utilisées dans l'article. Ils aident vraiment à expliquer exactement ce qui est fait pour obtenir l'effet souhaité.

Animations de bordure à l'aide de contenu généré par Coco

Le calque blanc et les lignes de couleur constituent du contenu généré. En faisant glisser la couche blanche en fondu, on voit clairement comment elles s'empilent et comment fonctionne l'animation.

Conserver le modèle de boîte

L'utilisation de contenu généré pour imiter une bordure présente un inconvénient : vous vous retrouvez avec un modèle de zone défectueux : le contenu peut désormais masquer la fausse bordure, car cette bordure est peinte en dessous. Pour limiter les problèmes, vous devez appliquer le border-width souhaité en tant que padding.

Pour avoir une véritable bordure (et ainsi conserver le fonctionnement du modèle de zone), vous pouvez utiliser plusieurs arrière-plans que vous étirez ensuite dans la zone de bordure.

Principes de base

Commençons par créer une bordure en pointillés et ajouter les différents arrière-plans.

/* Size of the border */
--border-size: 0.5rem;

/* Create a dotted border */
border: var(--border-size) dotted lime;

/* Create two background layers:
   1. A white semi-transparent
   2. A layer with the colored boxes
 */
background-image:
  linear-gradient(to right, rgb(255 255 255 / 0.5), rgb(255 255 255 / 0.5)),

  conic-gradient(
    from 45deg,
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  )
;

Dimensionner les arrière-plans avec background-origin

Comme vous pouvez le voir, il se passe quelque chose d'amusant sur les arrière-plans: ils sont peints dans la bordure, mais le conic-gradient semble ne pas être correct. Il s'agit d'un comportement intentionnel: par défaut, les images de fond ne dessinent pas dans la bordure, car leur origine est le padding-box de l'élément. Pour créer une bordure, les images de fond définies sont répétées dans la bordure elle-même, ce qui génère l'effet visuel étrange.

Pour résoudre ce problème, vous devez étirer l'arrière-plan afin qu'il occupe également la taille de la bordure. Vous pouvez le faire manuellement en étirant et en repositionnant l'arrière-plan, mais la meilleure solution consiste à utiliser la propriété background-origin pour dimensionner l'arrière-plan par rapport au border-box.

Navigateurs pris en charge

  • 1
  • 12
  • 4
  • 3

Source

À éviter
/* Manually add or offset the size of the border where needed */
background-position: calc(var(--border-size) * -1) calc(var(--border-size) * -1);
background-size: calc(var(--border-size) * 2 + 100%) calc(var(--border-size) * 2 + 100%);
À faire
background-origin: border-box;

Cet ajout améliore considérablement l'aspect général:

Réduction du calque d'arrière-plan blanc avec background-clip

Les arrière-plans occupent désormais tout l'espace, et le calque semi-transparent doit à nouveau être réduit. Au lieu de modifier à nouveau background-size, il existe une méthode plus simple: utilisez background-clip et définissez-le sur padding-box. Ainsi, l'arrière-plan ne sera plus dessiné sous la zone de la bordure.

Navigateurs pris en charge

  • 1
  • 12
  • 4
  • 5

Source

background-clip:
  padding-box, /* Clip white semi-transparent to the padding-box */
  border-box /* Clip colored boxes to the border-box (default) */
;

Enfin, définissez la bordure sur transparent pour qu'elle s'applique totalement.

border: 0.3rem dotted transparent;

Animation

Pour restaurer l'animation de la bordure, vous pouvez manipuler l'angle de début de conic-gradient.

--angle: 0deg;
conic-gradient(
  from var(--angle),
  #d53e33 0deg 90deg,
  #fbb300 90deg 180deg,
  #377af5 180deg 270deg,
  #399953 270deg 360deg
);

Grâce à @property, cela devient un jeu d'enfant dans les navigateurs compatibles:

Navigateurs pris en charge

  • 85
  • 85
  • 16.4

Source

@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes rotate {
  to {
    --angle: 360deg;
  }
}

L'ensemble du code devient le suivant:

Contenu bonus: border-image

Pour dessiner une bordure en dégradé, une approche précédemment abordée consiste à utiliser CSS border-image.

Navigateurs pris en charge

  • 16
  • 12
  • 15
  • 6

Source

Elle simplifie le code, car vous n'avez pas besoin de gérer le chevauchement des arrière-plans. L'animation peut être appliquée de la même manière qu'auparavant.

/* Create a border */
border: 0.5rem solid transparent;

/* Paint an image in the border */
border-image:
  conic-gradient(
    from var(--angle),
    #d53e33 0deg 90deg,
    #fbb300 90deg 180deg,
    #377af5 180deg 270deg,
    #399953 270deg 360deg
  ) 1
;

Toutefois, vous remarquerez que certaines choses ne fonctionnent plus avec cette approche:

  • Le border-image ne suit pas le border-radius ; il restera toujours rectangulaire.
  • Lorsque vous définissez border-image-slice pour remplir l'ensemble, le border-image n'est pas peint sous l'ensemble background, mais en haut. Cela peut être problématique si vous souhaitez que l'arrière-plan soit semi-transparent.

En bouclage

Il existe de nombreuses possibilités pour animer des bordures en CSS. Selon le cas d'utilisation, vous pouvez choisir l'une ou l'autre de ces solutions.