Règle CSS @starting-style
Baseline 2024>
Nouvellement disponible
Depuis août 2024, cette fonctionnalité fonctionne sur les appareils et les versions de navigateur les plus récents. Elle peut ne pas fonctionner sur les appareils ou navigateurs plus anciens.
La règle @ CSS @starting-style est utilisée pour définir les valeurs de départ des propriétés appliquées à un élément, à partir desquelles vous souhaitez effectuer une transition lors de la première mise à jour de style de l'élément, c'est-à-dire lorsqu'un élément est affiché pour la première fois sur une page déjà chargée.
Syntaxe
La règle @starting-style peut être utilisée de deux façons :
-
Comme bloc autonome, auquel cas elle contient un ou plusieurs ensembles de règles définissant les déclarations de style de départ et sélectionnant les éléments auxquels elles s'appliquent :
css@starting-style { /* règles */ } -
Imbriquée dans un ensemble de règles existant, auquel cas elle contient une ou plusieurs déclarations définissant les valeurs de départ des propriétés pour les éléments déjà sélectionnés par cet ensemble de règles :
cssselector { /* règles existantes */ /* ... */ @starting-style { /* déclarations */ } }
Description
Pour éviter un comportement inattendu, les transitions CSS ne sont pas déclenchées par défaut lors de la première mise à jour de style d'un élément, ou lorsque son type display passe de none à une autre valeur. Pour activer les transitions sur le premier style, il faut utiliser des règles starting-style. Elles fournissent des styles de départ pour les éléments qui n'ont pas d'état précédent, en définissant les valeurs de propriété à partir desquelles effectuer la transition.
@starting-style est particulièrement utile pour créer des transitions d'entrée et de sortie pour les éléments affichés dans la couche supérieure (comme les fenêtres contextuelles et les boîtes de dialogue bloquantes <dialog>), les éléments qui changent vers ou depuis display: none, et les éléments ajoutés ou retirés du DOM pour la première fois.
Note :
@starting-style ne concerne que les transitions CSS. Lorsque vous utilisez des animations CSS pour réaliser de tels effets, @starting-style n'est pas nécessaire. Voir Utiliser les animations CSS pour un exemple.
Il existe deux façons d'utiliser @starting-style : comme règle autonome ou imbriquée dans un ensemble de règles.
Prenons le cas où vous souhaitez animer une fenêtre contextuelle lorsqu'elle est affichée (c'est-à-dire lorsqu'elle est ajoutée à la top layer). La « règle originale » qui définit les styles de la fenêtre contextuelle ouverte peut ressembler à ceci (voir l'exemple de fenêtre contextuelle ci-dessous) :
[popover]:popover-open {
opacity: 1;
transform: scaleX(1);
}
Pour définir les valeurs de départ des propriétés de la fenêtre contextuelle à animer avec la première méthode, vous incluez un bloc autonome @starting-style dans votre CSS :
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: scaleX(0);
}
}
Note :
La règle @starting-style et la « règle originale » ont la même spécificité. Pour garantir l'application des styles de départ, placez la règle @starting-style après la « règle originale ». Si vous la placez avant, les styles originaux écrasent les styles de départ.
Pour définir le style de départ de la fenêtre contextuelle avec la méthode imbriquée, vous pouvez imbriquer le bloc @starting-style dans la « règle originale » :
[popover]:popover-open {
opacity: 1;
transform: scaleX(1);
@starting-style {
opacity: 0;
transform: scaleX(0);
}
}
Quand les styles de départ sont-ils utilisés ?
Il est important de comprendre qu'un élément va effectuer une transition à partir de ses styles @starting-style lorsqu'il est rendu pour la première fois dans le DOM, ou lorsqu'il passe de display: none à une valeur visible. Lorsqu'il repasse de son état visible initial, il n'utilise plus les styles @starting-style, car il est désormais visible dans le DOM. Il effectue alors une transition vers les styles définis pour l'état par défaut de l'élément.
En pratique, il y a trois états de style à gérer dans ces situations : l'état de départ (@starting-style), l'état transitionné, et l'état par défaut. Il est possible que les transitions « vers » et « depuis » soient différentes dans ces cas. Vous pouvez voir une démonstration dans notre Exemple de quand les styles de départ sont utilisés ci-dessous.
Syntaxe formelle
@starting-style =
@starting-style { <rule-list> }
Exemples
>Utilisation basique de @starting-style
Faites passer la background-color d'un élément de transparent à vert lors de son rendu initial :
#target {
transition: background-color 1.5s;
background-color: green;
}
@starting-style {
#target {
background-color: transparent;
}
}
Faites passer la opacity d'un élément lorsqu'il change sa valeur display vers ou depuis none :
#target {
transition-property: opacity, display;
transition-duration: 0.5s;
display: block;
opacity: 1;
@starting-style {
opacity: 0;
}
}
#target.hidden {
display: none;
opacity: 0;
}
Démonstration de l'utilisation des styles de départ
Dans cet exemple, un bouton est pressé pour créer un élément <div>, lui donner la classe showing, et l'ajouter au DOM.
La classe showing reçoit un style de départ @starting-style de background-color: red et un style de transition vers background-color: blue. Le bloc de règles par défaut du div contient background-color: yellow, et c'est aussi là que la propriété transition est définie.
Lorsque le <div> est ajouté au DOM pour la première fois, le fond passe de rouge à bleu. Après un délai, la classe showing est retirée du <div> avec JavaScript. À ce moment-là, la transition se fait de bleu vers jaune, et non vers rouge. Cela prouve que les styles de départ ne sont utilisés que lors du premier rendu de l'élément dans le DOM. Une fois affiché, l'élément revient au style par défaut qui lui est appliqué.
Après un autre délai, le <div> est retiré du DOM, réinitialisant l'état initial de l'exemple pour pouvoir le relancer.
HTML
<button>Afficher <code><div></code></button>
CSS
div {
background-color: yellow;
transition: background-color 3s;
}
div.afficher {
background-color: skyblue;
}
@starting-style {
div.afficher {
background-color: red;
}
}
JavaScript
const btn = document.querySelector("button");
btn.addEventListener("click", () => {
btn.disabled = true;
const divElem = document.createElement("div");
divElem.classList.add("afficher");
document.body.append(divElem);
setTimeout(() => {
divElem.classList.remove("afficher");
setTimeout(() => {
divElem.remove();
btn.disabled = false;
}, 3000);
}, 3000);
});
Résultat
Le code s'affiche ainsi :
Animation d'une fenêtre contextuelle
Dans cet exemple, une fenêtre contextuelle est animée à l'aide des transitions CSS. Des animations d'entrée et de sortie basiques sont fournies avec la propriété transition.
HTML
Le HTML contient un élément <div> déclaré comme fenêtre contextuelle grâce à l'attribut popover et un élément <button> servant de contrôle d'affichage de la fenêtre contextuelle avec son attribut popovertarget.
<button popovertarget="mypopover">Afficher la fenêtre contextuelle</button>
<div popover="auto" id="mypopover">
Je suis une fenêtre contextuelle ! Je dois être animée.
</div>
CSS
Dans cet exemple, on souhaite animer deux propriétés, opacity et transform (notamment une transformation d'échelle horizontale), pour faire apparaître/disparaître la fenêtre contextuelle et la faire grandir/rétrécir horizontalement.
html {
font-family: Arial, Helvetica, sans-serif;
}
[popover]:popover-open {
opacity: 1;
transform: scaleX(1);
}
[popover] {
font-size: 1.2rem;
padding: 10px;
/* État final de l'animation de sortie */
opacity: 0;
transform: scaleX(0);
transition:
opacity 0.7s,
transform 0.7s,
overlay 0.7s allow-discrete,
display 0.7s allow-discrete;
/* Équivalent à
transition: all 0.7s allow-discrete; */
}
/* À inclure après la règle [popover]:popover-open */
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: scaleX(0);
}
}
/* Transition pour le backdrop du popover */
[popover]::backdrop {
background-color: transparent;
transition:
display 0.7s allow-discrete,
overlay 0.7s allow-discrete,
background-color 0.7s;
/* Équivalent à
transition: all 0.7s allow-discrete; */
}
[popover]:popover-open::backdrop {
background-color: rgb(0 0 0 / 25%);
}
/* L'imbrication (&) n'est pas supportée pour les pseudo-éléments,
il faut donc définir un bloc autonome starting-style. */
@starting-style {
[popover]:popover-open::backdrop {
background-color: transparent;
}
}
Pour cela, on définit un état de départ pour ces propriétés sur l'état caché par défaut de l'élément de fenêtre contextuelle (sélectionné par [popover]), et un état final sur l'état ouvert de la fenêtre contextuelle (sélectionné par la pseudo-classe :popover-open).
On définit ensuite la propriété transition pour animer entre les deux états. Un état de départ pour l'animation est inclus dans une règle @starting-style pour activer l'animation d'entrée.
Comme l'élément animé est promu dans la couche supérieure, lorsqu'il est affiché et retiré de la couche supérieure et lorsqu'il est caché (avec display: none), quelques étapes supplémentaires sont nécessaires pour garantir que l'animation fonctionne dans les deux sens :
displayest ajouté à la liste des propriétés animées pour garantir que l'élément animé reste visible (défini surdisplay: blockou une autre valeur visible) pendant toute l'animation d'entrée et de sortie. Sans cela, l'animation de sortie n'est pas visible : la fenêtre contextuelle disparaît simplement. Notez que la valeurtransition-behavior: allow-discreteest aussi définie dans le raccourci pour activer l'animation.overlayest ajouté à la liste des propriétés animées pour garantir que le retrait de l'élément de la couche supérieure soit différé jusqu'à la fin de l'animation. Cela n'a pas un grand impact pour ce type d'animation, mais dans des cas plus complexes, ne pas le faire peut entraîner le retrait trop rapide de l'élément, rendant l'animation peu fluide ou inefficace. Là encore,transition-behavior: allow-discreteest requis pour que l'animation ait lieu.
Note :
Une transition est aussi appliquée au ::backdrop qui apparaît derrière la fenêtre contextuelle à l'ouverture, pour une animation d'assombrissement agréable. [popover]:popover-open::backdrop est utilisé pour cibler le backdrop lorsque la fenêtre contextuelle est ouverte.
Résultat
Le code s'affiche ainsi :
Note :
Comme les fenêtres contextuelles passent de display: none à display: block à chaque affichage, la fenêtre contextuelle effectue une transition de ses styles @starting-style vers ses styles [popover]:popover-open à chaque animation d'entrée. Lorsqu'il se ferme, il passe de l'état [popover]:popover-open à l'état [popover] par défaut.
Note :
Vous pouvez trouver un exemple montrant la transition d'un élément <dialog> et de son backdrop lors de l'affichage et de la fermeture sur la page de référence <dialog> — voir Transition des éléments dialog.
Transition d'éléments lors de l'ajout et du retrait dans le DOM
Cet exemple contient un bouton qui, lorsqu'il est pressé, ajoute de nouveaux éléments à un conteneur <section>. Chaque élément contient à son tour un bouton imbriqué qui, lorsqu'il est pressé, retire l'élément. Cet exemple montre comment utiliser les transitions pour animer les éléments lors de leur ajout ou retrait du DOM.
HTML
<button>Créer une nouvelle colonne</button>
<section></section>
JavaScript
Le JavaScript permet l'ajout et le retrait des éléments :
const btn = document.querySelector("button");
const sectionElem = document.querySelector("section");
btn.addEventListener("click", createColumn);
function randomBackground() {
function randomNum() {
return Math.floor(Math.random() * 255);
}
const baseColor = `${randomNum()} ${randomNum()} ${randomNum()}`;
return `linear-gradient(to right, rgb(${baseColor} / 0), rgb(${baseColor} / 0.5))`;
}
function createColumn() {
const divElem = document.createElement("div");
divElem.style.background = randomBackground();
const closeBtn = document.createElement("button");
closeBtn.textContent = "✖";
closeBtn.setAttribute("aria-label", "fermer");
divElem.append(closeBtn);
sectionElem.append(divElem);
closeBtn.addEventListener("click", () => {
divElem.classList.add("fade-out");
setTimeout(() => {
divElem.remove();
}, 1000);
});
}
Lorsque le bouton « Créer une nouvelle colonne » est cliqué, la fonction createColumn() est appelée. Elle crée un élément <div> avec une couleur de fond générée aléatoirement et un bouton <button> pour fermer le <div>. Le bouton est ajouté au <div>, puis le <div> au conteneur <section>.
On ajoute ensuite un écouteur d'évènement au bouton de fermeture avec addEventListener(). Cliquer sur le bouton fait deux choses :
- Ajoute la classe
fade-outau<div>. L'ajout de la classe déclenche l'animation de sortie définie sur cette classe. - Retire le
<div>après un délai de 1000 ms. La fonctionsetTimeout()retarde le retrait du<div>du DOM (avecElement.remove()) jusqu'à la fin de l'animation.
CSS
On inclut une propriété transition qui anime la opacity et la scale de chaque colonne lors de leur ajout et retrait :
div {
flex: 1;
border: 1px solid gray;
position: relative;
opacity: 1;
scale: 1 1;
transition:
opacity 0.7s,
scale 0.7s,
display 0.7s allow-discrete,
all 0.7s allow-discrete;
/* Équivalent à
transition: all 0.7s allow-discrete; */
}
/* À inclure après la règle `div` */
@starting-style {
div {
opacity: 0;
scale: 1 0;
}
}
.fade-out {
opacity: 0;
display: none;
scale: 1 0;
}
div > button {
font-size: 1.6rem;
background: none;
border: 0;
text-shadow: 2px 1px 1px white;
border-radius: 15px;
position: absolute;
top: 1px;
right: 1px;
cursor: pointer;
}
Pour animer la opacity et la scale de chaque <div> lors de son ajout au DOM puis inverser l'animation lors de son retrait, on :
- Définit l'état final des propriétés à animer dans la règle
div { ... }. - Définit l'état de départ à partir duquel effectuer la transition dans un bloc
@starting-style. - Définit l'animation de sortie dans la règle
.fade-out— c'est la classe que le JavaScript assigne aux éléments<div>lorsque leur bouton de fermeture est pressé. En plus de définir les états finaux deopacityetscale, on définit aussidisplay: nonesur les<div>— on souhaite qu'ils deviennent immédiatement indisponibles une fois retirés de l'interface. - Définit la liste
transitiondans la règlediv { ... }pour animeropacity,scaleetdisplay. Notez que pourdisplay, la valeurtransition-behavior: allow-discreteest aussi définie dans le raccourci pour que l'animation ait lieu.
Résultat
Le résultat final ressemble à ceci :
Spécifications
| Spécification |
|---|
| CSS Transitions Module Level 2> # defining-before-change-style> |
Compatibilité des navigateurs
Voir aussi
- Le module des transitions CSS
- La propriété
overlay - La propriété
transition-behavior - L'interface API
CSSStartingStyleRule - Quatre nouvelles fonctionnalités CSS pour des animations d'entrée et de sortie fluides (angl.) sur developer.chrome.com (2023)