Requêtes d'élément et comment vous pouvez les utiliser aujourd'hui
Publié: 2022-03-10Pensez un instant à une structure physique. Si vous construisez un grand édifice avec des matériaux faibles, beaucoup de soutien externe est nécessaire pour le maintenir ensemble, et les choses doivent être surconstruites pour rester solides. Lorsque vous créez un site Web à partir de HTML, CSS et JavaScript, ce support externe peut ressembler à des frameworks, des plugins, des préprocesseurs, des transpilers, des outils d'édition, des gestionnaires de packages et des processus de construction.
Au lieu d'ajouter encore un autre plugin au sommet de la pile, je me suis demandé si, en étendant l'un des langages de base, CSS , nous pourrions renforcer le matériau à partir duquel les sites Web sont construits, en développant des sites Web meilleurs et plus solides nécessitant moins de support et d'outils externes. construire.
L'état actuel des requêtes d'éléments
Avec des outils tels que les préprocesseurs CSS, nous écrivons CSS en raccourci, pour être développé plus tard dans sa forme complète (avant d'être visualisé dans un navigateur). Les plugins peuvent fonctionner sur la page avec les éléments qu'ils affectent, mais pour appliquer des styles, ils écrivent des styles CSS directement en HTML ou basculent les noms de classe qui appliquent différentes règles CSS. Dans les deux cas, nous devons écrire ou générer le CSS dont nous aurons besoin avant que la page ne se charge réellement.
Le problème
Le problème avec cette méthode est que même les meilleurs plugins nécessitent souvent une personnalisation et une configuration dans chaque mise en page que vous utilisez. De plus, lorsque JavaScript écrit des styles pour vous, il peut être difficile de garder votre logique basée sur le plugin et vos styles CSS ensemble lors de la refactorisation ou de la réutilisation du code.
Un autre problème avec les préprocesseurs est que toutes les erreurs écrites en sténographie se transforment rapidement en un désordre beaucoup plus important une fois que le CSS est développé dans sa forme complète. Lors de l'utilisation de plugins, nous ajoutons de nombreux points de défaillance potentiels. Nous utilisons peut-être plusieurs plugins pour accomplir une poignée de choses différentes qui pourraient toutes être inutiles si CSS était un peu plus puissant. Cela crée une charge supplémentaire pour les développeurs à maintenir, pour les navigateurs à rendre et pour les utilisateurs à télécharger.
Y a-t-il un espoir pour l'avenir du développement Web ?
En 2013, Tyson Matanich a écrit un article intitulé "Media Queries Are Not the Answer: Element Query Polyfill", qui a présenté le concept de requêtes d'éléments à un large public. Cela a lancé une discussion sur la manière dont les plugins et les polyfills pourraient être créés pour contourner les lacunes de CSS.
Depuis lors, en attendant que les fonctionnalités CSS progressent, un certain nombre de plugins ont été publiés qui permettent aux développeurs d'utiliser les requêtes d'éléments de différentes manières.
Que sont les requêtes d'éléments ?
Les requêtes d'élément sont comme les requêtes multimédia, sauf que leurs règles s'appliquent aux propriétés des éléments réels, plutôt qu'à celles de la fenêtre d'affichage du navigateur.
Comment EQCSS est né
Fin 2013, je me suis retrouvé à travailler sur le front-end d'une application Web Ruby on Rails. L'application devait afficher des informations détaillées aux utilisateurs, et l'objectif était de créer une interface réactive qui fonctionnerait aussi bien sur les téléphones, les tablettes et les navigateurs de bureau. Cela posait quelques défis, dont l'un était qu'une grande partie du contenu important à afficher était mieux affiché dans des tableaux - oui, des éléments de table
réels (pour montrer les transactions financières, les records sportifs, etc.).

J'ai créé des styles réactifs à l'aide de requêtes multimédias qui affichaient correctement l'élément de table
pour les navigateurs de différentes tailles. Mais dès que l'un de ces tableaux réactifs a été affiché dans un modèle contenant une barre latérale, tous mes points d'arrêt réactifs se sont soudainement transformés en points d'arrêt réactifs. Ils n'ont tout simplement pas pris en compte la barre latérale de 200 pixels de large, ce qui fait que les choses se chevauchent et semblent brisées.
Autre obstacle : la longueur des noms d'utilisateurs variait de 3 à 20 caractères, et je me suis retrouvé à souhaiter pouvoir ajuster automatiquement la taille de la police de chaque nom d'utilisateur en fonction du nombre de caractères qu'il contenait. J'avais besoin de mettre chaque nom d'utilisateur dans la barre latérale, et il était difficile de choisir une taille de police suffisamment petite pour contenir un nom d'utilisateur de 20 caractères mais suffisamment grande pour que le spectateur puisse voir un nom d'utilisateur de 3 caractères.
Pour contourner des problèmes comme ceux-ci, je me retrouvais souvent à copier des requêtes multimédia entières, à dupliquer de grandes sections de ma base de code, simplement parce que j'avais besoin d'un moyen plus intelligent d'appliquer les styles réactifs dans chaque mise en page. Je me suis appuyé sur JavaScript comme autre solution de fortune, en écrivant de nombreuses fonctions presque identiques qui surveillaient une page et appliquaient des styles là où CSS ne pouvait pas atteindre. Après un certain temps, la charge supplémentaire de tout ce code en double a commencé à alourdir la base de code et a rendu les modifications difficiles à effectuer.
Je savais qu'il devait y avoir une meilleure solution, et au bout d'un moment, j'ai commencé à penser : je n'ai pas besoin de requêtes multimédias ; ce dont j'ai besoin, ce sont des requêtes d'éléments !
Recherche et développement
Jusqu'en 2014, j'ai commencé à expérimenter différentes façons d'informer CSS sur les propriétés des éléments tels qu'ils apparaissaient sur la page, afin de pouvoir appliquer de meilleurs styles. J'espérais découvrir une approche qui me permettrait d'écrire des styles combinant la beauté de CSS avec la puissance de JavaScript.
Certaines approches abandonnées sur lesquelles j'ai abandonné incluent l'ajout d'attributs aux balises HTML afin d'ajouter un support réactif, et d'essayer de trouver des moyens d'intégrer des blocs entiers de code CSS à l'intérieur d'instructions if
basées sur JavaScript pour produire une sorte de monstre Frankenstein patché à partir de JavaScript et CSS.
Mais au lieu de faciliter les choses, toutes mes approches ratées avaient une chose en commun : elles ajoutaient plus de travail ! Je savais que la bonne solution simplifierait et réduirait le travail à faire, alors j'ai continué à chercher. Grâce à ces expériences, j'ai fini par avoir une idée précise du type de syntaxe qui serait nécessaire pour que les requêtes d'éléments fonctionnent correctement.
Comme mentionné, pour un site Web construit à partir de HTML, CSS et JavaScript, le support externe se présente sous la forme de frameworks, plugins, préprocesseurs, transpilers, outils d'édition, gestionnaires de packages et processus de construction. Au lieu d'ajouter encore un autre plugin au sommet de la pile, je me suis demandé si, en étendant l'un des langages de base, CSS, nous pourrions renforcer le matériau à partir duquel les sites Web sont construits, en créant des sites Web meilleurs et plus solides qui nécessitent moins de support externe et outils à construire.
La naissance d'une syntaxe
Fin 2014, doté d'une meilleure vision de la syntaxe nécessaire, j'ai contacté Maxime Euzière, un golfeur de code JavaScript phénoménal et lui ai demandé son avis sur la possibilité d'étendre CSS en utilisant JavaScript dans le navigateur à l'exécution. Non seulement il m'a informé que c'était possible, mais il m'a proposé de l'aider à le faire ! Nous avons nommé la syntaxe EQCSS, abréviation de « element query CSS ». Le nom est également un clin d'œil au mot "excès", car tout ce qu'il fait dépasse ce que CSS peut faire.
Le besoin
Mon exigence pour la syntaxe était qu'elle soit aussi proche que possible du CSS - si proche que les surligneurs de syntaxe seraient trompés en pensant qu'il s'agissait de CSS standard. J'ai donc cartographié la syntaxe CSS pour les requêtes d'éléments qui avaient du sens - le type de syntaxe dont les gens sont surpris n'existe pas déjà.
Je savais que si nous allions étendre la prise en charge du navigateur pour CSS en utilisant JavaScript, le plugin devrait être aussi léger et simple que possible pour faire le travail, ce qui excluait l'utilisation de bibliothèques telles que jQuery pour construire le plugin. J'avais besoin d'une bibliothèque JavaScript pure qui ajouterait les fonctionnalités que je souhaite à l'avenir dans les navigateurs que je dois prendre en charge aujourd'hui.
À l'heure actuelle, les discussions au sein de la communauté CSS se concentrent sur les règles @
personnalisées et les discussions sur les requêtes d'éléments sont encore préliminaires. Nous sommes probablement encore à des années de toute spécification CSS officielle pour des fonctionnalités comme celle-ci, et même après une spécification, nous devrons encore attendre une prise en charge suffisante du navigateur avant de pouvoir utiliser ces fonctionnalités dans les sites Web.
Attendre que ces fonctionnalités soient ajoutées au CSS n'a aucun sens lorsque nous avons besoin de cette fonctionnalité pour créer et réparer des sites Web aujourd'hui.
Le résultat
Le résultat de cette recherche a été la création d'une syntaxe qui comprend un nouvel ensemble de conditions réactives avancées, des styles étendus et de nouveaux sélecteurs pour les éléments de ciblage, ainsi qu'une bibliothèque JavaScript pure nommée EQCSS.js. De plus, la prise en charge d'Internet Explorer (IE) 8 a été fournie dans un polyfill externe facultatif. Le plugin et le polyfill ont été publiés sous la licence MIT et sont gratuits pour tout le monde.
Cas d'utilisation pour les requêtes d'éléments
Développeurs de plugins
Lors de la création de composants d'interface utilisateur et de widgets, les développeurs se retrouvent souvent limités par les requêtes multimédias. Nous devons souvent choisir entre créer de nombreuses mises en page différentes qui peuvent être configurées par la personne utilisant le plugin, et simplifier l'interface au point que vous pouvez créer une solution unique.
Mais lors de la conception de plugins et d'interfaces avec des requêtes d'éléments, nous pouvons facilement écrire des styles réactifs qui couvrent toutes les situations que nous anticipons, ce qui les rend vraiment à l'épreuve des balles, quel que soit le contenu que l'utilisateur met à l'intérieur ou l'endroit où le plugin apparaît. Supposons que nous puissions styliser un widget avec des mises en page allant de 150 à 2000 pixels de large. Ensuite, peu importe où ce widget est affiché sur un site Web, il aura toujours fière allure.
Générateurs de modèles
Lorsque vous prototypez un site Web, il est courant de réorganiser les éléments de conception sur la page et de considérer la conception comme un ensemble de composants modulaires. Si vous avez écrit des requêtes média CSS, il peut parfois s'agir d'un cas d' optimisation prématurée . En concevant avec des requêtes d'éléments, vous gardez les conditions réactives indépendantes de la mise en page, ce qui vous donne beaucoup plus de flexibilité pour déplacer les choses sans avoir à retravailler autant les styles.
Les éléments que j'ai trouvés particulièrement utiles à concevoir ou à modéliser à l'aide de requêtes d'éléments incluent :
- barres de navigation,
- modaux,
- formulaires d'inscription et de connexion,
- pieds de page,
- grilles tarifaires,
- pages de destination,
- les tables,
- boîtes à onglets,
- accordéons,
- widgets de la barre latérale,
- lecteurs multimédias,
- rubriques témoignages.
Tout élément de conception peut être « délimité » et porté n'importe où – page à page ou site Web à site Web.
Prise en charge des appareils
L'un des problèmes auxquels vous êtes confronté lorsque vous prenez en charge le Web sur des appareils mobiles est l'abondance de matériel. Le marché des appareils est plus fragmenté que jamais et de nouveaux appareils apparaissent chaque jour. Nous ne pouvons plus maintenir une liste des navigateurs et des appareils que nous prenons en charge, il est donc crucial de savoir qu'un design fonctionne partout, même sur les appareils qui n'ont pas encore été publiés.
En utilisant des requêtes d'éléments, vous pouvez mieux concevoir des sites Web et éliminer certaines de ces différences entre navigateurs.
De nombreux articles écrits récemment sur la nécessité des requêtes d'éléments illustrent en détail de nombreux cas d'utilisation. Alors, passons à leur utilisation !
Comment écrire des requêtes d'éléments
Démarrer avec EQCSS est facile. Tout ce dont vous avez besoin pour commencer à utiliser la syntaxe EQCSS est d'inclure le JavaScript quelque part dans votre code HTML.
Téléchargement de EQCSS.js
Si vous souhaitez cloner le projet EQCSS depuis GitHub, vous pouvez saisir :
git clone https://github.com/eqcss/eqcss.git
Si vous utilisez npm, vous pouvez ajouter EQCSS à votre projet avec la commande suivante :
npm install eqcss
Ajouter EQCSS.js à votre code HTML
Une fois que vous avez téléchargé EQCSS, vous pouvez l'ajouter à votre code HTML avec une balise de script
:
<script src="EQCSS.js"></script>
Ce fichier ( EQCSS.js
) inclut la prise en charge de tous les navigateurs actuels, y compris IE 9 et versions ultérieures. Pour supporter IE 8, nous aurions dû utiliser beaucoup d'autres polyfills. Gardez à l'esprit qu'IE 8 ne prend même pas en charge les requêtes multimédia CSS sans polyfill, il est donc assez étonnant que nous ayons pu également faire fonctionner les requêtes d'éléments. Pour inclure la prise en charge d'IE 8 pour un site Web utilisant EQCSS, ajoutez le lien suivant avant votre lien vers le plug-in principal :
<!‐‐[if lt IE 9]><script src="EQCSS‐polyfills.js"></script><![endif]‐‐>
Exécution d'EQCSS
Par défaut, le plug-in EQCSS calcule tous les styles qu'il trouve une fois la page chargée, ainsi qu'à chaque fois qu'il détecte le redimensionnement du navigateur, comme pour les requêtes multimédias. Vous pouvez également appeler EQCSS.apply()
manuellement avec JavaScript pour recalculer les styles à tout moment, ce qui peut être utile une fois le contenu mis à jour sur la page.
Écriture de la requête d'élément CSS
Le plug-in EQCSS.js peut lire les styles de différentes manières. Vous pouvez inclure EQCSS dans toutes les balises de style
d'une page HTML. Vous pouvez également écrire EQCSS dans une feuille de style CSS externe.
Si vous souhaitez que votre code basé sur EQCSS soit séparé de votre CSS, vous pouvez charger la syntaxe EQCSS à l'aide de la balise de script
avec le type défini sur text/eqcss
. Vous pouvez ajouter des styles en ligne dans une balise comme celle-ci, ou créer un lien vers une feuille de style .eqcss
externe avec <script type=“text/eqcss” src=styles.eqcss></script>
, qui chargerait un fichier nommé styles.eqcss
.
Anatomie d'une requête d'élément
Portée des styles
La syntaxe dans EQCSS pour écrire des requêtes d'éléments est très similaire au formatage des requêtes média CSS, mais au lieu de @media
, nous commençons la requête avec @element
. La seule autre information que nous devons fournir est au moins un sélecteur auquel ces styles doivent s'appliquer. Voici comment créer une nouvelle étendue pour un élément nommé <div class=“widget”>
:
@element '.widget' { }
L'élément entre les guillemets (dans ce cas, .widget
) peut être n'importe quel sélecteur CSS valide. Avec cette requête, nous avons créé une nouvelle portée sur l'élément .widget
. Nous n'avons pas encore inclus de conditions réactives pour la portée, donc tous les styles d'une requête comme celle-ci s'appliqueront à l'élément de portée à tout moment.
Sans la possibilité d'étendre les styles à un ou plusieurs éléments (au lieu de la page entière à la fois), nous ne serions pas en mesure d'appliquer des requêtes réactives uniquement à ces éléments. Une fois que nous avons créé cette portée au niveau de l'élément, l'utilisation des fonctionnalités plus avancées de la syntaxe EQCSS devient facile - comme le méta-sélecteur $parent
, par exemple - parce que JavaScript a maintenant un point de référence à partir duquel calculer des choses comme le parentNode
de la portée élément. C'est énorme!
Certes, CSS inclut déjà un sélecteur descendant direct, avec le >
, qui nous permet de sélectionner des éléments qui sont des enfants directs de l'élément spécifié. Mais CSS n'offre actuellement aucun moyen de voyager dans l'autre sens vers le haut de l'arbre généalogique, pour sélectionner un élément qui contient un autre élément, que l'on appellerait son élément parent. La spécification « CSS Selectors Level 4 » inclut désormais un sélecteur :has()
, qui fonctionne de manière similaire au sélecteur :has()
de jQuery, mais actuellement la prise en charge du navigateur est nulle. Le CSS Scoped rend possible un autre type de sélecteur parent.
Maintenant que nous avons ouvert une portée dans le contexte de l'élément .widget
, nous pouvons écrire des styles de son point de vue pour cibler son propre élément parent :
@element '.widget' { $parent { /* These styles apply to the parent of .widget */ } }
Un autre exemple de sélecteurs spéciaux qui peuvent être utilisés dans n'importe quelle requête d'élément sont les sélecteurs $prev
et $next
, qui représentent les éléments frères précédents et suivants. Même si CSS peut atteindre le frère suivant de notre widget avec un sélecteur comme .widget + *
, il n'y a aucun moyen en CSS d'aller en arrière et de sélectionner l'élément qui vient directement avant un autre élément.
<section> <div>This will be the previous item</div> <div class="widget">This is the scoped element</div> <div>This will be the next item</div> </section> <style> @element '.widget' { $prev { /* These styles apply to the element before .widget */ } $next { /* These styles apply to the element after .widget */ } } </style>
Requêtes d'élément
Les développeurs utilisent le plus souvent les requêtes média CSS pour une conception réactive en appliquant des styles basés sur la hauteur ou la largeur de la fenêtre d'affichage du navigateur. La syntaxe EQCSS prend en charge de nombreux nouveaux types de conditions réactives. Au lieu de travailler uniquement avec la largeur et la hauteur du navigateur, vous pouvez écrire des styles qui s'appliquent aux éléments en fonction de leurs propres propriétés, comme le nombre d'éléments enfants qu'il contient ou le nombre de caractères ou de lignes de texte dans l'élément en ce moment. .
L'ajout de ces conditions réactives à vos styles étendus est similaire à la façon dont vous formateriez les requêtes multimédia : vous ajouteriez and (condition: value)
pour chaque condition que vous souhaitez vérifier. Dans cet exemple, nous allons vérifier si des éléments .widget
affichent au moins 500 pixels de large sur la page.
@element '.widget' and (min‐width: 500px) { /* CSS rules here */ }
La syntaxe d'une requête d'élément se décompose comme suit :
- requête d'élément
@element selector_list [ condition_list ] { css_code }
- liste de sélecteur
" css selector [ "," css selector ]* "
- liste de conditions
and ( query_condition : value ) [ "and (" query condition ":" value ")" ]*
- valeur
number [ css unit ]
- condition de requête
min-height | max-height | min-width | max-width | min-characters | max-characters | min-lines | max-lines | min-children | max-children | min-scroll-y | max-scroll-y | min-scroll-x | max-scroll-x
min-height | max-height | min-width | max-width | min-characters | max-characters | min-lines | max-lines | min-children | max-children | min-scroll-y | max-scroll-y | min-scroll-x | max-scroll-x
- unité css
% | px | pt | em | cm | mm | rem | ex | ch | pc | vw | vh | vmin | vmax
% | px | pt | em | cm | mm | rem | ex | ch | pc | vw | vh | vmin | vmax
Comme autre exemple, voici comment écrire une requête qui rend l'élément body
rouge lorsque l'élément .widget
atteint 500 pixels de large :
@element '.widget' and (min‐width: 500px) { body { background: red; } }
Notez que l'élément body
change lorsque le .widget
atteint une certaine largeur, pas l'élément .widget
lui-même !
Conditions de requête d'élément
Vous trouverez ci-dessous la liste complète des conditions réactives prises en charge par EQCSS.

Conditions basées sur la largeur
- démo
min-width
pour les pixels, démo pour les pourcentages - démo de
max-width
pour les pixels, démo pour les pourcentages
Conditions basées sur la hauteur
- démo
min-height
pour les pixels, démo pour les pourcentages - démo de
max-height
pour les pixels, démo pour les pourcentages
Conditions basées sur le comptage
- démo
min-characters
pour les éléments de bloc, démo pour les entrées de formulaire - démo
max-characters
pour les éléments de bloc, démo pour les entrées de formulaire - démo
min-lines
- démo
max-lines
- démo
min-children
- démo
max-children
Conditions basées sur le défilement
- démo
min-scroll-y
- démo
max-scroll-y
- démo
min-scroll-x
- démo
max-scroll-x
Vous pouvez combiner n'importe quel nombre de ces conditions dans vos requêtes d'éléments pour obtenir des styles réactifs véritablement multidimensionnels. Cela vous donne beaucoup plus de flexibilité et de contrôle sur le rendu des éléments. Par exemple, pour réduire la taille de la police d'un en-tête de plus de 15 caractères lorsque moins de 600 pixels d'espace sont disponibles pour l'affichage, vous pouvez combiner les conditions pour max‐characters: 15
et max‐width: 600px
:
h1 { font‐size: 24pt; } @element 'h1' and (min‐characters: 16) and (max‐width: 600px) { h1 { font‐size: 20pt; } }
Sélecteurs de méta
L'un des problèmes que vous pourriez rencontrer une fois que vous avez commencé à écrire des styles étendus avec des conditions réactives est que, lorsque plusieurs instances du même sélecteur se trouvent sur une page, l'utilisation de ce sélecteur dans votre requête d'élément appliquera des styles à toutes les instances de ce sélecteur sur le page lorsque l'un d'entre eux correspond aux conditions. En prenant nos exemples .widget
précédents, supposons que nous ayons deux widgets sur la page (peut-être un dans la barre latérale et un autre affiché en pleine largeur) et que nous écrivions notre requête d'élément comme ceci :
@element '.widget' and (min‐width: 500px) { .widget h2 { font‐size: 14pt; } }
Cela signifierait que lorsque l'un des éléments .widget
de la page mesure au moins 500 pixels de large, le style s'appliquerait aux deux éléments .widget
. Ce n'est probablement pas ce que nous voulons qu'il se passe dans la plupart des cas. C'est là qu'interviennent les méta-sélecteurs !
Les deux parties qui composent notre requête d'élément sont le sélecteur et la condition réactive. Donc, si nous voulons cibler uniquement les éléments de la page qui correspondent à la fois au sélecteur et aux conditions réactives, nous pouvons utiliser le méta-sélecteur $this
. Nous pouvons réécrire notre dernier exemple afin que le style ne s'applique qu'aux éléments .widget
qui correspondent à la condition min‐width: 500px
:
@element '.widget' and (min‐width: 500px) { $this h2 { font‐size: 14pt; } }
Un certain nombre de nouveaux sélecteurs sont pris en charge par la syntaxe EQCSS qui ne sont pas dans le CSS standard. Voici la liste complète :
-
$this
démo - Démo
$parent
- Démo
$root
-
$prev
démo -
$next
démo
Ces sélecteurs ne fonctionneront que dans une requête d'élément.
Ouverture du portail entre JavaScript et CSS
-
eval(')
démo
La dernière et dernière fonctionnalité d'EQCSS est la plus folle de toutes : eval(')
. Par cette porte se cache toute la puissance de JavaScript, accessible depuis CSS. Bien que JavaScript puisse appliquer des styles aux éléments, il a actuellement du mal à atteindre certaines choses, telles que les pseudo-éléments :before
et :after
. Mais que se passerait-il si CSS pouvait atteindre JavaScript depuis l'autre direction ? Au lieu de définir les propriétés CSS de JavaScript, que se passerait-il si CSS pouvait être conscient de JavaScript ?
C'est là eval(')
entre en jeu. Vous pouvez accéder et évaluer n'importe quel JavaScript, que ce soit pour utiliser la valeur d'une variable JavaScript dans votre CSS, pour exécuter une ligne JavaScript (comme eval('new Date().getFullYear()')
), pour vérifier les valeurs du navigateur et d'autres éléments que JavaScript peut mesurer (comme eval('innerHeight')
) ou pour exécuter une fonction JavaScript et utiliser la valeur qu'elle renvoie dans vos styles CSS. Voici un exemple qui affiche 2016
dans un élément <footer>
:
@element 'footer' { $this:after { content: " eval('new Date().getFullYear()')"; } }
Utiliser $it dans eval(')
Lors de l'évaluation de JavaScript, eval(')
fonctionne également à partir du contexte de l'élément à portée active, le même élément auquel les styles pour $this
s'appliquent. Vous pouvez utiliser $it
en JavaScript écrit en eval(')
comme espace réservé pour l'élément de portée si cela vous aide à structurer le code, mais s'il est omis, cela fonctionnera de la même manière. Par exemple, disons que nous avons un div
avec le mot "bonjour" dedans. Le code suivant afficherait "hello hello":
<div>hello</div> <style> @element 'div' { div:before { content: "eval('$it.textContent') "; } } </style>
Ici, $it
fait référence à la div
car il s'agit du sélecteur actuellement étendu. Vous pouvez également omettre le $it
et écrire le code suivant pour afficher la même chose :
@element 'div' { div:before { content: "eval('textContent') "; } }
eval(')
peut être utile dans les situations où CSS n'est pas au courant des mesures ou des événements qui se produisent sur la page après son chargement. Par exemple, les éléments iframe utilisés pour intégrer des vidéos YouTube ont une largeur et une hauteur spécifiées. Bien que vous puissiez définir la largeur sur auto
dans CSS, il n'existe aucun moyen simple de maintenir le rapport d'aspect correct de la largeur à la hauteur lorsque la vidéo s'agrandit pour remplir l'espace disponible.
Une solution de contournement courante pour conserver des proportions réactives lors de la mise à l'échelle consiste à placer le contenu qui doit conserver ses proportions dans un wrapper, puis à ajouter un rembourrage au wrapper avec une valeur basée sur le rapport largeur/hauteur que vous souhaitez conserver. Cela fonctionne, mais vous oblige à connaître à l'avance le format d'image de toutes les vidéos, ainsi que davantage de balisage HTML (un élément wrapper) pour chaque vidéo que vous souhaitez intégrer de manière réactive. Multipliez cela sur tous les sites Web qui ont des vidéos réactives, et c'est beaucoup de crudités qui n'auraient pas besoin d'être là si CSS était juste un peu plus intelligent.
Peut-être qu'une meilleure approche des rapports d'aspect réactifs consiste à placer chaque vidéo dans un wrapper sans rembourrage, puis à écrire une bibliothèque JavaScript qui calcule le rapport d'aspect de chaque vidéo trouvée et applique la bonne quantité de rembourrage à chaque wrapper.
Mais que se passerait-il si CSS pouvait accéder directement à ces mesures ? Non seulement pourrions-nous consolider le CSS pour tous les différents rapports d'aspect en une seule règle, mais si nous pouvions l'évaluer une fois la page chargée, nous pourrions écrire une règle qui redimensionne de manière réactive toute vidéo que nous lui donnerons à l'avenir. Et nous pourrions tout faire sans aucun emballage !
Si cela semble trop beau pour être vrai, consultez ceci. Voici à quel point il est simple d'écrire des éléments iframe de redimensionnement réactifs sans wrapper dans EQCSS :
@element 'iframe' { $this { margin: 0 auto; width: 100%; height: eval('clientWidth/(width/height)'); } }
Ici, width
et height
font référence aux attributs width=“”
et height=“”
dans l'iframe en HTML. JavaScript peut effectuer le calcul de (width/height)
, ce qui nous donne le rapport d'aspect ; et pour l'appliquer à n'importe quelle largeur, nous diviserions simplement la largeur actuelle de l'élément iframe par le ratio.
Cela a la concision et la lisibilité du CSS, et toute la puissance du JavaScript. Aucun wrapper supplémentaire requis, aucune classe supplémentaire et aucun CSS supplémentaire.
Soyez prudent avec eval(')
, cependant. Il y a une raison pour laquelle les expressions CSS étaient considérées comme dangereuses dans le passé, et il y a aussi une raison pour laquelle nous avons essayé l'idée. Si vous ne faites pas attention au nombre d'éléments auxquels vous les appliquez sur la page ou à la fréquence à laquelle vous recalculez les styles, JavaScript pourrait finir par exécuter des centaines de fois plus que nécessaire. Heureusement, EQCSS nous permet d'invoquer EQCSS.apply()
ou EQCSS.throttle()
pour recalculer les styles manuellement, afin que nous ayons plus de contrôle sur le moment où les styles sont mis à jour.
La Zone Dangereuse !
D'autres problèmes peuvent survenir si vous créez des requêtes avec des conditions ou des styles conflictuels. EQCSS, comme CSS, est lu de haut en bas en utilisant une hiérarchie de spécificité. Bien que CSS soit un langage déclaratif, il contient certaines fonctionnalités avancées. Ce n'est qu'à quelques pas d'être Turing-complet en tant que langage de programmation. Jusqu'à présent, le débogage du CSS a été une affaire assez simple, mais EQCSS fait passer le CSS d'un simple langage déclaratif interprété à un langage de feuille de style dynamique avec une couche supplémentaire d'interprétation entre le CSS et le navigateur. Ce nouveau territoire s'accompagne d'une variété de nouveaux pièges potentiels.
Voici un exemple de boucle réciproque dans EQCSS, quelque chose dont les requêtes média CSS normales sont immunisées par conception :
@element '.widget' and (min‐width: 300px) { $this { width: 200px; } }
J'appelle ce jekyll: hide;
CSS. Mais en plus d'un style qui se déclenche continuellement, il y a aussi la possibilité d'écrire plusieurs requêtes qui se déclenchent mutuellement, dans ce que nous appelons une "boucle réciproque à double inversion", la plus désagréable de toutes :
@element '.widget' and (min‐width: 400px) { $this { width: 200px; } } @element '.widget' and (max‐width: 300px) { $this { width: 500px; } }
En théorie, ce malheureux widget serait coincé dans une boucle, redimensionnant entre 200 et 500 pixels jusqu'à la fin des temps, incapable de se fixer sur une largeur. Pour des cas comme celui-ci, EQCSS calcule simplement les règles dans l'ordre dans lequel elles sont évaluées, récompense le gagnant et passe à autre chose. Si vous deviez réorganiser l'ordre dans lequel ces règles apparaissent, ce dernier style gagnerait toujours si elles sont de spécificité égale.
Certaines personnes disent que la possibilité de créer des boucles (ou même des boucles réciproques à double inversion) est un défaut de conception, mais pour empêcher les boucles d'être possibles, vous devez limiter la puissance d'EQCSS d'une manière qui supprimerait la plupart des la valeur fournie par la syntaxe. D'un autre côté, créer des boucles infinies en JavaScript est très facile, mais ce n'est pas considéré comme un défaut du langage — c'est considéré comme une preuve de sa puissance ! C'est la même chose avec les requêtes d'éléments.
Débogage des requêtes d'élément
Actuellement, le débogage des requêtes d'éléments peut ressembler un peu au débogage des requêtes multimédias avant que nous disposions d'outils tels que l'inspecteur Web pour nous montrer les styles tels qu'ils étaient calculés sur la page. Pour l'instant, le débogage et le développement de requêtes d'éléments nécessitent que le développeur maintienne un modèle mental du comportement réactif qui devrait se produire. À l'avenir, la création d'outils de développement prenant en charge EQCSS pourrait être possible, mais pour l'instant, les outils de développement de tous les principaux navigateurs ne connaissent que les styles que EQCSS a déjà appliqués aux éléments de la page, et ils ne sont pas conscients de les conditions réactives surveillées par EQCSS.
Comment concevoir avec des requêtes d'éléments
Le moyen le plus simple d'utiliser les requêtes d'éléments consiste à convertir les conceptions existantes à l'aide de requêtes multimédias en requêtes d'éléments, en "libérant" les éléments et leurs styles réactifs d'une mise en page et en facilitant la réutilisation de ce code dans d'autres pages et projets. La requête multimédia et la requête d'élément suivantes peuvent signifier la même chose :
footer a { display: inline-block; } @media (max‐width: 500px) { footer a { display: block; } }
footer a { display: inline-block; } @element 'footer' and (max‐width: 500px) { $this a { display: block; } }
La différence est que, dans l'exemple d'origine, les liens de pied de page restent display: block
jusqu'à ce que le navigateur ait une largeur d'au moins 500 pixels. Le deuxième exemple, utilisant des requêtes d'éléments, aurait le même aspect, mais uniquement si l'élément de footer
de page était en pleine largeur.
Après avoir libéré ce style de sa requête multimédia d'origine, nous pouvons maintenant placer le pied de page dans un conteneur de n'importe quelle largeur et être sûr que lorsque le pied de page a besoin du style réactif à appliquer (c'est-à-dire lorsqu'il est plus étroit que 500 pixels), il sera appliqué.
- Assurez-vous que
EQCSS.js
est présent dans le code HTML du document de destination. - Remplacez
@media
par@element
dans le CSS. - Ajoutez un sélecteur CSS à la portée de chaque requête
@element
. - Facultatif : remplacez les occurrences de l'élément délimité par
$this
dans les requêtes d'élément.
À moins que le composant de conception que vous convertissez ait été conçu à l'origine pour s'afficher sur toute la largeur de la fenêtre d'affichage du navigateur, vous devrez probablement modifier les points d'arrêt après la conversion en requêtes d'éléments.
Éviter le verrouillage
L'expérience de création de styles EQCSS est similaire à l'expérience d'écriture de CSS standard : toutes vos propriétés et techniques CSS préférées sont toujours là, avec quelques fonctionnalités supplémentaires qui les aident à fonctionner ensemble de nouvelles façons. Étant donné que EQCSS génère des CSS standard pour le navigateur, toute fonctionnalité CSS pour laquelle votre navigateur a une prise en charge intégrée fonctionnera lorsqu'elle est utilisée avec EQCSS. Si un jour des fonctionnalités telles que les requêtes d'éléments et les styles étendus sont spécifiés dans CSS et pris en charge dans les navigateurs, vous pourrez alors commencer à les utiliser immédiatement dans votre code EQCSS, tout en continuant à compter sur EQCSS pour les autres fonctionnalités que le navigateur ne fait pas. encore pris en charge nativement.
Parce que vous pouvez utiliser la syntaxe EQCSS à la fois directement dans CSS ainsi que dans son propre script, avec le type text/eqcss
, si jamais CSS développe une syntaxe pour les requêtes d'éléments natifs, vous pourrez toujours charger EQCSS en tant que script et éviter les conflits .
Pour l'avenir, une solution que les développeurs de navigateurs expérimentent actuellement est Houdini, qui ouvrirait l'accès aux développeurs de plugins pour étendre le CSS de nouvelles manières, comme l'ajout de la prise en charge du navigateur lui-même. Un jour, il pourrait être possible d'écrire des plugins plus efficaces qui interprètent la syntaxe EQCSS et apportent ces fonctionnalités aux navigateurs d'une manière plus directe et plus performante que ne le permet la bibliothèque JavaScript actuelle.
Alors, devrions-nous toujours utiliser les Media Queries ?
Oui, même si les requêtes d'éléments offrent de nombreuses façons nouvelles et passionnantes de cibler des éléments avec des styles, les requêtes multimédias (bien que limitées) s'exécuteront toujours plus rapidement dans le navigateur qu'un style qui s'appuie sur JavaScript pour calculer. Cependant, les requêtes média CSS ne se limitent pas au style HTML pour les écrans. Les requêtes multimédia CSS prennent également en charge les requêtes basées sur l'impression et d'autres façons dont les sites Web affichent des informations. EQCSS peut être utilisé en conjonction avec des requêtes multimédias pour des éléments tels que les styles d'impression, il n'est donc pas nécessaire de supprimer la requête multimédia simplement parce que les requêtes d'éléments peuvent désormais également être utilisées !
Concevoir avec une vision 20 ⁄ 20
La meilleure chose que nous puissions faire pour l'avenir du CSS est d'expérimenter ces idées autant que possible aujourd'hui. Aucune quantité de remue-méninges et de théories sur ces fonctionnalités ne sera aussi utile que d'essayer de les mettre en œuvre et de les utiliser, en découvrant les techniques qui les rendent utiles et puissantes.
En plus de fournir une solution pour les requêtes d'éléments, EQCSS.js, espérons-le, sert également de plate-forme pour d'autres expériences d'extension de CSS. Si vous avez une idée pour une nouvelle condition réactive, une nouvelle propriété CSS ou un nouveau sélecteur à utiliser dans votre code, bifurquer EQCSS.js et le modifier pour inclure votre idée peut vous permettre d'y parvenir avec peu d'effort.
Conception modulaire
In designing layouts using element queries, the biggest shift is learning how to stop viewing the DOM from the top down and from the perspective of only the root HTML element, and to start thinking about individual elements on the page from their own perspectives within the document.
The old paradigms of “desktop-first” and “mobile-first” responsive design aren't relevant any longer — the new way of building layouts approaches design “element-first.” Using element queries enables you to work on the individual parts that make up a layout, in isolation from one another, styling them to a greater level of detail. If you are using a modular approach for your back-end code already but have so far been unable to package your CSS with your modules because of the difficulties of styling with media queries alone, then element queries will finally allow you to modularize your styles in the same way.
Thinking Element-First
Element-first design is in the same spirit as the atomic design principle but looks different in practice from how most people have implemented atomic design in the past.
For example, let's say you have some HTML like the following, and the desired responsive behavior can be explained as, “The search input and button are displayed side by side until the form gets too narrow. Then, both the input and the button should be stacked on top of each other and displayed full width.”
<form> <input type=search> <input type=button value=Search> </form>
Desktop-First Approach
In a desktop-first mindset, you would write styles for the desktop layout first and then add responsive support for smaller screens.
input { width: 50%; float: left; } @media (max‐width: 600px) { input { width: 100%; float: none; } }
Mobile-First Approach
In a mobile-first mindset, you would design the mobile view first and add support for the side-by-side view only when the screen is wide enough.
input { width: 100%; } @media (min‐width: 600px) { input { width: 50%; float: left; } }
Element-First Approach
In the first two examples, the media breakpoint was set to 600 pixels, and not because that's how wide the inputs will be when they switch. Chances are, the search input is probably inside at least one parent element that would have margins or padding. So, when the browser is 600 pixels wide, those inputs might be somewhere around 550 or 525 pixels wide on the page. In a desktop-first or mobile-first approach, you're always setting breakpoints based on the layout and how elements show up within it. With an element-first layout, you're saying, “I don't care how wide the browser is. I know that the sweet spot for where I want the inputs to stack is somewhere around 530 pixels wide.” Instead of using a media query to swap that CSS based on the browser's dimensions, with element-first design, we would scope our responsive style to the form
element itself, writing a style like this:
input { width: 100% } @element 'form' and (min‐width: 530px) { $this input { width: 50%; float: left; } }
The code is similar to that of the two previous methods, but now we are free to display this search input anywhere — in a sidebar or full width. We can use it in any layout on any website, and no matter how wide the browser is, when the form itself doesn't have enough room to display the inputs side by side, it will adapt to look its best.
Resources For Getting Started
EQCSS-Enabled Template
<!DOCTYPE html> <html> <head> <meta charset="utf‐8"> <title></title> <style></style> </head> <body> <!‐‐[if lt IE 9]><script src="https://elementqueries.com/EQCSS‐polyfills.min.js"></script><![endif]‐‐> <script src="https://elementqueries.com/EQCSS.min.js"></script> </body> </html>
Démos
- Responsive Aspect Ratio
- Sticky Scroll Header
- Blockquote Style
- Calendrier
- Content Demo
- Counting Children Demo
- Date Demo
- Zastrow-style Element Query Demo Demo
- Flyout Demo
- Headline Demo
- Media Player Demo
- Message Style Demo
- Modal Demo
- Nav Demo
- Parent Selector Demo
- Pricing Chart Demo
- Responsive Tables Demo
- Scroll-triggered Blocker Demo
- Signup Form Demo
- Testimonials Block Demo
- Tweet-Counter Demo
- JS Variables Demo
- Responsive Scaling Demo
- Geometric Design Demo
- Responsive Order Form
- Element Query Grid
- JS Functions in CSS
- Responsive Content Waterfall
Lectures complémentaires
You can find the EQCSS project on GitHub, demos, documentation and articles on the EQCSS website. An ever-growing number of Codepens use EQCSS, and you can create your own pen by forking the batteries-included template that comes hooked up with EQCSS. You can also play with the EQCSS tool that I built to preview if your EQCSS code is working as expected.
Happy hacking!