Un aperçu pratique de CSS Houdini
Publié: 2022-03-10Il faut beaucoup de temps pour qu'une nouvelle fonctionnalité ou amélioration CSS passe d'un brouillon initial à une fonctionnalité CSS entièrement prise en charge et stable que les développeurs peuvent utiliser. Les polyfills basés sur JavaScript peuvent être utilisés pour remplacer le manque de prise en charge des navigateurs afin d'utiliser de nouvelles fonctionnalités CSS avant qu'elles ne soient officiellement implémentées. Mais ils sont défectueux dans la plupart des cas. Par exemple, scrollsnap-polyfill est l'un des nombreux polyfills qui peuvent être utilisés pour corriger les incohérences de prise en charge du navigateur pour la spécification CSS Scroll Snap. Mais même cette solution a des limites, des bogues et des incohérences.
L'inconvénient potentiel de l'utilisation de polyfills est qu'ils peuvent avoir un impact négatif sur les performances et qu'ils sont difficiles à mettre en œuvre correctement. Cet inconvénient est lié au DOM et au CSSOM du navigateur. Le navigateur crée un DOM (Document Object Model) à partir du balisage HTML et, de la même manière, il a créé CSSOM (CSS Object Model) à partir du balisage CSS. Ces deux arbres d'objets sont indépendants l'un de l'autre. JavaScript fonctionne sur DOM et a un accès très limité à CSSOM.
Les solutions JavaScript Polyfill ne s'exécutent qu'après la fin du cycle de rendu initial, c'est-à-dire lorsque le DOM et le CSSOM ont été créés et que le document a fini de se charger. Une fois que Polyfill a modifié les styles dans le DOM (en les incorporant), le processus de rendu s'exécute à nouveau et la page entière est restituée. L'impact négatif sur les performances devient encore plus apparent s'ils s'appuient sur la méthode requestAnimationFrame
ou dépendent des interactions de l'utilisateur comme les événements de défilement.
Un autre obstacle au développement web est les diverses contraintes imposées par les standards CSS . Par exemple, il n'y a qu'un nombre limité de propriétés CSS qui peuvent être animées nativement. CSS sait animer nativement les couleurs, mais ne sait pas animer les dégradés. Il a toujours été nécessaire d'innover et de créer des expériences Web impressionnantes en repoussant les limites malgré les limitations technologiques. C'est pourquoi les développeurs ont souvent tendance à utiliser des solutions de contournement moins qu'idéales ou JavaScript pour implémenter un style et des effets plus avancés qui ne sont actuellement pas pris en charge par CSS, tels que la disposition en maçonnerie, les effets 3D avancés, l'animation avancée, la typographie fluide, les dégradés animés, éléments de select
stylés, etc.
Il semble impossible pour les spécifications CSS de suivre les diverses demandes de fonctionnalités de l'industrie, telles qu'un meilleur contrôle des animations, une troncature de texte améliorée, une meilleure option de style pour les éléments d' input
et de select
, plus d'options display
, plus d'options de filter
, etc.
Quelle pourrait être la solution potentielle ? Offrez aux développeurs un moyen natif d'étendre CSS à l'aide de diverses API . Dans cet article, nous allons voir comment les développeurs frontaux peuvent le faire en utilisant les API Houdini, JavaScript et CSS. Dans chaque section, nous allons examiner chaque API individuellement, vérifier la prise en charge de son navigateur et l'état actuel des spécifications, et voir comment elles peuvent être implémentées aujourd'hui à l'aide de l'amélioration progressive.
Qu'est-ce que Houdini ?
Houdini, un terme générique désignant la collection d'API de navigateur, vise à apporter des améliorations significatives au processus de développement Web et au développement des normes CSS en général. Les développeurs pourront étendre le CSS avec de nouvelles fonctionnalités à l'aide de JavaScript, se connecter au moteur de rendu CSS et indiquer au navigateur comment appliquer le CSS lors d'un processus de rendu. Cela se traduira par des performances et une stabilité nettement meilleures que l'utilisation de polyfills ordinaires.
La spécification Houdini se compose de deux groupes d'API : les API de haut niveau et les API de bas niveau .
Les API de haut niveau sont étroitement liées au processus de rendu du navigateur (style → mise en page → peinture → composite). Ceci comprend:
- API de peinture
Un point d'extension pour l'étape de rendu de peinture du navigateur où les propriétés visuelles (couleur, arrière-plan, bordure, etc.) sont déterminées. - API de mise en page
Un point d'extension pour l'étape de rendu de la disposition du navigateur où les dimensions, la position et l'alignement des éléments sont déterminés. - API d'animation
Un point d'extension pour l'étape de rendu composite du navigateur où les calques sont dessinés à l'écran et animés.
Les API de bas niveau constituent la base des API de haut niveau. Ceci comprend:
- API de modèle d'objet typé
- API Propriétés et valeurs personnalisées
- API de métrique de police
- Worklets
Certaines API Houdini sont déjà disponibles pour une utilisation dans certains navigateurs avec d'autres API à suivre lorsqu'elles sont prêtes à être publiées.
L'avenir du CSS
Contrairement aux spécifications de fonctionnalités CSS habituelles qui ont été introduites jusqu'à présent, Houdini se démarque en permettant aux développeurs d'étendre le CSS de manière plus native. Cela signifie-t-il que les spécifications CSS cesseront d'évoluer et qu'aucune nouvelle implémentation officielle des fonctionnalités CSS ne sera publiée ? Eh bien, ce n'est pas le cas. L'objectif de Houdini est d'aider le processus de développement de fonctionnalités CSS en permettant aux développeurs de créer des prototypes fonctionnels qui peuvent être facilement standardisés.
De plus, les développeurs pourront partager les Worklets CSS open source plus facilement et avec moins de corrections de bogues spécifiques au navigateur.
API de modèle d'objet typé
Avant l'introduction de Houdini, le seul moyen pour JavaScript d'interagir avec CSS était d'analyser les CSS représentés sous forme de valeurs de chaîne et de les modifier. L'analyse et le remplacement manuels des styles peuvent être difficiles et sujets aux erreurs car le type de valeur doit être modifié dans les deux sens et l'unité de valeur doit être ajoutée manuellement lors de l'attribution d'une nouvelle valeur.
selectedElement.style.fontSize = newFontSize + "px"; // newFontSize = 20 console.log(selectedElement.style.fontSize); // "20px"
L'API Typed Object Model (Typed OM) ajoute plus de sens sémantique aux valeurs CSS en les exposant en tant qu'objets JavaScript typés. Il améliore considérablement le code associé et le rend plus performant, stable et maintenable. Les valeurs CSS sont représentées par l'interface CSSUnitValue
qui se compose d'une valeur et d'une propriété d'unité.
{ value: 20, unit: "px" }
Cette nouvelle interface peut être utilisée avec les nouvelles propriétés suivantes :
-
computedStyleMap()
: pour analyser les styles calculés (non en ligne). Il s'agit d'une méthode d'élément sélectionné qui doit être invoquée avant l'analyse ou l'utilisation d'autres méthodes. -
attributeStyleMap
: pour analyser et modifier les styles en ligne. Il s'agit d'une propriété disponible sur un élément sélectionné.
// Get computed styles from stylesheet (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Set inline styles selectedElement.attributeStyleMap.set("font-size", CSS.em(2)); // Sets inline style selectedElement.attributeStyleMap.set("color", "blue"); // Sets inline style // Computed style remains the same (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Get new inline style selectedElement.attributeStyleMap.get("font-size"); // { value: 2, unit: "em"}
Remarquez comment des types CSS spécifiques sont utilisés lors de la définition d'une nouvelle valeur numérique. En utilisant cette syntaxe, de nombreux problèmes potentiels liés au type peuvent être évités et le code résultant est plus fiable et sans bogue.
Les méthodes get
et set
ne sont qu'un petit sous-ensemble de toutes les méthodes disponibles définies par l'API Typed OM. Certains d'entre eux incluent:
-
clear
: supprime tous les styles en ligne -
delete
: supprime une propriété CSS spécifiée et sa valeur des styles en ligne -
has
: renvoie un booléen si une propriété CSS spécifiée est définie -
append
: ajoute une valeur supplémentaire à une propriété qui prend en charge plusieurs valeurs - etc.
Détection de fonctionnalités
var selectedElement = document.getElementById("example"); if(selectedElement.attributeStyleMap) { /* ... */ } if(selectedElement.computedStyleMap) { /* ... */ }
État de la spécification W3C
- Ébauche de travail : publiée pour examen par la communauté
Prise en charge du navigateur
Google Chrome | Bord Microsoft | Navigateur Opera | Firefox | Safari |
---|---|---|---|---|
Prise en charge | Prise en charge | Prise en charge | Non supporté | Prise en charge partielle (*) |
* pris en charge avec les "fonctionnalités expérimentales de la plate-forme Web" ou un autre indicateur de fonctionnalité activé.
Source de données : Houdini est-il encore prêt ?
API de propriétés et de valeurs personnalisées
L'API CSS Properties And Values permet aux développeurs d'étendre les variables CSS en ajoutant un type, une valeur initiale et en définissant l'héritage. Les développeurs peuvent définir des propriétés personnalisées CSS en les enregistrant à l'aide de la méthode registerProperty
qui indique aux navigateurs comment effectuer la transition et gérer le repli en cas d'erreur.
CSS.registerProperty({ name: "--colorPrimary", syntax: "<color>", inherits: false, initialValue: "blue", });
Cette méthode accepte un argument d'entrée qui est un objet avec les propriétés suivantes :
-
name
: le nom de la propriété personnalisée -
syntax
: indique au navigateur comment analyser une propriété personnalisée. Ce sont des valeurs prédéfinies comme<color>
,<integer>
,<number>
,<length>
,<percentage>
, etc. -
inherits
: indique au navigateur si la propriété personnalisée hérite de la valeur de son parent. -
initialValue
: indique la valeur initiale qui est utilisée jusqu'à ce qu'elle soit remplacée et celle-ci est utilisée comme solution de secours en cas d'erreur.
Dans l'exemple suivant, la propriété personnalisée de type <color>
est définie. Cette propriété personnalisée sera utilisée dans la transition de dégradé. Vous pensez peut-être que le CSS actuel ne prend pas en charge les transitions pour les dégradés d'arrière-plan et vous auriez raison. Remarquez comment la propriété personnalisée elle-même est utilisée dans transition
, au lieu d'une propriété background
qui serait utilisée pour les transitions background-color
régulières.
.gradientBox { background: linear-gradient(45deg, rgba(255,255,255,1) 0%, var(--colorPrimary) 60%); transition: --colorPrimary 0.5s ease; /* ... */ } .gradientBox:hover { --colorPrimary: red /* ... */ }
Le navigateur ne sait pas comment gérer la transition de dégradé, mais il sait comment gérer les transitions de couleur car la propriété personnalisée est spécifiée en tant que type <color>
. Sur un navigateur prenant en charge Houdini, une transition dégradée se produit lorsque l'élément est survolé. Le pourcentage de position de dégradé peut également être remplacé par une propriété personnalisée CSS (enregistrée en tant que type <percentage>
) et ajoutée à une transition de la même manière que dans l'exemple.
Si registerProperty
est supprimé et qu'une propriété personnalisée CSS standard est enregistrée dans un sélecteur :root
, la transition en dégradé ne fonctionnera pas. Il est nécessaire que registerProperty
soit utilisé pour que le navigateur sache qu'il doit le traiter comme une couleur.
Dans la future implémentation de cette API, il serait possible d'enregistrer une propriété personnalisée directement dans CSS.
@property --colorPrimary { syntax: "<color>"; inherits: false; initial-value: blue; }
Exemple
Cet exemple simple présente une couleur de dégradé et une transition de position lors d'un événement de survol à l'aide de propriétés personnalisées CSS enregistrées pour la couleur et la position respectivement. Le code source complet est disponible sur l'exemple de référentiel.
Détection de fonctionnalités
if (CSS.registerProperty) { /* ... */ }
État de la spécification W3C
- Ébauche de travail : publiée pour examen par la communauté
Prise en charge du navigateur
Google Chrome | Bord Microsoft | Navigateur Opera | Firefox | Safari |
---|---|---|---|---|
Prise en charge | Prise en charge | Prise en charge | Non supporté | Non supporté |
Source de données : Houdini est-il encore prêt ?
API de métrique de police
L'API Font Metrics est encore à un stade très précoce de développement, de sorte que ses spécifications peuvent changer à l'avenir. Dans son projet actuel, l' API Font Metrics fournira des méthodes pour mesurer les dimensions des éléments de texte qui sont rendus à l'écran afin de permettre aux développeurs d'affecter la façon dont les éléments de texte sont rendus à l'écran. Ces valeurs sont difficiles ou impossibles à mesurer avec les fonctionnalités actuelles. Cette API permettra donc aux développeurs de créer plus facilement des fonctionnalités CSS liées au texte et aux polices. La troncature de texte dynamique multiligne est un exemple de l'une de ces fonctionnalités.
État de la spécification W3C
- Recueil d'idées : aucun projet de cahier des charges soumis pour le moment
Prise en charge du navigateur
Google Chrome | Bord Microsoft | Navigateur Opera | Firefox | Safari |
---|---|---|---|---|
Non supporté | Non supporté | Non supporté | Non supporté | Non supporté |
Source de données : Houdini est-il encore prêt ?
Worklets
Avant de passer aux autres API, il est important d'expliquer le concept des Worklets. Les worklets sont des scripts qui s'exécutent pendant le rendu et sont indépendants de l'environnement JavaScript principal. Ils sont un point d'extension pour les moteurs de rendu. Ils sont conçus pour le parallélisme (avec 2 instances ou plus) et indépendants des threads, ont un accès réduit à la portée globale et sont appelés par le moteur de rendu en cas de besoin. Les worklets peuvent être exécutés uniquement sur HTTPS (sur l'environnement de production) ou sur localhost (à des fins de développement).
Houdini introduit les Worklets suivants pour étendre le moteur de rendu du navigateur :
- Paint Worklet - API de peinture
- Worklet d'animation - API d'animation
- Worklet de mise en page - API de mise en page
API de peinture
L'API Paint permet aux développeurs d'utiliser des fonctions JavaScript pour dessiner directement dans l'arrière-plan, la bordure ou le contenu d'un élément à l'aide du contexte de rendu 2D, qui est un sous-ensemble de l'API HTML5 Canvas. L'API Paint utilise Paint Worklet pour dessiner une image qui répond dynamiquement aux changements dans CSS (changements dans les variables CSS, par exemple). Quiconque connaît l'API Canvas se sentira comme chez lui avec l'API Paint de Houdini.
Plusieurs étapes sont nécessaires pour définir un Paint Worklet :
- Écrire et enregistrer un Paint Worklet à l'aide de la fonction
registerPaint
- Appelez le Worklet dans le fichier HTML ou le fichier JavaScript principal à l'aide de la fonction
CSS.paintWorklet.addModule
- Utilisez la fonction
paint()
dans CSS avec un nom de Worklet et des arguments d'entrée facultatifs.
Jetons un coup d'œil à la fonction registerPaint
qui est utilisée pour enregistrer un Paint Worklet et définir sa fonctionnalité.
registerPaint("paintWorketExample", class { static get inputProperties() { return ["--myVariable"]; } static get inputArguments() { return ["<color>"]; } static get contextOptions() { return {alpha: true}; } paint(ctx, size, properties, args) { /* ... */ } });
La fonction registerPaint
se compose de plusieurs parties :
-
inputProperties
:
Un tableau de propriétés personnalisées CSS dont le Worklet gardera une trace. Ce tableau représente les dépendances d'un worklet de peinture. -
inputArguments
:
Un tableau d'arguments d'entrée qui peuvent être passés à partir de la fonction depaint
depuis l'intérieur du CSS. -
contextOptions
: autoriser ou interdire l'opacité des couleurs. Si défini surfalse
, toutes les couleurs seront affichées avec une opacité totale. -
paint
: la fonction principale qui fournit les arguments suivants :-
ctx
: contexte de dessin 2D, presque identique au contexte de dessin 2D de l'API Canvas. -
size
: un objet contenant la largeur et la hauteur de l'élément. Les valeurs sont déterminées par le processus de rendu de mise en page. La taille du canevas est la même que la taille réelle de l'élément. -
properties
: variables d'entrée définies dansinputProperties
-
args
: un tableau d'arguments d'entrée passés dans la fonction depaint
en CSS
-
Une fois le Worklet enregistré, il doit être appelé dans le fichier HTML en fournissant simplement un chemin d'accès au fichier.
CSS.paintWorklet.addModule("path/to/worklet/file.js");
Tout Worklet peut également être ajouté à partir d'une URL externe (à partir d'un réseau de distribution de contenu, par exemple) ce qui les rend modulaires et réutilisables.
CSS.paintWorklet.addModule("https://url/to/worklet/file.js");
Une fois le Worklet appelé, il peut être utilisé dans CSS à l'aide de la fonction de paint
. Cette fonction accepte le nom enregistré du Worklet comme premier argument d'entrée et chaque argument d'entrée qui le suit est un argument personnalisé qui peut être passé à un Worklet (défini dans inputArguments du inputArguments
). À partir de ce moment, le navigateur détermine quand appeler le Worklet et à quelles actions de l'utilisateur et à quelles valeurs de propriétés personnalisées CSS il faut répondre.
.exampleElement { /* paintWorkletExample - name of the worklet blue - argument passed to a Worklet */ background-image: paint(paintWorketExample, blue); }
Exemple
L'exemple suivant présente l'API Paint et la réutilisation et la modularité générales des Worklets. Il utilise le Worklet Ripple directement à partir du référentiel Google Chrome Labs et s'exécute sur un élément différent avec des styles différents. Le code source complet est disponible sur l'exemple de référentiel.
Détection de fonctionnalités
if ("paintWorklet" in CSS) { /* ... */ } @supports(background:paint(paintWorketExample)){ /* ... */ }
État de la spécification W3C
- Recommandation du candidat : projet de travail stable prêt à être mis en œuvre
Prise en charge du navigateur
Google Chrome | Bord Microsoft | Navigateur Opera | Firefox | Safari |
---|---|---|---|---|
Prise en charge | Prise en charge | Prise en charge | Non supporté | Non supporté |
Source de données : Houdini est-il encore prêt ?
API d'animation
L'API d' animation étend les animations Web avec des options pour écouter divers événements (défilement, survol, clic, etc.) et améliore les performances en exécutant des animations sur leur propre fil dédié à l'aide d'un Worklet d'animation. Il permet à l'action de l'utilisateur de contrôler le flux d'animation qui s'exécute de manière performante et non bloquante.
Comme tout Worklet, Animation Worklet doit d'abord être enregistré.
registerAnimator("animationWorkletExample", class { constructor(options) { /* ... */ } animate(currentTime, effect) { /* ... */ } });
Cette classe est constituée de deux fonctions :
-
constructor
: appelé lors de la création d'une nouvelle instance. Utilisé pour la configuration générale. -
animate
: la fonction principale qui contient la logique d'animation. Fournit les arguments d'entrée suivants :-
currentTime
: la valeur de l'heure actuelle de la chronologie définie -
effect
: un tableau d'effets que cette animation utilise
-
Une fois le Worklet d'animation enregistré, il doit être inclus dans le fichier JavaScript principal , l'animation (élément, images clés, options) doit être définie et l'animation est instanciée avec la chronologie sélectionnée. Les concepts de chronologie et les bases de l'animation Web seront expliqués dans la section suivante.
/* Include Animation Worklet */ await CSS.animationWorklet.addModule("path/to/worklet/file.js");; /* Select element that's going to be animated */ const elementExample = document.getElementById("elementExample"); /* Define animation (effect) */ const effectExample = new KeyframeEffect( elementExample, /* Selected element that's going to be animated */ [ /* ... */ ], /* Animation keyframes */ { /* ... */ }, /* Animation options - duration, delay, iterations, etc. */ ); /* Create new WorkletAnimation instance and run it */ new WorkletAnimation( "animationWorkletExample" /* Worklet name */ effectExample, /* Animation (effect) timeline */ document.timeline, /* Input timeline */ {}, /* Options passed to constructor */ ).play(); /* Play animation */
Mappage de la chronologie
L'animation Web est basée sur des chronologies et le mappage de l'heure actuelle sur une chronologie de l'heure locale d'un effet . Par exemple, examinons une animation linéaire répétitive avec 3 images clés (début, milieu, dernier) qui s'exécute 1 seconde après le chargement d'une page (délai) et d'une durée de 4 secondes.
La chronologie de l'effet de l'exemple ressemblerait à ceci (avec une durée de 4 secondes sans délai) :
Chronologie de l'effet (durée 4s) | Image clé |
---|---|
0 ms | Première image clé - l'animation démarre |
2000ms | Image clé du milieu - animation en cours |
4000ms | Dernière image clé - l'animation se termine ou revient à la première image clé |
Afin de mieux comprendre effect.localTime
, en définissant sa valeur sur 3 000 ms (en tenant compte du délai de 1 000 ms), l'animation résultante sera verrouillée sur une image clé intermédiaire dans la chronologie de l'effet (délai de 1 000 ms + 2 000 ms pour une image clé intermédiaire). Le même effet va se produire en définissant la valeur sur 7000ms et 11000ms car l'animation se répète dans un intervalle de 4000ms (durée de l'animation).
animate(currentTime, effect) { effect.localTime = 3000; // 1000ms delay + 2000ms middle keyframe }
Aucune animation ne se produit lorsque la valeur effect.localTime
est constante car l'animation est verrouillée dans une image clé spécifique. Afin d'animer correctement un élément, son effect.localTime
doit être dynamique. Il est nécessaire que la valeur soit une fonction qui dépend de l'argument d'entrée currentTime
ou d'une autre variable.
Le code suivant montre une représentation fonctionnelle du mappage 1:1 (fonction linéaire) d'une chronologie pour affecter l'heure locale.
animate(currentTime, effect) { effect.localTime = currentTime; // y = x linear function }
Chronologie ( document.timeline ) | Heure locale de l'effet mappé | Image clé |
---|---|---|
startTime + 0ms (temps écoulé) | startTime + 0 ms | Première |
startTime + 1000ms (temps écoulé) | startTime + 1000ms (délai) + 0ms | Première |
startTime + 3000ms (temps écoulé) | startTime + 1000ms (délai) + 2000ms | Milieu |
startTime + 5000ms (temps écoulé) | startTime + 1000ms (délai) + 4000ms | Derniers seront les premiers |
startTime + 7000ms (temps écoulé) | startTime + 1000ms (délai) + 6000ms | Milieu |
startTime + 9000ms (temps écoulé) | startTime + 1000ms (délai) + 8000ms | Derniers seront les premiers |
La chronologie n'est pas limitée au mappage 1: 1 à l'heure locale de l'effet. L'API d'animation permet aux développeurs de manipuler le mappage de la chronologie dans la fonction d' animate
en utilisant des fonctions JavaScript standard pour créer des chronologies complexes. L'animation n'a pas non plus à se comporter de la même manière à chaque itération (si l'animation est répétée).
L'animation n'a pas à dépendre de la chronologie du document qui ne commence à compter que les millisecondes à partir du moment où il est chargé. Les actions de l'utilisateur telles que les événements de défilement peuvent être utilisées comme chronologie pour l'animation à l'aide d'un objet ScrollTimeline
. Par exemple, une animation peut démarrer lorsqu'un utilisateur a fait défiler jusqu'à 200 pixels et peut se terminer lorsqu'un utilisateur a fait défiler jusqu'à 800 pixels sur un écran.
const scrollTimelineExample = new ScrollTimeline({ scrollSource: scrollElement, /* DOM element whose scrolling action is being tracked */ orientation: "vertical", /* Scroll direction */ startScrollOffset: "200px", /* Beginning of the scroll timeline */ endScrollOffset: "800px", /* Ending of the scroll timeline */ timeRange: 1200, /* Time duration to be mapped to scroll values*/ fill: "forwards" /* Animation fill mode */ }); ...
L'animation s'adaptera automatiquement à la vitesse de défilement de l'utilisateur et restera fluide et réactive. Étant donné que les Worklets d'animation s'exécutent à partir du thread principal et sont connectés au moteur de rendu d'un navigateur, l'animation qui dépend du défilement de l'utilisateur peut s'exécuter de manière fluide et être très performante.
Exemple
L'exemple suivant montre comment mettre en œuvre une chronologie non linéaire. Il utilise la fonction gaussienne modifiée et applique une animation de traduction et de rotation avec la même chronologie. Le code source complet est disponible sur l'exemple de référentiel.
Détection de fonctionnalités
if (CSS.animationWorklet) { /* ... */ }
État de la spécification W3C
- Premier brouillon de travail public : prêt pour l'examen de la communauté, sujet à des modifications de spécifications
Prise en charge du navigateur
Google Chrome | Bord Microsoft | Navigateur Opera | Firefox | Safari |
---|---|---|---|---|
Prise en charge partielle (*) | Prise en charge partielle (*) | Prise en charge partielle (*) | Non supporté | Non supporté |
* pris en charge avec l'indicateur "Fonctionnalités expérimentales de la plate-forme Web" activé.
Source de données : Houdini est-il encore prêt ?
API de mise en page
L'API de mise en page permet aux développeurs d'étendre le processus de rendu de mise en page du navigateur en définissant de nouveaux modes de mise en page pouvant être utilisés dans la propriété CSS d' display
. L'API de mise en page introduit de nouveaux concepts, est très complexe et offre de nombreuses options pour développer des algorithmes de mise en page personnalisés.
Comme pour les autres Worklets, le Worklet de mise en page doit d'abord être enregistré et défini.
registerLayout('exampleLayout', class { static get inputProperties() { return ['--exampleVariable']; } static get childrenInputProperties() { return ['--exampleChildVariable']; } static get layoutOptions() { return { childDisplay: 'normal', sizing: 'block-like' }; } intrinsicSizes(children, edges, styleMap) { /* ... */ } layout(children, edges, constraints, styleMap, breakToken) { /* ... */ } });
Le registre des worklets contient les méthodes suivantes :
-
inputProperties
:
Un tableau de propriétés personnalisées CSS dont le Worklet gardera une trace et qui appartient à un élément de mise en page parent, c'est-à-dire l'élément qui appelle cette mise en page. Ce tableau représente les dépendances d'un Worklet de mise en page. -
childrenInputProperties
:
Un tableau de propriétés personnalisées CSS dont le Worklet gardera la trace et qui appartiennent aux éléments enfants d'un élément de mise en page parent, c'est-à-dire les enfants des éléments qui définissent cette mise en page. -
layoutOptions
: définit les propriétés de mise en page suivantes :-
childDisplay
: peut avoir une valeur prédéfinie deblock
ounormal
. Détermine si les cases seront affichées sous forme de blocs ou en ligne. -
sizing
: peut avoir une valeur prédéfinie deblock-like
oumanual
. Il indique au navigateur de pré-calculer la taille ou de ne pas pré-calculer (sauf si une taille est explicitement définie), respectivement.
-
-
intrinsicSizes
: définit comment une boîte ou son contenu s'intègre dans un contexte de mise en page.-
children
: éléments enfants d'un élément Parent Layout, c'est-à-dire les enfants de l'élément qui appellent ce layout. - edge : Disposition des
edges
d'une boîte -
styleMap
: styles OM typés d'une boîte
-
-
layout
: la fonction principale qui effectue une mise en page.-
children
: éléments enfants d'un élément Parent Layout, c'est-à-dire les enfants de l'élément qui appellent ce layout. - edge : Disposition des
edges
d'une boîte -
constraints
: contraintes d'une mise en page parent -
styleMap
: styles OM typés d'une boîte -
breakToken
: jeton de rupture utilisé pour reprendre une mise en page en cas de pagination ou d'impression.
-
Comme dans le cas d'une API Paint, le moteur de rendu du navigateur détermine quand le Worklet Paint est appelé. Il suffit de l'ajouter à un fichier HTML ou JavaScript principal.
CSS.layoutWorklet.addModule('path/to/worklet/file.js');
Et, enfin, il doit être référencé dans un fichier CSS
.exampleElement { display: layout(exampleLayout); }
Comment l'API de mise en page effectue la mise en page
Dans l'exemple précédent, exampleLayout
a été défini à l'aide de l'API Layout.
.exampleElement { display: layout(exampleLayout); }
Cet élément s'appelle une mise en page parent qui est entourée de bords de mise en page qui se composent de remplissages, de bordures et de barres de défilement. Parent Layout se compose d'éléments enfants appelés Current Layouts . Les mises en page actuelles sont les éléments cibles réels dont la mise en page peut être personnalisée à l'aide de l'API de mise en page. Par exemple, lors de l'utilisation de display: flex;
sur un élément, ses enfants sont repositionnés pour former la mise en page flexible. Ceci est similaire à ce qui se fait avec l'API Layout.
Chaque mise en page actuelle consiste en une mise en page enfant qui est un algorithme de mise en page pour le LayoutChild (élément, ::before
et ::after
les pseudo-éléments) et LayoutChild est une boîte générée par CSS qui ne contient que des données de style (pas de données de mise en page). Les éléments LayoutChild sont automatiquement créés par le moteur de rendu du navigateur lors de l'étape de style. Layout Child peut générer un fragment qui effectue réellement des actions de rendu de mise en page.
Exemple
Comme dans l'exemple de l'API Paint, cet exemple importe un Worklet de mise en page de maçonnerie directement à partir du référentiel Google Chrome Labs, mais dans cet exemple, il est utilisé avec du contenu d'image au lieu de texte. Le code source complet est disponible sur l'exemple de référentiel.
Détection de fonctionnalités
if (CSS.layoutWorklet) { /* ... */ }
État de la spécification W3C
- Premier brouillon de travail public : prêt pour l'examen de la communauté, sujet à des modifications de spécifications
Prise en charge du navigateur
Google Chrome | Bord Microsoft | Navigateur Opera | Firefox | Safari |
---|---|---|---|---|
Prise en charge partielle (*) | Prise en charge partielle (*) | Prise en charge partielle (*) | Non supporté | Non supporté |
* pris en charge avec l'indicateur "Fonctionnalités expérimentales de la plate-forme Web" activé.
Source de données : Houdini est-il encore prêt ?
Houdini et amélioration progressive
Même si CSS Houdini n'a pas encore de support de navigateur optimal, il peut être utilisé aujourd'hui avec une amélioration progressive à l'esprit. Si vous n'êtes pas familier avec l'amélioration progressive, cela vaut la peine de consulter cet article pratique qui l'explique très bien. Si vous décidez d'implémenter Houdini dans votre projet aujourd'hui, il y a peu de choses à garder à l'esprit :
- Utilisez la détection de fonctionnalités pour éviter les erreurs.
Chaque API et Worklet Houdini offre un moyen simple de vérifier s'il est disponible dans le navigateur. Utilisez la détection de fonctionnalités pour appliquer les améliorations Houdini uniquement aux navigateurs qui la prennent en charge et éviter les erreurs. - Utilisez-le uniquement pour la présentation et l'amélioration visuelle.
Les utilisateurs qui naviguent sur un site Web avec un navigateur qui ne prend pas encore en charge Houdini doivent avoir accès au contenu et aux fonctionnalités de base du site Web. L'expérience utilisateur et la présentation du contenu ne doivent pas dépendre des fonctionnalités de Houdini et doivent avoir une solution de secours fiable. - Utilisez une alternative CSS standard.
Par exemple, les propriétés personnalisées CSS standard peuvent être utilisées comme solution de rechange pour les styles définis à l'aide de l'API Custom Properties & Values.
Concentrez-vous d'abord sur le développement d'une expérience utilisateur de site Web performante et fiable, puis utilisez les fonctionnalités de Houdini à des fins décoratives en tant qu'amélioration progressive.
Conclusion
Les API Houdini permettront enfin aux développeurs de garder le code JavaScript utilisé pour la manipulation et la décoration de style plus près du pipeline de rendu du navigateur, ce qui se traduira par de meilleures performances et stabilité. En permettant aux développeurs de se connecter au processus de rendu du navigateur, ils pourront développer divers polyfills CSS qui peuvent être facilement partagés, implémentés et, potentiellement, ajoutés à la spécification CSS elle-même. Houdini rendra également les développeurs et les concepteurs moins contraints par les limitations CSS lorsqu'ils travaillent sur le style, les mises en page et les animations, ce qui se traduira par de nouvelles expériences Web agréables.
Les fonctionnalités CSS Houdini peuvent être ajoutées aux projets aujourd'hui, mais strictement avec une amélioration progressive à l'esprit. Cela permettra aux navigateurs qui ne prennent pas en charge les fonctionnalités Houdini de rendre le site Web sans erreurs et d'offrir une expérience utilisateur optimale.
Ce sera passionnant de voir ce que la communauté des développeurs proposera à mesure que Houdini gagne du terrain et une meilleure prise en charge du navigateur. Voici quelques exemples impressionnants d'expériences API Houdini de la communauté :
- Expériences CSS Houdini
- Introduction interactive à CSS Houdini
- Échantillons Houdini par Google Chrome Labs
Les références
- Brouillons de spécifications W3C Houdini
- État de Houdini (Chrome Dev Summit 2018)
- Worklet d'animation de Houdini – Google Developers
- Introduction interactive à CSS Houdini