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.
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é.
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
.
/* 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%);
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.
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:
@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
.
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 leborder-radius
; il restera toujours rectangulaire. - Lorsque vous définissez
border-image-slice
pour remplir l'ensemble, leborder-image
n'est pas peint sous l'ensemblebackground
, 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.