+ Les différentes versions de graphiques présentées pour le moment reposent uniquement
+ sur un balisage sémantique — à base de <table> —
+ et une tartine de variables CSS portées par les balises.
+ Aucun JavaScript n’est requis pour l’affichage, et les styles sont
+ améliorés progressivement selon les capacités de votre navigateur.
+
+
+
+ Note : en vertu du caractère expérimental
+ de ces techniques et d’une fondation solide améliorée progressivement,
+ je ne précise pas le support navigateur de chaque exemple — mais
+ il va de soi que ce n’est pas magique, et que seuls les navigateurs modernes répondent à l’appel,
+ à l’exception notable de Edge
+ qui ne supporte pas (encore) clip-path.
+ Les autres navigateurs affichent un tableau correctement stylé, et c’est chouette.
+
+
+
L’accessibilité
+
+
+ Un effort conséquent a été porté à l’accessibilité.
+ Comme évoqué précédement, un balisage sémantique et structuré est un pré-requis
+ — mais ça ne suffit pas. Les CSS
+ sont appliqués aussi progressivement que possible, afin de garantir le meilleur affichage
+ possible des données pour chaque internaute.
+
+
+
Tableau accessible
+
+
Piqure de rappel :
+
+
+
un tableau doit démarrer par un <caption> ;
+
+ les cellules d’en-tête <th> doivent porter un attribut scope,
+ avec une valeur row ou col selon le cas ;
+
+
+ et vous aurez généralement besoin de distinguer l’entête du corps grâce à
+ <thead> et <tbody> ;
+
+
+ pour les valeurs disposant d’une unité : si vous vous aventurez à utiliser l’élement
+ <abbr> pour utiliser sa version abrégée, pensez à doubler l’attribut
+ title avec l’attribut aria-label — cela en améliorera
+ considérablement l’intérêt pour de nombreux internautes.
+
+ Pour distinguer les différentes zones autrement que par la couleur, un motif
+ svg
+ est appliqué en
+ css
+ — vous en trouverez quelques-uns sur le site
+ Hero Patterns :
+
+
+
+ afin d’améliorer le mélange avec les couleurs ou dégradés d’arrière-plan, la propriété
+ background-blend-mode est utilisée avec la valeur hard-light ;
+
+
+ les tailles et positions du motif dépendent directement de la valeur et de l’échelle du
+ graphique,
+ selon le type de graphique ;
+
+
+ {% include 'includes/_svg-encoding.njk' %}
+
+
Respect des préférences
+
+ Afin de respecter autant que possible les préférences des visiteurs,
+ de nombreux éléments ont été adaptés :
+
+
+
+ les dimensions sont en unités relatives (em ou rem selon les cas),
+ afin de s’ajuster de manière cohérente au corps de texte hérité du navigateur et de pouvoir
+ être agrandi ou réduit sans perte ;
+
+ les animations et transitions sont désactivées lorsque le système
+ expose cette préférence grâce à prefers-reduced-motion: reduce ;
+
+
+ les effets de survol dont l’état initial consiste à masquer du contenu
+ sont activés contextuellement dans la requête média @media (hover: hover) { … }.
+
+
+
+
display et sémantique
+
+ Adrian Roselli explique que jouer avec le display d’un élément
+ <table> ou <dl> met en péril sa sémantique.
+ Cette dernière est donc « verrouillée » à l’aide des rôles
+ aria
+ dédiés — comme il l’explique
+ dans un article
+ détaillé.
+
+
+ C’est pourquoi chaque tableau est précédé d’un interrupteur — basé sur
+ le composant inclusif
+ conçu par Heydon Pickering —
+ dont le seul et unique rôle est de désactiver les styles supplémentaires :
+
+
+ {% include 'includes/_inclusive-toggle.njk' %}
+
+
+ Voilà, nous sommes prêts à entrer dans le vif du sujet.
+ Faites chauffer votre inspecteur !
+
+ This type of graph is used to represent one-dimensional data
+ (in our example, a timeline).
+ It's based on CSS grids and custom properties,
+ a technique inspired by
+ an article by Miriam Suzanne on
+ CSS Tricks
+ with a slight enhancement to improve accessibility.
+ Here's how to use it:
+
+
+
+
+ On the table itself, the --scale custom property is used to define the maximum value
+ for the graph,
+ in order to determine its scale. Concretely, a grid will be generated with:
+
+
the first column dedicated to header cells <th> arbitrarily set to 12.5em;
+
+
then the CSS repeat() function creates a column per scale unit — in the example, 3000
+ columns;
+
+ On each cell<td>, a --value custom property
+ allows to place it on the grid, applied to grid-column-end.
+ Moreover, thanks to clever calculations based on this value, the background gradient is sized
+ and positioned to reflect the proportion represented by this value on the given scale
+ (from green for almost nothing to red for almost everything).
+
+
+ In each cell, the content must include the value and its unit in a
+ <span> element, possibly tagged with <abbr>
+ (and aria-label to complement title) if a title can explicit the unit.
+ This value is pushed to the right of the grid, and its text serves as a mask for the background
+ gradient — thanks to S. Shaw's trick to
+ apply background-clip: text as a progressively enhancement — allowing it to be the
+ corresponding color at the end of the gradient for the given position.
+
+
+
+ {% import 'macros/_table-bar.njk' as table %}
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+ The principle is the same for this variant, except for one detail: we also manage
+ the starting point for each measurement
+ — which is, very simply, the value of the previous point…
+ However, all the values must be passed as variables on the parent <table>.
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+ Ce type de graphique sert à représenter des données à une dimension
+ (dans notre exemple, une ligne de temps).
+ Il repose sur les grilles et les variables CSS,
+ technique inspirée
+ d’un article de Miriam
+ Suzanne sur
+ CSS Tricks
+ légèrement agrémentée pour en améliorer l’accessibilité.
+ Pour vous en servir, c’est simple :
+
+
+
+
+ Sur le tableau, une variable --scale permet de définir la valeur maximale du
+ graphique,
+ afin d’en déterminer l’échelle. Concrètement, une grille va être générée avec :
+
+
la première colonne pour les entêtes <th> arbitrairement fixée à 12.5em ;
+
+
puis la fonction CSS repeat() crée une colonne par unité de l’échelle — dans l’exemple,
+ 3000 colonnes ;
+
+ Sur chaque cellule<td>, une variable --value permet de la placer
+ sur la grille,
+ appliquée à grid-column-end.
+ De plus grâce à de savants calculs reposant sur cette valeur, le dégradé en arrière-plan est dimensionné et
+ positionné de façon à
+ refléter la proportion représentée par cette valeur sur l’échelle donnée (du vert pour presque rien au rouge pour
+ presque tout).
+
+
+ Dans chaque cellule, le contenu doit reprendre la valeur et son unité dans un élément <span>,
+ éventuellement
+ balisée avec <abbr> (et aria-label pour suppléer title) si un
+ intitulé peut être explicité pour l’unité.
+ Cette valeur est poussée à droite de la grille, et son texte sert de masque pour le dégradé en arrière-plan
+ — grâce à une astuce de S.
+ Shaw's pour
+ appliquer background-clip: text en amélioration progressive — lui permettant d’être de la
+ couleur correspondante
+ à la fin du dégradé pour la position donnée.
+
+
+
+ {% import 'macros/_table-bar.njk' as table %}
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+ Le principe est le même pour cette variante, à un détail près :
+ on gère également le point de départ pour chaque mesure
+ — qui est, très simplement, la valeur du point précédent…
+ Il faut cependant passer toutes les valeurs en tant que variables sur
+ le parent <table>.
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+ Le graphique en tarte sert pour les représentations de proportions en pourcentage.
+ Il s’appuie sur des variables CSS, un abus outrancier de calc(),
+ display: table-*, clip-path, mask-image,
+ transform et un tantinet de SVG
+ pour distinguer chaque zone. Oui, je sais rigoler. Comment qu’on s’en sert ?
+
+
+
+
+ Sur chaque entête<th>, une variable --color
+ permet d’attribuer, et bien… une couleur.
+
+
+ Puis chaque cellule<td> doit contenir la valeur et son unité,
+ ainsi qu’un attribut style pour porter quelques variables :
+
+
+ --value correspond à la valeur en pourcentage,
+ utile pour déterminer l’angle que doit occuper l’élément sur le cercle.
+ Tous les points du polygon() — servant à tracer la part du fromage
+ à l’aide de clip-path — dépendent de cette valeur (lire la note
+ technique après l’exemple pour le détail
+ des calculs).
+
+
+ --start permet de définir le point de départ de l’arc
+ sur le cercle. Il s’agit de la somme des précédentes définitions, et est appliqué
+ à la fonction rotate() de la propriété transform.
+
+
+ Et enfin une série de variables booléennes valant chacune 0 ou 1
+ — d’après une idée de
+ Roman Komarov dans son article "Conditions for CSS variables" —
+ dépendent de la valeur : --lt-25, --gt-25, --lt-50…
+ Elles permettent de faire basculer les points de leur position d’origine
+ (50% 50%) à leur position calculée, en s’additionnant ou se soustrayant
+ à la valeur initiale ;
+
+
+
+
+ un pseudo-élément::before sur chaque cellule <td> est mis en
+ forme
+ de savante manière en fonction de toutes nos variables, avec notamment transform,
+ clip-path et mask-image.
+
+ un pseudo-élément::after est utilisé pour simuler une infobulle, récapitulant
+ l’entête et la valeur de la cellule — l’affichage de propriétés personnalisées dans un pseudo-élément n’est
+ pas si triviale :
+
+
+ content n’accepte que les chaînes de caractères, et nos propriétés personnalisées contiennent…
+ des nombres.
+
+ Dans ce graphique, chaque portion représente un arc de cercle basé sur un angle (une partie de 360 degrés).
+ Pour définir la forme de cette portion, il faut donc placer un point sur le cercle.
+
+
+ Pour ce faire, je divise le cercle en quatre carrés. La position du point sur le cercle peut ainsi
+ être calculée en utilisant les propriétés du triangle rectangle formé par :
+
+
+
le centre du cercle,
+
le point que nous cherchons à positionner,
+
et le point perpendiculaire au rayon et passant par notre point cible.
+
+
+ Nous connaissons l’hypoténuse de ce triangle — le rayon du cercle —,
+ et l’angle formé par l’hypoténuse et partant du centre du cercle
+ (en ramenant la valeur sur 90 degrés, puisque le cercle est divisé en quatre secteurs carrés :
+ si la valeur est supérieure à 25 : moins 90°, etc.)
+ — plus un angle droit, bien entendu.
+
+ L’utilisation de variables pseudo-booléennes rend ce calcul pseudo-algorithmique.
+ Démarrons par un pré-requis essentiel : le polygone étant un tracé fermé et CSS
+ n’étant pas magique, les points doivent pré-exister.
+ Spoiler, il nous faut onze points :
+
+
+
+ L’axe initial, du centre vers le milieu en haut : 50% 50%
+ et 50% 0%.
+
+
+ Un point pour chaque angle aux extrémités : le premier est fixe, à
+ 100% 0% (en haut à droite) — puis chacun des autres angles
+ a deux états, atteint ou non. Quelques détails :
+
+
+ Par exemple le point en bas à droite concerne
+ les valeurs entre 25% et 50% : si la valeur est inférieure à 25%, il doit
+ être au centre (pour ne pas gêner le tracé), et dans le cas contraire être
+ dans son coin. ce qui s’exprime ainsi :
+ calc( 50% + ( var(--gt-25, 0) * 50% ) ) calc( 50% + ( var(--gt-25, 0) * 50% ) )
+ Ainsi la valeur calculée sera 50% 50% si --gt-25 vaut 0,
+ et 100% 100% si --gt-25 vaut 1.
+
+
+ De plus, chaque angle a sa coordonnée cible :
+ 100% 100% pour en bas à droite, 0% 100% pour en bas à gauche,
+ 0% 0% pour en haut à gauche. Il faut donc tantôt soustraire et
+ tantôt ajouter 50% à la valeur intitiale 50% 50%
+ pour basculer sur le bon point.
+
+
+
+
+ Un point pour chaque position possible par quart de cercle, correspondant à
+ chaque tranche de 25%. À l’instar des points aux angles, ces points doivent être au centre
+ s’ils ne sont pas utilisés. C’est là qu’on rigole le plus :
+
+
on part de 50%, auxquels on ajoute ou soustrait la suite du calcul ;
+
+ on utilise enfinla position calculée — --pos-A
+ ou --pos-B selon le cas — qu’on convertit en pourcentages à l’aide de
+ * 1%, et qu’on rend inerte si la valeur est inférieure à la tranche concernée
+ grâce à * var(--lt-25, 1), par exemple.
+
+ Remarquez le seconde valeur dans var(), qui est la valeur par défaut
+ si la variable n’est pas définie. Cool, non ?
+
+
+
+ et finalement lorsque la tranche est dépassée, le point bascule vers
+ 0% ou 100% selon le cas.
+
+
+
+
+ Et enfin, on referme le tracé en revenant au centre du cercle,
+ à 50% 50%.
+
+
+
C’est tout !
+
Les positions illustrées
+
+ Ces captures d’écran — effectuées dans
+ l’éditeur
+ de formes
+ des outils de développement de Firefox —
+ montrent les points du polygone dans les différents cas. Vous pouvez consulter pour chaque valeur citée
+ le polygone résolu pour clip-path — et constater le basculement des valeurs dynamiques d’une
+ position à une autre.
+
+
+
+
+
+
+
+ Exemple de rendu pour 64%
+
+
+
+ Capture d’écran du tracé pour 64%.
+
+
+ {% include 'includes/_pie-styles:64.njk' %}
+ Code généré pour 64%.
+
+
+
+
+
+
+ Exemple de rendu pour 88%
+
+
+
+ Capture d’écran du tracé pour 88%.
+
+
+ {% include 'includes/_pie-styles:88.njk' %}
+ Code généré pour 88%.
+
+
+
+
+
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+ L’utilisation de conic-gradient() est prometteuse pour ce cas précis.
+ Vous en trouverez des exemples réalisés par Ana Tudor ou Léa Verou — qui a
+ carrément rédigé la spécification,
+ et conçu un polyfill.
+ Cependant le support limité aux navigateurs
+ basés sur WebKit est déprimant, et pose tout de même quelques questions
+ en matière d’accessibilité puisqu’on ne peut pas affecter un motif à chaque couleur du dégradé
+ conique.
+
+
+
+
Polaire
+
+
+ Pour cette déclinaison, on ne change presque rien : seulement la variable --zoom
+ et son implication dans la mise à l’échelle des portions à l’aide de scale().
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Répartition du poids des ressources pour ffoodd.fr
+
+ the repeat() function applied with the --scale custom property
+ enables us to handle a dynamic scale;
+
+
+ <thead>, <tbody> and <tr> containers
+ are neutralized in the grid structure using display: contents;
+
+
+ each cell is placed on the grid depending its --value
+ — its background color also depending on its value;
+
+
+ and finally its text value — wrapped in a <span> element —
+ is positioned at the top of the column using the same trick as in the bar chart.
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
Browser market shares in France in January 2019
+
+
+
Browser
+
Chrome
+
Firefox
+
Safari
+
Edge
+
IE
+
Others
+
+
+
+
+
Market shares
+
62%
+
15%
+
9%
+
5%
+
6%
+
3%
+
+
+
+
+
+
+ HTML
+
{% include 'includes/_column-markup.njk' %}
+
+
+ css
+
{% include 'includes/_column-styles.njk' %}
+
+
+
Multiple columns
+
+
+ In order to have two values for each main column, we must also have
+ two subheadings. Concretely speaking:
+
+
+
+
+ we add a second row in <thead>:
+
+
+ with two column header cells <th scope="col">
+ for each column header cell in the first row;
+
+
+ remember to add colspan="2" on the first row's header cell
+ to match the new table layout;
+
+
+ and finally add an identifier to each header cell
+ to referenced them to the relevant data cells — using the
+ headers attribute, par exemple pour la première cellule:
+ headers="browser chrome year chrome-2018" where each value
+ is a header cell's identifier.
+
+
+
+
+ Styles:
+
+
+ the first-level header cells must span two columns of the grid,
+ as required by their colspan for the table layout. It is
+ unfortunately impossible to use an attribute value in another
+ property than content — otherwise we could simply write
+ grid-column: 2 / span attr(colspan);, and that would be awesome…
+
+
+ but no! Thus, a --span custom property is added on <table>,
+ and must match the colspan attributes values mentionned earlier:
+ it is therefore used to extend the first level headers to the appropriate number of columns.
+
+
+ Colors and patterns are no longer applied according to each value,
+ but according to each column — in the example, every second element
+ (since we have two entries per column).
+ Again, if we could use an attribute value or a custom property
+ in a selector, that would be great. Imagine
+ tbody td:nth-of-type(var(--span)n + var(--span)) or even
+ tbody td:nth-of-type(attr(colspan)n + attr(colspan))!
+
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+ Ce graphique repose sur les variables CSS, les grilles et clip-path.
+ Cette dernière propriété est la plus importante.
+
+
+
+
+ Sur le tableau, les échelles et l’unité sont indiquées :
+
+
+ --y définit l’échelle des ordonnées, utilisée
+ pour indiquer l’échelle en arrière-plan mais aussi placer
+ les points sur la courbe ;
+
+
+ --x correspond à l’échelle des abscisses, exprimée
+ simplement comme le nombre de colonnes à afficher ;
+
+
--unit permet de définir l’unité à afficher dans l’infobulle simulée.
+
+
+
+ Chaque ligne <tr> dans <tbody> porte une palanquée
+ de variables, correspondant à toutes les valeurs qu’elle contient.
+ Dans un pseudo-élément ::before, une position est définie pour chaque valeur
+ au sein de la fonction polygon() de clip-path.
+
+
+ Étant donné que cette fonction accepte deux valeurs en pourcentage
+ chaque point, la méthode est relativement simple.
+ La position en abscisse est le nombre de colonnes (le décalage depuis la gauche, donc)
+ et la position en ordonnée est le ratio de la valeur sur l’échelle, le tout formulé ainsi :
+ calc( ( 100% / var(--x) * 1 ) + var(--offset) ) calc( 100% - ( var(--1) / var(--y) * 100% ) ),
+ où * 1 et var(--1) correspondent à l’index de la valeur dans l’ensemble,
+ et var(--offset) est la valeur d’une demi-colonne, pour placer le point au milieu
+ de sa colonne.
+
+
+ Vous l’aurez peut-être compris, le principal écueil de ce graphique est qu’il
+ nécessite de connaître le nombre de points par avance.
+
+ Chaque cellule <td> dans <tbody> porte un pseudo-élément
+ ::after qui sert à récapituler ses entêtes et valeur dans
+ une infobulle simulée, et un pseudo-élément ::before pour gérer un calque interactif sur la cellule :
+
Et finalement la propriété personnalisée --unit sert de finition.
+
+
+
+ Tout le reste n’est que décoration :
+
+
+ un padding-top important sur le tableau pour
+ réserver l’espace d’affichage des graphiques — attention :
+ il est nécessaire d’appliquer border-collapse: separate; sur le tableau
+ afin que le padding ait un impact ;
+
+
le ::before de chaque ligne est étiré afin d’occuper tout l’espace réservé ;
+
un arrière-plan dégradé pour représenter la surface pleine du même ::before ;
+
+ un repeating-linear-gradient() pour représenter l’échelle verticale,
+ en arrière-plan du tableau ;
+
+
+ et des interactions au survol pour mettre en exergue la valeur survolée :
+ sa colonne à l’aide d’un pseudo-élément — positionné à l’aide de de savants calculs —
+ et mix-blend-mode pour un effet waouh.
+
+ Pour commencer, il faut bien intégrer que clip-path est un tracé,
+ au même titre qu’une forme vectorielle. Il doit donc être fermé.
+ Ainsi le tracé démarre à 0% 100% — en bas à gauche, fait sa vie
+ de tracé, bascule à 100% 100% et revient boucler à 0% 100%.
+
+
Et dans son chemin, chaque point doit être positionné en abscisses et en ordonnées.
+
La position en abscisse
+
+ La première position est simple : on divise 100% par l’échelle
+ var(--x), et on multiplie par l’index de l’élément. Par exemple :
+ calc( ( 100% / var(--x) * 1) ).
+ Pour placer chaque point au milieu de sa colonne, on le décale d’une demi-colonne
+ — ce que l’on fait en ajoutant au calcul précédent var(--offset), qui correspond
+ à calc( ( 100% / var(--x) ) / 2 ).
+ La position finale est donc, ici pour le troisième point :
+ calc( ( 100% / var(--x) * 3) + var(--offset) ).
+
+
La position en ordonnée
+
+ Dans ce graphique, l’ordonnée est l’axe le plus important. Ainsi pour placer le point,
+ on commence par calculer le ratio de sa valeur sur l’échelle — formulé
+ ainsi : var(--1) / var(--y). Et parce que polygon() utilise
+ des valeurs en pourcentage, on rapporte ce calcul sur 100% :
+ ( var(--1) / var(--y) * 100% ).
+ Et pour finir, les référentiels du polygone partant d’en haut à gauche, la position
+ doit être définie en fonction du haut de la boîte. La formule finale ressemble
+ alors à ça — toujours pour le troisième élément :
+ calc( 100% - ( var(--3) / var(--y) * 100% ) ).
+
+
+
+
Graphique à point
+
+
Cette variante diffère finalement assez peu de la précédente mouture :
+
+
+
+ le polygon() est poursuivi pour former une ligne,
+ en dupliquant chaque point avec un décalage de 4px
+ — l’épaisseur du trait — et dans l’ordre inverse ;
+
+
+ le pseudo-élément ::before qui permet d’afficher l’infobulle prend ici la forme d’un
+ point sur la courbe — positionné à l’aide des mêmes calculs qui servent dans le polygone ;
+
+
+ et surtout, puisque clip-path est appliqué sur la ligne
+ <tr> : vous pouvez en mettre plusieurs !
+ Il nous faut donc ajouter une combinaison de couleur et motif pour distinguer chaque ligne
+ et les associer visuellement à leur légende.
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+ la fonction repeat() appliquée avec la variable --scale
+ permet de gérer une échelle dynamique ;
+
+
+ les conteneurs <thead>, <tbody> et <tr>
+ sont neutralisés dans la gestion de la grille à l’aide de display: contents ;
+
+
+ chaque cellule est placée sur la grille en fonction de --value
+ — sa valeur, donc — sa couleur d’arrière-plan dépend également de
+ sa valeur ;
+
+
+ et finalement la valeur textuelle — contenue dans un élément
+ <span> — est positionnée en haut de la colonne
+ à l’aide de la même astuce que dans le graphique en barre.
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Parts de marché navigateurs en France en janvier 2019
+
+
+
Navigateur
+
Chrome
+
Firefox
+
Safari
+
Edge
+
IE
+
Autres
+
+
+
+
+
Parts de marché
+
62 %
+
15 %
+
9 %
+
5 %
+
6 %
+
3 %
+
+
+
+
+
+
+ Le HTML
+
+
{% include 'includes/_column-markup.njk' %}
+
+
+ Le css
+
{% include 'includes/_column-styles.njk' %}
+
+
+
Colonnes multiples
+
+
+ Pour disposer de deux valeurs pour chaque colonne principale, nous devons également
+ disposer de deux sous-titres.
+ Concrètement parlant :
+
+
+
+
+ on ajoute une seconde ligne dans l’entête<thead> :
+
+
+ avec deux cellules d’entête de colonne <th scope="col">
+ pour chaque cellule d’entête de colonne dans la première ligne d’entête ;
+
+
+ n’oublions pas d’ajouter un colspan="2" sur les cellules d’entête de
+ la première ligne pour faire correspondre la structure du tableau ;
+
+
+ et enfin ajouter un identifiant à chaque cellule d’entête
+ afin de les référencer sur les cellules de données concernées — à l’aide
+ de l’attribut headers, par exemple pour la première cellule :
+ headers="navigateur chrome annee chrome-2018" où chaque valeur est un
+ identifiant de cellule d’entête.
+
+
+
+
+ Côté styles :
+
+
+ les cellules d’entête de premier niveau doivent s’étendre sur deux colonnes de la grille,
+ comme le réclame leur attribut colspan pour la structure du tableau. Il est
+ malheureusement impossible d’utiliser la valeur d’un attribut dans une autre
+ propriété que content — sinon nous pourrions simplement écrire
+ grid-column: 2 / span attr(colspan); et ça serait magnifique…
+
+
+ mais non ! Ainsi, une variable --span est ajoutée sur <table>,
+ et doit correspondre à la valeur des attributs colspan cités plus tôt :
+ elle sert donc à étendre les entêtes de premier niveau sur le nombre de colonnes adéquat.
+
+
+ les couleurs et motifs ne sont plus appliqués en fonction
+ de chaque valeur, mais en fonction de chaque colonne — dans l’exemple, un élément
+ sur deux (puisque nous avons deux entrées par colonne).
+ Là aussi, si nous pouvions utiliser une valeur d’attribut ou une propriété personnalisée
+ dans un sélecteur, ce serait génial. Imaginez un peu
+ tbody td:nth-of-type(var(--span)n + var(--span)) ou encore
+ tbody td:nth-of-type(attr(colspan)n + attr(colspan)) !
+
+
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Parts de marché navigateurs en France en janvier 2019
diff --git a/src/templates/includes/_radars-styles.html b/_site/templates/includes/_radars-styles.njk
similarity index 100%
rename from src/templates/includes/_radars-styles.html
rename to _site/templates/includes/_radars-styles.njk
diff --git a/src/templates/includes/_sin-mixin.html b/_site/templates/includes/_sin-mixin.njk
similarity index 100%
rename from src/templates/includes/_sin-mixin.html
rename to _site/templates/includes/_sin-mixin.njk
diff --git a/src/templates/includes/_svg-encoding.html b/_site/templates/includes/_svg-encoding.njk
similarity index 100%
rename from src/templates/includes/_svg-encoding.html
rename to _site/templates/includes/_svg-encoding.njk
diff --git a/src/templates/includes/_waterfall-markup.html b/_site/templates/includes/_waterfall-markup.njk
similarity index 83%
rename from src/templates/includes/_waterfall-markup.html
rename to _site/templates/includes/_waterfall-markup.njk
index 2cc6371..5bf7cda 100644
--- a/src/templates/includes/_waterfall-markup.html
+++ b/_site/templates/includes/_waterfall-markup.njk
@@ -1,3 +1,3 @@
+ Every charts in this project relies solely on semantic markup
+ — <table> based — and a spread of
+ CSS variables carried by the tags.
+ No JavaScript required for display, and styles are
+ progressively enhanced depending on your browser's capabilities.
+
+
+
+ Note : by virtue of the experimental
+ nature of these techniques and a solid foundation enhanced progressively,
+ I don't mention browser support for each example — but
+ it goes without saying that this is not magic, and only modern browsers handle this right,
+ with the notable exception of Edge
+ which does not (yet) support clip-path.
+ Other browsers display a properly styled table, and that's nice.
+
+
+
Accessibility
+
+
+ A major effort has been made to ensure accessibility.
+ As mentioned above, semantic and structured markup is a prerequisite
+ — but it's not enough. CSS
+ is being applied as gradually as possible, in order to guarantee
+ the best possible display of data for each user.
+
+
+
Accessible table
+
+
Wakeup call :
+
+
+
a table must start with a <caption>;
+
+ header cells <th> must carry a scope attribute,
+ with a row or col value;
+
+
+ and you'll usually need to distinguish the head from the body through
+ <thead> and <tbody>;
+
+
+ for values with a unit : if you venture to use the
+ <abbr> element to use its abbreviated version, consider doubling the
+ title with the aria-label attribute — this will considerably
+ improve the interest for many users.
+
+ To distinguish the different areas other than by colour, an
+ svg
+ pattern is applied in
+ css
+ — you can find some of them on the
+ Hero Patterns website:
+
+
+
+ in order to improve blending with background colors or gradients, the
+ background-blend-mode proerty is used with the hard-light value;
+
+
+ pattern's size and position depends directly on the value and scale of the chart,
+ depending on the type of chart;
+
+
+ {% include 'includes/_svg-encoding.njk' %}
+
+
User preferences
+
+ In order to respect as much as possible the preferences of the visitors,
+ many elements have been adapted:
+
+
+
+ dimensions are in relatives units (em or rem as the case may be),
+ in order to fit coherently with the body of text inherited from the browser and to be able
+ to be enlarged or reduced without loss;
+
+ animations and transitions are disabled when the system exposes
+ this preference through prefers-reduced-motion: reduce ;
+
+
+ hover effects whose initial state consists in hiding content
+ are activated contextually in the @media (hover: hover) { … } media query.
+
+
+
+
display and semantics
+
+ Adrian Roselli explains that playing with a <table> or <dl>
+ element's display endangers its semantics.
+ The latter is therefoore "locked" using dedicated
+ aria
+ roles — as he explains
+ in a detailed article.
+
+ This chart is based on CSS custom properties, grids and clip-path
+ — the latter being the most important.
+
+
+
+
+ Scales are set on the table:
+
+
+ --y defines the y-axis scale, used to indicate the scale
+ in the background but also to place the points on the curve;
+
+
+ --x is the x-axis scale,
+ simply expressed as the number of columns to display;
+
+
--unit defines unit to be displayed in simulated tooltip (see below).
+
+
+
+ Each line <tr> in <tbody> carries a set of variables,
+ corresponding to all the values it contains.
+ In a ::before pseudo-element, a position is defined for each value
+ within the clip-pathpolygon() function.
+
+
+ Since this function accepts two percentage values at each point,
+ the method is pretty straightforward.
+ The x-axis position is the number of columns (i.e., the offset from the left) and
+ the y-axis position is the ratio of the value on the scale, formulated as follows:
+ calc( ( 100% / var(--x) * 1 ) + var(--offset) ) calc( 100% - ( var(--1) / var(--y) * 100% ) ),
+ where * 1 and var(--1) is the index of the value as a whole,
+ and var(--offset) is the value of half a column,
+ to place the point in the middle of its column.
+
+
+ As you may have understood, the main pitfall of this graph is
+ that it requires to know the number of points in advance.
+
+ Each cell <td> in <tbody> carries an
+ ::after pseudo-element used to summarize
+ its headers and value in a simulated tooltip, and a ::before pseudo-element
+ to manage an interactive layer on the cell:
+
+ a big padding-top on the table is used to reserve space
+ for the charts — caution:
+ it is necessary to apply border-collapse: separate; on the table
+ for the padding to have an impact;
+
+
each line's ::before is stretched in order to occupy all the reserved space;
+
a gradient background to represent the full area of the same ::before;
+
+ a repeating-linear-gradient() to represent the vertical scale
+ in the table's background;
+
+
+ and hover interactions to highlight the hovered value:
+ its column using a pseudo-element — positioned with the help of clever calculations —
+ and mix-blend-mode for a wow effect.
+
+ To begin with, you need to understand that clip-path is a path,
+ just like a vector shape. It must therefore be closed.
+ So the path starts at 0% 100% — bottom left, does its path life,
+ toggles to 100% 100% and comes back looping at 0% 100%.
+
+
And in its path, each point must be positioned in abscissa and ordinate.
+
The X-axis position
+
+ The first position is simple: divide 100% by the
+ var(--x) scale, and multiply by the index of the element.
+ For example: calc( ( 100% / var(--x) * 1) ).
+ To place each point in the middle of its column, we shift it by half a column
+ — which we do by adding to the previous calculation var(--offset),
+ which corresponds to calc( ( 100% / var(--x) ) / 2 ).
+ The final position is therefore, here for the third point:
+ calc( ( 100% / var(--x) * 3) + var(--offset) ).
+
+
The Y-axis position
+
+ In this graph, the Y-axis is the most important axis. So to place the point,
+ we start by calculating the ratio of its value on the scale
+ — formulated as follows: var(--1) / var(--y). And because
+ polygon() uses percentage values, we report this calculation on 100%:
+ ( var(--1) / var(--y) * 100% ).
+ And finally, since the polygon's datums start from the top left, the position
+ position must be defined according to the top of the box.
+ The final formula then looks like this — again for the third element:
+ calc( 100% - ( var(--3) / var(--y) * 100% ) ).
+
+
+
+
+
Line chart with dots
+
+
In the end, this variant differs little from the previous version:
+
+
+
+ the polygon() is continued to form a line,
+ duplicating each point with an offset of 4px
+ — the line thickness — and in the reverse order;
+
+
+ the ::before pseudo-element that displays the tooltip takes
+ here the form of a point on the curve
+ — positioned using the same calculations that are used in the polygon;
+
+
+ and especially, since clip-path is applied in the line
+ <tr>: you can put more than one !
+ So we need to add a combination of color and pattern to distinguish each line
+ and associate them visually with their caption.
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+ The pie chart is used for representations of percentage proportions.
+ It relies on CSS variables, an outrageous abuse of calc(),
+ display: table-*, clip-path, mask-image,
+ transform and a bit of SVG
+ to distinguish each area. Yes, I know how to laugh. How do we use it?
+
+
+
+
+ On each header<th>, a --color
+ custom property allows you to assign, well… a color.
+
+
+ Then each cell<td> must contain the value
+ and its unit, as well as a style attribute to carry some variables:
+
+
+ --value is the percentage value,
+ useful for determining the angle the element should occupy on the circle.
+ All points of the polygon() — used to draw the pie part thanks to clip-path —
+ depend on this value (read the technical note after
+ the example for details of the calculations).
+
+
+ --start is used to define the starting point
+ of the arc on the circle. It's the sum of the previous definitions, and is applied
+ to the rotate() function of the transform poperty.
+
+
+ And finally a series of pseudo-boolean variables, each worthing 0 or 1
+ — according to and idea of
+ Roman Komarov in "Conditions for CSS variables" —
+ depend on the value: --lt-25, --gt-25, --lt-50…
+ They allow to toggle the points from their original position
+ (50% 50%) to their calculated position, by adding or subtracting from the initial value;
+
+
+
+
+ a ::beforepseudo-element on each cell <td>is formatted
+ in a clever way according to all our variables, including transform,
+ clip-path and mask-image.
+
+ a ::afterpseudo-element is used as a tooltip, to summarize header and value for
+ each cell
+ —but the display of custom properties in a pseudo-element is not so trivial:
+
+
+ content only accepts strings, and our custom properties contains… number.
+
+ In this graph, each portion represents an arc of a circle based on an angle (part of 360 degrees).
+ To define the shape of this portion, a point must be placed on the circle.
+
+
+ To do this, I divide the circle into four squares. The position of the point on the circle
+ can then be calculated using the properties of the right-angled triangle formed by:
+
+
+
the center of the circle,
+
the point we're trying to position,
+
and the point perpendicular to the radius and passing through our target point.
+
+
+ We know the hypotenuse of this triangle — the radius of the circle —,
+ and the angle formed by the hypotenuse and starting from the center of the circle
+ (reducing the value to 90 degrees, since the circle is divided into four square sectors:
+ if the value is greater than 25: minus 90°, etc.)
+ — plus a right angle, of course.
+
+ The use of pseudo-Boolean variables makes this calculation pseudo-algorithmic.
+ Let's start with an essential pre-requisite: the polygon being a closed shape and CSS
+ not being magical, points must pre-exist.
+ Spoiler, we need eleven points:
+
+
+
+ The initial axis, from centre upwards: 50% 50%
+ and 50% 0%.
+
+
+ One point for each angle at the ends: the first one is fixed, at
+ 100% 0% (top right) — then each of the other angles has
+ two states, reached or not reached. Some insights:
+
+
+ For example, the point at the bottom right concerns values between 25% and 50%:
+ if the value is less than 25%, it must be in the centre (so as not to interfere
+ with the drawing), and if not, it must be in its corner:
+ calc( 50% + ( var(--gt-25, 0) * 50% ) ) calc( 50% + ( var(--gt-25, 0) * 50% ) )
+ Thus the calculated value will be 50% 50% if --gt-25 is 0,
+ and 100% 100% if --gt-25 is 1.
+
+
+ In addition, each angle has its target coordinate:
+ 100% 100% for bottom right, 0% 100% for bottom left,
+ 0% 0% for top left. It is therefore necessary to sometimes subtract
+ and sometimes add to the initial value 50% 50%
+ to switch to the right point.
+
+
+
+
+ One point for each possible position per quarter circle, corresponding
+ to each 25% slice. Like the points at the corners, these points must be in the centre
+ if they are not used. That's where we laugh the most:
+
+
we start from 50%, to which we add or subtract the following calculation;
+
+ then the calculated position is used — --pos-A
+ or --pos-B as the case may be — which is converted into percentages using
+ * 1%, and rendered inert if the value is less than the range concerned
+ using * var(--lt-25, 1), for example.
+
+ Notice the second value in var()?
+ This is the default value if the variable is not defined. Cool, isn't it?
+
+
+
+ finally when the range is exceeded, the point switches to
+ 0% or 100% as appropriate.
+
+
+
+
+ And lastly, we lose the path by going back to the centre of the circle,
+ at 50% 50%.
+
+
+
That's it!
+
The positions illustrated
+
+ These screenshots — taken in
+ the shape editor of
+ the
+ Firefox devtools —
+ show the points of the polygon in the different cases.
+ You can see for each cited value the resolved polygon for clip-path
+ — and see how the dynamic values tilt from one position to another.
+
+
+
+
+ Rendering example for 44%
+
+
+
+ Shape screenshot for 44%.
+
+
+ {% include 'includes/_pie-styles:44.njk' %}
+ Code generated for 44%.
+
+
+
+
+
+
+ Rendering example for 64%
+
+
+
+ Shape screenshot for 64%.
+
+
+ {% include 'includes/_pie-styles:64.njk' %}
+ Code generated for 64%.
+
+
+
+
+
+
+ Rendering example for 88%
+
+
+
+ Shape screenshot for 88%.
+
+
+ {% include 'includes/_pie-styles:88.njk' %}
+ Code generated for 88%.
+
+
+
+
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+ On the <table> element, we add an --offset variable
+ that allows us to determine the size of the hole of the donut,
+ generated using mask-image and radial-gradient().
+ Ana Tudor has made
+ many examples of using mask-* on CodePen, have a look!
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
Distribution of the weight of resources for ffoodd.fr
+
+ The use of conic-gradient() is promising for this case.
+ You'll find examples made by Ana Tudor and Léa Verou
+ — who actually wrote the specification, and designed
+ a polyfill.
+ However, current support is limited to WebKit based
+ browsers
+ is depressing, and still raises some accessibility issues
+ since you can't assign a pattern to each color of the conic-gradient().
+
+
+
+
Polar chart
+
+
+ For this variant, wa change almost nothing: only the --zoom variable
+ and its implication in the scaling of portions using scale().
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
Distribution of the weight of resources for ffoodd.fr
+
+ This one's kind of fun. We define some CSS
+ variables on the table: the scale (and tiers), the number of elements, and the values.
+
+
+
+ On the CSS side, it's getting complicated:
+
+
+
+
+ on the <table> element, the circular scale is created using two successive
+ repeating-radial-gradient() — depending on the
+ --scale and --step variables;
+
each one is decorated with a border at the bottom;
+
+ then we use again clip-pathpolygon() function
+ on each direct child <span> — extended to occupy the whole surface
+ of its parent <td> — in order to form a triangle, based for one side
+ on the ratio value of the current element / scale, and on another side a ratio based on the
+ value of the next element (yum calc())
+ — but on another scale…
+
+
+ because to compensate for the distortion
+ due to the skew() function,
+ we need to correct the scale on which the second ratio is calculated
+ using a little trigonometry:
+
+
+ we know one side of the right-angled triangle obtained after the deformation,
+ as well as two angles — the right one, of course, and we deduce
+ the second from the angle used to deform the element;
+
+
+ so we can calculate the hypothenuse using the sine law,
+ — as before in the pie chart;
+
+
+ and finally, all we have to do is calculate the ratio between the initial dimension
+ — the side — and the final dimension — the hypothenuse —
+ and apply this ratio to the scale on which the second point of the polygon is placed.
+
+
+
+
+ The third point of the polygon is the bottom right corner, whose coordinates are
+ 100% 100%;
+
+
+
+
+ one last trick is necessary to close the shape you have seen,
+ we use the current and next value for each element. But when we get to the last element,
+ there is no next! So we need to add a value, to which we assign
+ the first value — in this example, --8: var(--1);.
+
+
+
+
And that's it!
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
Level of interest by domain, out of 20
+
+
+
Accessibility
+
SEO
+
Performance
+
Compatibility
+
Security
+
Code quality
+
Test
+
+
+
+
+
14
+
11
+
13
+
16
+
10
+
12
+
4
+
+
+
+
+
+
+ HTML
+
{% include 'includes/_radar-markup.njk' %}
+
+
+ css
+
{% include 'includes/_radar-styles.njk' %}
+
+
+ A Chromium bug
+
+ There is currently a bug in Chromium — I filled
+ an issue on bugs.chromium.org —
+ when using the border-spacing property on the table:
+ it prevents Chrome to define the dimensions of the table…
+ For Chrome user, use the inspector to uncheck this property on the
+ <table> tag of these examples!
+
+
Reduced test case
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
Very few changes compared to the previous version:
+
+
+
+ the <table> element no longer carries the values,
+ but has a new --areas custom property to indicate the number of rows in the table;
+
+
+ however we multiply the number of rows in the body of the table:
+
+
+ each one carries several variables:
+ --color then the values — --1, etc.;
+
+
+ and contains several cells: a <th scope="row"> row header cell
+ and <td> data cells;
+
+
+
+
+ the rest is relatively common now — if you've gone through the previous examples:
+
+
+ a color for each row, presented on the header cells
+ and serving as a background for the data cells;
+
+
+ a distinctive hover effect over each row: the values appear
+ verbatim on hovering, and the hovered row is highlighted. In order not to deprive users
+ who do not have a good hover pointer, this effect is a progressive enhancement
+ based on the @media (hover: hover) { … } media query.
+
+
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+ Celui-ci est plutôt amusant. On définit quelques variables
+ CSS sur le tableau
+ : l’échelle (et les paliers), le nombre d’éléments, et les valeurs.
+
+
+
+ Côté CSS, ça se complique :
+
+
+
+
+ sur l’élément <table>, on crée l’échelle circulaire à l’aide de deux
+ repeating-radial-gradient() successifs — en fonction des variables
+ --scale et --step ;
+
+ puis on utilise de nouveau clip-path et la fonction polygon()
+ sur chaque enfant direct <span> — étendu pour occuper toute la surface
+ de son <td> de parent — afin de former un triangle, basé pour un côté
+ sur le ratio valeur de l’élément courant / échelle, et sur un autre côté un ratio basé sur
+ la valeur de l’élément suivant (miam les calc())
+ — mais sur une autre échelle…
+
+
+ car pour compenser la distorsiondue à la fonction skew(),
+ nous devons corriger l’échelle sur laquelle est calculée le second ratio à l’aide d’un peu
+ de trigonométrie :
+
+
+ nous connaissons un côté du triangle rectangle obtenu après la déformation,
+ ainsi que deux angles — le droit, bien entendu, et nous déduisons le deuxième de
+ l’angle utilisé pour déformer l’élément ;
+
+
+ nous pouvons donc calculer l’hypothénuse en utilisant la loi des sinus,
+ — comme précédemment dans le graphique en tarte ;
+
+
+ et finalement, il ne nous reste qu’à calculer le ratio entre la dimension initiale
+ — le côté — et la dimension finale — l’hypothénuse — et appliquer ce ratio
+ à l’échelle sur laquelle est placée le deuxième point du polygone.
+
+
+
+
+ le troisième point du polygône est l’angle en bas à droite, dont les coordonnées sont
+ 100% 100% ;
+
+
+
+
+ une dernière astuce est nécessaire pour fermer la forme vous l’avez vu, nous utilisons
+ la valeur courante et la valeur suivante pour chaque élément. Mais arrivé au dernier élément,
+ il n’y a plus de suivant ! Il faut donc ajouter une valeur,
+ à laquelle on attribue la première valeur — dans cet exemple, --8: var(--1);.
+
+
+
+
Et voilà, c’est tout !
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Niveau d’intérêt par domaine, sur 20
+
+
+
Accessibilité
+
Référencement
+
Performance
+
Compatibilité
+
Sécurité
+
Qualité de code
+
Test
+
+
+
+
+
14
+
11
+
13
+
16
+
10
+
12
+
4
+
+
+
+
+
+
+ Le HTML
+
+
{% include 'includes/_radar-markup.njk' %}
+
+
+ Le css
+
{% include 'includes/_radar-styles.njk' %}
+
+
+ Bug dans Chromium
+
+ Il y a en ce moment un bug dans Chromium — j’ai saisi
+ un ticket sur bugs.chromium.org —
+ lors de l’utilisation de la propriété border-spacing sur le tableau :
+ cela empêche Chrome de définir les dimensions du tableau…
+ Pour les utilisateurs de Chrome, utilisez l’inspecteur pour décocher cette propriété
+ sur la balise <table> de ces exemples !
+
+
Cas de test réduit
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
Très peu de changements par rapport à la version précédente :
+
+
+
+ l’élément <table> ne porte plus les valeurs, mais dispose d’une nouvelle
+ variable --areas pour indiquer le nombre de lignes dans le tableau ;
+
+
+ en revanche on multiplie le nombre de lignes dans le corps du tableau :
+
+
+ chacune porte plusieurs variables :
+ --color puis les valeurs — --1, etc. ;
+
+
+ et contient plusieurs cellules : une d’entête de ligne <th scope="row">
+ et des cellules de données <td> ;
+
+
+
+
+ le reste est relativement commun désormais — si vous avez parcourus les exemples précédents :
+
+
+ une couleur pour chaque ligne, présentée sur les cellules d’entête et servant d’arrière-plan aux
+ cellules de données ;
+
+
+ un effet distinctif au survol de chaque ligne : les valeurs apparaissent
+ textuellement au survol, et la ligne survolée est mise en exergue. Afin de ne pas priver les utilisateurs
+ n’ayant pas de pointeur doué pour le survol, cet effet est une amélioration progressive
+ basé sur la media query@media (hover: hover) { … }.
+
+
+
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
- Les différentes versions de graphiques présentées pour le moment reposent uniquement
- sur un balisage sémantique — à base de <table> —
- et une tartine de variables CSS portées par les balises.
- Aucun JavaScript n’est requis pour l’affichage, et les styles sont
- améliorés progressivement selon les capacités de votre navigateur.
-
-
-
- Note : en vertu du caractère expérimental
- de ces techniques et d’une fondation solide améliorée progressivement,
- je ne précise pas le support navigateur de chaque exemple — mais
- il va de soi que ce n’est pas magique, et que seuls les navigateurs modernes répondent à l’appel,
- à l’exception notable de Edge
- qui ne supporte pas (encore) clip-path.
- Les autres navigateurs affichent un tableau correctement stylé, et c’est chouette.
-
-
-
L’accessibilité
-
-
- Un effort conséquent a été porté à l’accessibilité.
- Comme évoqué précédement, un balisage sémantique et structuré est un pré-requis
- — mais ça ne suffit pas. Les CSS
- sont appliqués aussi progressivement que possible, afin de garantir le meilleur affichage
- possible des données pour chaque internaute.
-
-
-
Tableau accessible
-
-
Piqure de rappel :
-
-
-
un tableau doit démarrer par un <caption> ;
-
- les cellules d’en-tête <th> doivent porter un attribut scope,
- avec une valeur row ou col selon le cas ;
-
-
- et vous aurez généralement besoin de distinguer l’entête du corps grâce à
- <thead> et <tbody> ;
-
-
- pour les valeurs disposant d’une unité : si vous vous aventurez à utiliser l’élement
- <abbr> pour utiliser sa version abrégée, pensez à doubler l’attribut
- title avec l’attribut aria-label — cela en améliorera
- considérablement l’intérêt pour de nombreux internautes.
-
- Pour distinguer les différentes zones autrement que par la couleur, un motif
- svg
- est appliqué en
- css
- — vous en trouverez quelques-uns sur le site
- Hero Patterns :
-
-
-
- afin d’améliorer le mélange avec les couleurs ou dégradés d’arrière-plan, la propriété
- background-blend-mode est utilisée avec la valeur hard-light ;
-
-
- les tailles et positions du motif dépendent directement de la valeur et de l’échelle du graphique,
- selon le type de graphique ;
-
+ Les différentes versions de graphiques présentées pour le moment reposent uniquement
+ sur un balisage sémantique — à base de <table> —
+ et une tartine de variables CSS portées par les balises.
+ Aucun JavaScript n’est requis pour l’affichage, et les styles sont
+ améliorés progressivement selon les capacités de votre navigateur.
+
+
+
+ Note : en vertu du caractère expérimental
+ de ces techniques et d’une fondation solide améliorée progressivement,
+ je ne précise pas le support navigateur de chaque exemple — mais
+ il va de soi que ce n’est pas magique, et que seuls les navigateurs modernes répondent à l’appel,
+ à l’exception notable de Edge
+ qui ne supporte pas (encore) clip-path.
+ Les autres navigateurs affichent un tableau correctement stylé, et c’est chouette.
+
+
+
L’accessibilité
+
+
+ Un effort conséquent a été porté à l’accessibilité.
+ Comme évoqué précédement, un balisage sémantique et structuré est un pré-requis
+ — mais ça ne suffit pas. Les CSS
+ sont appliqués aussi progressivement que possible, afin de garantir le meilleur affichage
+ possible des données pour chaque internaute.
+
+
+
Tableau accessible
+
+
Piqure de rappel :
+
+
+
un tableau doit démarrer par un <caption> ;
+
+ les cellules d’en-tête <th> doivent porter un attribut scope,
+ avec une valeur row ou col selon le cas ;
+
+
+ et vous aurez généralement besoin de distinguer l’entête du corps grâce à
+ <thead> et <tbody> ;
+
+
+ pour les valeurs disposant d’une unité : si vous vous aventurez à utiliser l’élement
+ <abbr> pour utiliser sa version abrégée, pensez à doubler l’attribut
+ title avec l’attribut aria-label — cela en améliorera
+ considérablement l’intérêt pour de nombreux internautes.
+
+ Pour distinguer les différentes zones autrement que par la couleur, un motif
+ svg
+ est appliqué en
+ css
+ — vous en trouverez quelques-uns sur le site
+ Hero Patterns :
+
+
+
+ afin d’améliorer le mélange avec les couleurs ou dégradés d’arrière-plan, la propriété
+ background-blend-mode est utilisée avec la valeur hard-light ;
+
+
+ les tailles et positions du motif dépendent directement de la valeur et de l’échelle du
+ graphique,
+ selon le type de graphique ;
+
- Afin de respecter autant que possible les préférences des visiteurs,
- de nombreux éléments ont été adaptés :
-
-
-
- les dimensions sont en unités relatives (em ou rem selon les cas),
- afin de s’ajuster de manière cohérente au corps de texte hérité du navigateur et de pouvoir
- être agrandi ou réduit sans perte ;
-
- les animations et transitions sont désactivées lorsque le système
- expose cette préférence grâce à prefers-reduced-motion: reduce ;
-
-
- les effets de survol dont l’état initial consiste à masquer du contenu
- sont activés contextuellement dans la requête média @media (hover: hover) { … }.
-
-
-
-
display et sémantique
-
- Adrian Roselli explique que jouer avec le display d’un élément
- <table> ou <dl> met en péril sa sémantique.
- Cette dernière est donc « verrouillée » à l’aide des rôles
- aria
- dédiés — comme il l’explique
- dans un article détaillé.
-
-
- C’est pourquoi chaque tableau est précédé d’un interrupteur — basé sur
- le composant inclusif
- conçu par Heydon Pickering —
- dont le seul et unique rôle est de désactiver les styles supplémentaires :
-
+ Afin de respecter autant que possible les préférences des visiteurs,
+ de nombreux éléments ont été adaptés :
+
+
+
+ les dimensions sont en unités relatives (em ou rem selon les cas),
+ afin de s’ajuster de manière cohérente au corps de texte hérité du navigateur et de pouvoir
+ être agrandi ou réduit sans perte ;
+
+ les animations et transitions sont désactivées lorsque le système
+ expose cette préférence grâce à prefers-reduced-motion: reduce ;
+
+
+ les effets de survol dont l’état initial consiste à masquer du contenu
+ sont activés contextuellement dans la requête média @media (hover: hover) { … }.
+
+
+
+
display et sémantique
+
+ Adrian Roselli explique que jouer avec le display d’un élément
+ <table> ou <dl> met en péril sa sémantique.
+ Cette dernière est donc « verrouillée » à l’aide des rôles
+ aria
+ dédiés — comme il l’explique
+ dans un article
+ détaillé.
+
+
+ C’est pourquoi chaque tableau est précédé d’un interrupteur — basé sur
+ le composant inclusif
+ conçu par Heydon Pickering —
+ dont le seul et unique rôle est de désactiver les styles supplémentaires :
+
- This type of graph is used to represent one-dimensional data
- (in our example, a timeline).
- It's based on CSS grids and custom properties,
- a technique inspired by
- an article by Miriam Suzanne on
- CSS Tricks
- with a slight enhancement to improve accessibility.
- Here's how to use it:
-
-
-
-
- On the table itself, the --scale custom property is used to define the maximum value for the graph,
- in order to determine its scale. Concretely, a grid will be generated with:
-
-
the first column dedicated to header cells <th> arbitrarily set to 12.5em;
-
then the CSS repeat() function creates a column per scale unit — in the example, 3000 columns;
- On each cell<td>, a --value custom property
- allows to place it on the grid, applied to grid-column-end.
- Moreover, thanks to clever calculations based on this value, the background gradient is sized
- and positioned to reflect the proportion represented by this value on the given scale
- (from green for almost nothing to red for almost everything).
-
-
- In each cell, the content must include the value and its unit in a
- <span> element, possibly tagged with <abbr>
- (and aria-label to complement title) if a title can explicit the unit.
- This value is pushed to the right of the grid, and its text serves as a mask for the background
- gradient — thanks to S. Shaw's trick to
- apply background-clip: text as a progressively enhancement — allowing it to be the
- corresponding color at the end of the gradient for the given position.
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
+ This type of graph is used to represent one-dimensional data
+ (in our example, a timeline).
+ It's based on CSS grids and custom properties,
+ a technique inspired by
+ an article by Miriam Suzanne on
+ CSS Tricks
+ with a slight enhancement to improve accessibility.
+ Here's how to use it:
+
+
+
+
+ On the table itself, the --scale custom property is used to define the maximum value
+ for the graph,
+ in order to determine its scale. Concretely, a grid will be generated with:
+
+
the first column dedicated to header cells <th> arbitrarily set to 12.5em;
+
+
then the CSS repeat() function creates a column per scale unit — in the example, 3000
+ columns;
+
+ On each cell<td>, a --value custom property
+ allows to place it on the grid, applied to grid-column-end.
+ Moreover, thanks to clever calculations based on this value, the background gradient is sized
+ and positioned to reflect the proportion represented by this value on the given scale
+ (from green for almost nothing to red for almost everything).
+
+
+ In each cell, the content must include the value and its unit in a
+ <span> element, possibly tagged with <abbr>
+ (and aria-label to complement title) if a title can explicit the unit.
+ This value is pushed to the right of the grid, and its text serves as a mask for the background
+ gradient — thanks to S. Shaw's trick to
+ apply background-clip: text as a progressively enhancement — allowing it to be the
+ corresponding color at the end of the gradient for the given position.
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
- The principle is the same for this variant, except for one detail: we also manage
- the starting point for each measurement
- — which is, very simply, the value of the previous point…
- However, all the values must be passed as variables on the parent <table>.
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
+ The principle is the same for this variant, except for one detail: we also manage
+ the starting point for each measurement
+ — which is, very simply, the value of the previous point…
+ However, all the values must be passed as variables on the parent <table>.
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
- Ce type de graphique sert à représenter des données à une dimension
- (dans notre exemple, une ligne de temps).
- Il repose sur les grilles et les variables CSS,
- technique inspirée
- d’un article de Miriam Suzanne sur
- CSS Tricks
- légèrement agrémentée pour en améliorer l’accessibilité.
- Pour vous en servir, c’est simple :
-
-
-
-
- Sur le tableau, une variable --scale permet de définir la valeur maximale du graphique,
- afin d’en déterminer l’échelle. Concrètement, une grille va être générée avec :
-
-
la première colonne pour les entêtes <th> arbitrairement fixée à 12.5em ;
-
puis la fonction CSS repeat() crée une colonne par unité de l’échelle — dans l’exemple, 3000 colonnes ;
- Sur chaque cellule<td>, une variable --value permet de la placer sur la grille,
- appliquée à grid-column-end.
- De plus grâce à de savants calculs reposant sur cette valeur, le dégradé en arrière-plan est dimensionné et positionné de façon à
- refléter la proportion représentée par cette valeur sur l’échelle donnée (du vert pour presque rien au rouge pour presque tout).
-
-
- Dans chaque cellule, le contenu doit reprendre la valeur et son unité dans un élément <span>, éventuellement
- balisée avec <abbr> (et aria-label pour suppléer title) si un intitulé peut être explicité pour l’unité.
- Cette valeur est poussée à droite de la grille, et son texte sert de masque pour le dégradé en arrière-plan
- — grâce à une astuce de S. Shaw's pour
- appliquer background-clip: text en amélioration progressive — lui permettant d’être de la couleur correspondante
- à la fin du dégradé pour la position donnée.
-
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
+ Ce type de graphique sert à représenter des données à une dimension
+ (dans notre exemple, une ligne de temps).
+ Il repose sur les grilles et les variables CSS,
+ technique inspirée
+ d’un article de Miriam
+ Suzanne sur
+ CSS Tricks
+ légèrement agrémentée pour en améliorer l’accessibilité.
+ Pour vous en servir, c’est simple :
+
+
+
+
+ Sur le tableau, une variable --scale permet de définir la valeur maximale du
+ graphique,
+ afin d’en déterminer l’échelle. Concrètement, une grille va être générée avec :
+
+
la première colonne pour les entêtes <th> arbitrairement fixée à 12.5em ;
+
+
puis la fonction CSS repeat() crée une colonne par unité de l’échelle — dans l’exemple,
+ 3000 colonnes ;
+
+ Sur chaque cellule<td>, une variable --value permet de la placer
+ sur la grille,
+ appliquée à grid-column-end.
+ De plus grâce à de savants calculs reposant sur cette valeur, le dégradé en arrière-plan est dimensionné et
+ positionné de façon à
+ refléter la proportion représentée par cette valeur sur l’échelle donnée (du vert pour presque rien au rouge pour
+ presque tout).
+
+
+ Dans chaque cellule, le contenu doit reprendre la valeur et son unité dans un élément <span>,
+ éventuellement
+ balisée avec <abbr> (et aria-label pour suppléer title) si un
+ intitulé peut être explicité pour l’unité.
+ Cette valeur est poussée à droite de la grille, et son texte sert de masque pour le dégradé en arrière-plan
+ — grâce à une astuce de S.
+ Shaw's pour
+ appliquer background-clip: text en amélioration progressive — lui permettant d’être de la
+ couleur correspondante
+ à la fin du dégradé pour la position donnée.
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
- Le principe est le même pour cette variante, à un détail près :
- on gère également le point de départ pour chaque mesure
- — qui est, très simplement, la valeur du point précédent…
- Il faut cependant passer toutes les valeurs en tant que variables sur
- le parent <table>.
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
+ Le principe est le même pour cette variante, à un détail près :
+ on gère également le point de départ pour chaque mesure
+ — qui est, très simplement, la valeur du point précédent…
+ Il faut cependant passer toutes les valeurs en tant que variables sur
+ le parent <table>.
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
- Le graphique en tarte sert pour les représentations de proportions en pourcentage.
- Il s’appuie sur des variables CSS, un abus outrancier de calc(),
- display: table-*, clip-path, mask-image,
- transform et un tantinet de SVG
- pour distinguer chaque zone. Oui, je sais rigoler. Comment qu’on s’en sert ?
-
-
-
-
- Sur chaque entête<th>, une variable --color
- permet d’attribuer, et bien… une couleur.
-
-
- Puis chaque cellule<td> doit contenir la valeur et son unité,
- ainsi qu’un attribut style pour porter quelques variables :
-
-
- --value correspond à la valeur en pourcentage,
- utile pour déterminer l’angle que doit occuper l’élément sur le cercle.
- Tous les points du polygon() — servant à tracer la part du fromage
- à l’aide de clip-path — dépendent de cette valeur (lire la note technique après l’exemple pour le détail
- des calculs).
-
-
- --start permet de définir le point de départ de l’arc
- sur le cercle. Il s’agit de la somme des précédentes définitions, et est appliqué
- à la fonction rotate() de la propriété transform.
-
-
- Et enfin une série de variables booléennes valant chacune 0 ou 1
- — d’après une idée de
- Roman Komarov dans son article "Conditions for CSS variables" —
- dépendent de la valeur : --lt-25, --gt-25, --lt-50…
- Elles permettent de faire basculer les points de leur position d’origine
- (50% 50%) à leur position calculée, en s’additionnant ou se soustrayant
- à la valeur initiale ;
-
-
-
-
- un pseudo-élément::before sur chaque cellule <td> est mis en forme
- de savante manière en fonction de toutes nos variables, avec notamment transform,
- clip-path et mask-image.
-
- un pseudo-élément::after est utilisé pour simuler une infobulle, récapitulant
- l’entête et la valeur de la cellule — l’affichage de propriétés personnalisées dans un pseudo-élément n’est pas si triviale :
-
-
- content n’accepte que les chaînes de caractères, et nos propriétés personnalisées contiennent…
- des nombres.
-
- Et finalement un motif est appliqué sur l’arrière-plan, afin de mieux
- l’associer visuellement avec la légende correspondante.
-
-
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
-
Répartition du poids des ressources pour ffoodd.fr
-
-
-
Ressource
-
Proportion
-
-
-
-
-
-
HTML
-
-
-
-
- 2 %
-
-
-
-
-
CSS
-
-
-
-
- 2 %
-
-
-
-
-
JS
-
-
-
-
- 32 %
-
-
-
-
-
Json
-
-
-
-
- 1 %
-
-
-
-
-
Images
-
-
-
-
- 44 %
-
-
-
-
-
Webfonts
-
-
-
-
- 17 %
-
-
-
-
-
Autres
-
-
-
-
- 2 %
-
-
-
-
-
-
-
- Un peu de trigonométrie
-
-
- Dans ce graphique, chaque portion représente un arc de cercle basé sur un angle (une partie de 360 degrés).
- Pour définir la forme de cette portion, il faut donc placer un point sur le cercle.
-
-
- Pour ce faire, je divise le cercle en quatre carrés. La position du point sur le cercle peut ainsi
- être calculée en utilisant les propriétés du triangle rectangle formé par :
-
-
-
le centre du cercle,
-
le point que nous cherchons à positionner,
-
et le point perpendiculaire au rayon et passant par notre point cible.
-
-
- Nous connaissons l’hypoténuse de ce triangle — le rayon du cercle —,
- et l’angle formé par l’hypoténuse et partant du centre du cercle
- (en ramenant la valeur sur 90 degrés, puisque le cercle est divisé en quatre secteurs carrés :
- si la valeur est supérieure à 25 : moins 90°, etc.)
- — plus un angle droit, bien entendu.
-
+ Le graphique en tarte sert pour les représentations de proportions en pourcentage.
+ Il s’appuie sur des variables CSS, un abus outrancier de calc(),
+ display: table-*, clip-path, mask-image,
+ transform et un tantinet de SVG
+ pour distinguer chaque zone. Oui, je sais rigoler. Comment qu’on s’en sert ?
+
+
+
+
+ Sur chaque entête<th>, une variable --color
+ permet d’attribuer, et bien… une couleur.
+
+
+ Puis chaque cellule<td> doit contenir la valeur et son unité,
+ ainsi qu’un attribut style pour porter quelques variables :
+
+
+ --value correspond à la valeur en pourcentage,
+ utile pour déterminer l’angle que doit occuper l’élément sur le cercle.
+ Tous les points du polygon() — servant à tracer la part du fromage
+ à l’aide de clip-path — dépendent de cette valeur (lire la note
+ technique après l’exemple pour le détail
+ des calculs).
+
+
+ --start permet de définir le point de départ de l’arc
+ sur le cercle. Il s’agit de la somme des précédentes définitions, et est appliqué
+ à la fonction rotate() de la propriété transform.
+
+
+ Et enfin une série de variables booléennes valant chacune 0 ou 1
+ — d’après une idée de
+ Roman Komarov dans son article "Conditions for CSS variables" —
+ dépendent de la valeur : --lt-25, --gt-25, --lt-50…
+ Elles permettent de faire basculer les points de leur position d’origine
+ (50% 50%) à leur position calculée, en s’additionnant ou se soustrayant
+ à la valeur initiale ;
+
+
+
+
+ un pseudo-élément::before sur chaque cellule <td> est mis en
+ forme
+ de savante manière en fonction de toutes nos variables, avec notamment transform,
+ clip-path et mask-image.
+
+ un pseudo-élément::after est utilisé pour simuler une infobulle, récapitulant
+ l’entête et la valeur de la cellule — l’affichage de propriétés personnalisées dans un pseudo-élément n’est
+ pas si triviale :
+
+
+ content n’accepte que les chaînes de caractères, et nos propriétés personnalisées contiennent…
+ des nombres.
+
+ Et finalement un motif est appliqué sur l’arrière-plan, afin de mieux
+ l’associer visuellement avec la légende correspondante.
+
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Répartition du poids des ressources pour ffoodd.fr
+
+
+
+
Ressource
+
Proportion
+
+
+
+
+
HTML
+
+ 2 %
+
+
+
+
CSS
+
+ 2 %
+
+
+
+
JS
+
+ 32 %
+
+
+
+
Json
+
+ 1 %
+
+
+
+
Images
+
+ 44 %
+
+
+
+
Webfonts
+
+ 17 %
+
+
+
+
Autres
+
+ 2 %
+
+
+
+
+
+
+
+ Un peu de trigonométrie
+
+
+ Dans ce graphique, chaque portion représente un arc de cercle basé sur un angle (une partie de 360 degrés).
+ Pour définir la forme de cette portion, il faut donc placer un point sur le cercle.
+
+
+ Pour ce faire, je divise le cercle en quatre carrés. La position du point sur le cercle peut ainsi
+ être calculée en utilisant les propriétés du triangle rectangle formé par :
+
+
+
le centre du cercle,
+
le point que nous cherchons à positionner,
+
et le point perpendiculaire au rayon et passant par notre point cible.
+
+
+ Nous connaissons l’hypoténuse de ce triangle — le rayon du cercle —,
+ et l’angle formé par l’hypoténuse et partant du centre du cercle
+ (en ramenant la valeur sur 90 degrés, puisque le cercle est divisé en quatre secteurs carrés :
+ si la valeur est supérieure à 25 : moins 90°, etc.)
+ — plus un angle droit, bien entendu.
+
- L’utilisation de variables pseudo-booléennes rend ce calcul pseudo-algorithmique.
- Démarrons par un pré-requis essentiel : le polygone étant un tracé fermé et CSS
- n’étant pas magique, les points doivent pré-exister.
- Spoiler, il nous faut onze points :
-
-
-
- L’axe initial, du centre vers le milieu en haut : 50% 50%
- et 50% 0%.
-
-
- Un point pour chaque angle aux extrémités : le premier est fixe, à
- 100% 0% (en haut à droite) — puis chacun des autres angles
- a deux états, atteint ou non. Quelques détails :
-
-
- Par exemple le point en bas à droite concerne
- les valeurs entre 25% et 50% : si la valeur est inférieure à 25%, il doit
- être au centre (pour ne pas gêner le tracé), et dans le cas contraire être
- dans son coin. ce qui s’exprime ainsi :
- calc( 50% + ( var(--gt-25, 0) * 50% ) ) calc( 50% + ( var(--gt-25, 0) * 50% ) )
- Ainsi la valeur calculée sera 50% 50% si --gt-25 vaut 0,
- et 100% 100% si --gt-25 vaut 1.
-
-
- De plus, chaque angle a sa coordonnée cible :
- 100% 100% pour en bas à droite, 0% 100% pour en bas à gauche,
- 0% 0% pour en haut à gauche. Il faut donc tantôt soustraire et
- tantôt ajouter 50% à la valeur intitiale 50% 50%
- pour basculer sur le bon point.
-
-
-
-
- Un point pour chaque position possible par quart de cercle, correspondant à
- chaque tranche de 25%. À l’instar des points aux angles, ces points doivent être au centre
- s’ils ne sont pas utilisés. C’est là qu’on rigole le plus :
-
-
on part de 50%, auxquels on ajoute ou soustrait la suite du calcul ;
-
- on utilise enfinla position calculée — --pos-A
- ou --pos-B selon le cas — qu’on convertit en pourcentages à l’aide de
- * 1%, et qu’on rend inerte si la valeur est inférieure à la tranche concernée
- grâce à * var(--lt-25, 1), par exemple.
-
- Remarquez le seconde valeur dans var(), qui est la valeur par défaut
- si la variable n’est pas définie. Cool, non ?
-
-
-
- et finalement lorsque la tranche est dépassée, le point bascule vers
- 0% ou 100% selon le cas.
-
-
-
-
- Et enfin, on referme le tracé en revenant au centre du cercle,
- à 50% 50%.
-
-
-
C’est tout !
-
Les positions illustrées
-
- Ces captures d’écran — effectuées dans
- l’éditeur de formes
- des outils de développement de Firefox —
- montrent les points du polygone dans les différents cas. Vous pouvez consulter pour chaque valeur citée
- le polygone résolu pour clip-path — et constater le basculement des valeurs dynamiques d’une position à une autre.
-
-
-
-
- Exemple de rendu pour 44%
-
-
-
- Capture d’écran du tracé pour 44%.
-
-
-
td[style*="--value: 44;"]::before {
+
+
+
+ Le calcul tordu
+
Les positions du polygone
+
+ L’utilisation de variables pseudo-booléennes rend ce calcul pseudo-algorithmique.
+ Démarrons par un pré-requis essentiel : le polygone étant un tracé fermé et CSS
+ n’étant pas magique, les points doivent pré-exister.
+ Spoiler, il nous faut onze points :
+
+
+
+ L’axe initial, du centre vers le milieu en haut : 50% 50%
+ et 50% 0%.
+
+
+ Un point pour chaque angle aux extrémités : le premier est fixe, à
+ 100% 0% (en haut à droite) — puis chacun des autres angles
+ a deux états, atteint ou non. Quelques détails :
+
+
+ Par exemple le point en bas à droite concerne
+ les valeurs entre 25% et 50% : si la valeur est inférieure à 25%, il doit
+ être au centre (pour ne pas gêner le tracé), et dans le cas contraire être
+ dans son coin. ce qui s’exprime ainsi :
+ calc( 50% + ( var(--gt-25, 0) * 50% ) ) calc( 50% + ( var(--gt-25, 0) * 50% ) )
+ Ainsi la valeur calculée sera 50% 50% si --gt-25 vaut 0,
+ et 100% 100% si --gt-25 vaut 1.
+
+
+ De plus, chaque angle a sa coordonnée cible :
+ 100% 100% pour en bas à droite, 0% 100% pour en bas à gauche,
+ 0% 0% pour en haut à gauche. Il faut donc tantôt soustraire et
+ tantôt ajouter 50% à la valeur intitiale 50% 50%
+ pour basculer sur le bon point.
+
+
+
+
+ Un point pour chaque position possible par quart de cercle, correspondant à
+ chaque tranche de 25%. À l’instar des points aux angles, ces points doivent être au centre
+ s’ils ne sont pas utilisés. C’est là qu’on rigole le plus :
+
+
on part de 50%, auxquels on ajoute ou soustrait la suite du calcul ;
+
+ on utilise enfinla position calculée — --pos-A
+ ou --pos-B selon le cas — qu’on convertit en pourcentages à l’aide de
+ * 1%, et qu’on rend inerte si la valeur est inférieure à la tranche concernée
+ grâce à * var(--lt-25, 1), par exemple.
+
+ Remarquez le seconde valeur dans var(), qui est la valeur par défaut
+ si la variable n’est pas définie. Cool, non ?
+
+
+
+ et finalement lorsque la tranche est dépassée, le point bascule vers
+ 0% ou 100% selon le cas.
+
+
+
+
+ Et enfin, on referme le tracé en revenant au centre du cercle,
+ à 50% 50%.
+
+
+
C’est tout !
+
Les positions illustrées
+
+ Ces captures d’écran — effectuées dans
+ l’éditeur
+ de formes
+ des outils de développement de Firefox —
+ montrent les points du polygone dans les différents cas. Vous pouvez consulter pour chaque valeur citée
+ le polygone résolu pour clip-path — et constater le basculement des valeurs dynamiques d’une
+ position à une autre.
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Répartition du poids des ressources pour ffoodd.fr
+
+
+
+
Ressource
+
Proportion
+
+
+
+
+
HTML
+
+ 2 %
+
+
+
+
CSS
+
+ 2 %
+
+
+
+
JS
+
+ 32 %
+
+
+
+
Json
+
+ 1 %
+
+
+
+
Images
+
+ 44 %
+
+
+
+
Webfonts
+
+ 17 %
+
+
+
+
Autres
+
+ 2 %
+
+
+
+
+
+
+
+ Le css
+
.chaarts.donut {
--mask: radial-gradient(
circle at 50% calc(50% - .25rem),
transparent 0 var(--offset),
@@ -897,124 +832,103 @@
Donut
--away: calc( var(--radius) / 2 - 2.5rem );
}
-
-
-
-
Dégradé conique
-
- L’utilisation de conic-gradient() est prometteuse pour ce cas précis.
- Vous en trouverez des exemples réalisés par Ana Tudor ou Léa Verou — qui a carrément rédigé la spécification,
- et conçu un polyfill.
- Cependant le support limité aux navigateurs basés sur WebKit est déprimant, et pose tout de même quelques questions
- en matière d’accessibilité puisqu’on ne peut pas affecter un motif à chaque couleur du dégradé conique.
-
-
-
-
Polaire
-
-
- Pour cette déclinaison, on ne change presque rien : seulement la variable --zoom
- et son implication dans la mise à l’échelle des portions à l’aide de scale().
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
-
Répartition du poids des ressources pour ffoodd.fr
-
-
-
Ressource
-
Proportion
-
-
-
-
-
-
HTML
-
-
-
-
- 2 %
-
-
-
-
-
CSS
-
-
-
-
- 2 %
-
-
-
-
-
JS
-
-
-
-
- 32 %
-
-
-
-
-
Json
-
-
-
-
- 1 %
-
-
-
-
-
Images
-
-
-
-
- 44 %
-
-
-
-
-
Webfonts
-
-
-
-
- 17 %
-
-
-
-
-
Autres
-
-
-
-
- 2 %
-
-
-
-
-
-
-
- Le css
-
.chaarts.polar td::before {
+
+
+
+
Dégradé conique
+
+ L’utilisation de conic-gradient() est prometteuse pour ce cas précis.
+ Vous en trouverez des exemples réalisés par Ana Tudor ou Léa Verou — qui a
+ carrément rédigé la spécification,
+ et conçu un polyfill.
+ Cependant le support limité aux navigateurs
+ basés sur WebKit est déprimant, et pose tout de même quelques questions
+ en matière d’accessibilité puisqu’on ne peut pas affecter un motif à chaque couleur du dégradé
+ conique.
+
+
+
+
Polaire
+
+
+ Pour cette déclinaison, on ne change presque rien : seulement la variable --zoom
+ et son implication dans la mise à l’échelle des portions à l’aide de scale().
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Répartition du poids des ressources pour ffoodd.fr
+
- In order to have two values for each main column, we must also have
- two subheadings. Concretely speaking:
-
-
-
-
- we add a second row in <thead>:
-
-
- with two column header cells <th scope="col">
- for each column header cell in the first row;
-
-
- remember to add colspan="2" on the first row's header cell
- to match the new table layout;
-
-
- and finally add an identifier to each header cell
- to referenced them to the relevant data cells — using the
- headers attribute, par exemple pour la première cellule:
- headers="browser chrome year chrome-2018" where each value
- is a header cell's identifier.
-
-
-
-
- Styles:
-
-
- the first-level header cells must span two columns of the grid,
- as required by their colspan for the table layout. It is
- unfortunately impossible to use an attribute value in another
- property than content — otherwise we could simply write
- grid-column: 2 / span attr(colspan);, and that would be awesome…
-
-
- but no! Thus, a --span custom property is added on <table>,
- and must match the colspan attributes values mentionned earlier:
- it is therefore used to extend the first level headers to the appropriate number of columns.
-
-
- Colors and patterns are no longer applied according to each value,
- but according to each column — in the example, every second element
- (since we have two entries per column).
- Again, if we could use an attribute value or a custom property
- in a selector, that would be great. Imagine
- tbody td:nth-of-type(var(--span)n + var(--span)) or even
- tbody td:nth-of-type(attr(colspan)n + attr(colspan))!
-
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
+ In order to have two values for each main column, we must also have
+ two subheadings. Concretely speaking:
+
+
+
+
+ we add a second row in <thead>:
+
+
+ with two column header cells <th scope="col">
+ for each column header cell in the first row;
+
+
+ remember to add colspan="2" on the first row's header cell
+ to match the new table layout;
+
+
+ and finally add an identifier to each header cell
+ to referenced them to the relevant data cells — using the
+ headers attribute, par exemple pour la première cellule:
+ headers="browser chrome year chrome-2018" where each value
+ is a header cell's identifier.
+
+
+
+
+ Styles:
+
+
+ the first-level header cells must span two columns of the grid,
+ as required by their colspan for the table layout. It is
+ unfortunately impossible to use an attribute value in another
+ property than content — otherwise we could simply write
+ grid-column: 2 / span attr(colspan);, and that would be awesome…
+
+
+ but no! Thus, a --span custom property is added on <table>,
+ and must match the colspan attributes values mentionned earlier:
+ it is therefore used to extend the first level headers to the appropriate number of columns.
+
+
+ Colors and patterns are no longer applied according to each value,
+ but according to each column — in the example, every second element
+ (since we have two entries per column).
+ Again, if we could use an attribute value or a custom property
+ in a selector, that would be great. Imagine
+ tbody td:nth-of-type(var(--span)n + var(--span)) or even
+ tbody td:nth-of-type(attr(colspan)n + attr(colspan))!
+
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
- Ce graphique repose sur les variables CSS, les grilles et clip-path.
- Cette dernière propriété est la plus importante.
-
-
-
-
- Sur le tableau, les échelles et l’unité sont indiquées :
-
-
- --y définit l’échelle des ordonnées, utilisée
- pour indiquer l’échelle en arrière-plan mais aussi placer
- les points sur la courbe ;
-
-
- --x correspond à l’échelle des abscisses, exprimée
- simplement comme le nombre de colonnes à afficher ;
-
-
--unit permet de définir l’unité à afficher dans l’infobulle simulée.
-
-
-
- Chaque ligne <tr> dans <tbody> porte une palanquée
- de variables, correspondant à toutes les valeurs qu’elle contient.
- Dans un pseudo-élément ::before, une position est définie pour chaque valeur
- au sein de la fonction polygon() de clip-path.
-
-
- Étant donné que cette fonction accepte deux valeurs en pourcentage
- chaque point, la méthode est relativement simple.
- La position en abscisse est le nombre de colonnes (le décalage depuis la gauche, donc)
- et la position en ordonnée est le ratio de la valeur sur l’échelle, le tout formulé ainsi :
- calc( ( 100% / var(--x) * 1 ) + var(--offset) ) calc( 100% - ( var(--1) / var(--y) * 100% ) ),
- où * 1 et var(--1) correspondent à l’index de la valeur dans l’ensemble,
- et var(--offset) est la valeur d’une demi-colonne, pour placer le point au milieu
- de sa colonne.
-
-
- Vous l’aurez peut-être compris, le principal écueil de ce graphique est qu’il
- nécessite de connaître le nombre de points par avance.
-
- Chaque cellule <td> dans <tbody> porte un pseudo-élément
- ::after qui sert à récapituler ses entêtes et valeur dans
- une infobulle simulée, et un pseudo-élément ::before pour gérer un calque interactif sur la cellule :
-
Et finalement la propriété personnalisée --unit sert de finition.
-
-
-
- Tout le reste n’est que décoration :
-
-
- un padding-top important sur le tableau pour
- réserver l’espace d’affichage des graphiques — attention :
- il est nécessaire d’appliquer border-collapse: separate; sur le tableau
- afin que le padding ait un impact ;
-
-
le ::before de chaque ligne est étiré afin d’occuper tout l’espace réservé ;
-
un arrière-plan dégradé pour représenter la surface pleine du même ::before ;
-
- un repeating-linear-gradient() pour représenter l’échelle verticale,
- en arrière-plan du tableau ;
-
-
- et des interactions au survol pour mettre en exergue la valeur survolée :
- sa colonne à l’aide d’un pseudo-élément — positionné à l’aide de de savants calculs —
- et mix-blend-mode pour un effet waouh.
-
-
-
-
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
+ Chaque cellule <td> dans <tbody> porte un pseudo-élément
+ ::after qui sert à récapituler ses entêtes et valeur dans
+ une infobulle simulée, et un pseudo-élément ::before pour gérer un calque interactif sur la cellule :
+
Et finalement la propriété personnalisée --unit sert de finition.
+
+
+
+ Tout le reste n’est que décoration :
+
+
+ un padding-top important sur le tableau pour
+ réserver l’espace d’affichage des graphiques — attention :
+ il est nécessaire d’appliquer border-collapse: separate; sur le tableau
+ afin que le padding ait un impact ;
+
+
le ::before de chaque ligne est étiré afin d’occuper tout l’espace réservé ;
+
un arrière-plan dégradé pour représenter la surface pleine du même ::before ;
+
+ un repeating-linear-gradient() pour représenter l’échelle verticale,
+ en arrière-plan du tableau ;
+
+
+ et des interactions au survol pour mettre en exergue la valeur survolée :
+ sa colonne à l’aide d’un pseudo-élément — positionné à l’aide de de savants calculs —
+ et mix-blend-mode pour un effet waouh.
+
+
+
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
- Pour commencer, il faut bien intégrer que clip-path est un tracé,
- au même titre qu’une forme vectorielle. Il doit donc être fermé.
- Ainsi le tracé démarre à 0% 100% — en bas à gauche, fait sa vie
- de tracé, bascule à 100% 100% et revient boucler à 0% 100%.
-
-
Et dans son chemin, chaque point doit être positionné en abscisses et en ordonnées.
-
La position en abscisse
-
- La première position est simple : on divise 100% par l’échelle
- var(--x), et on multiplie par l’index de l’élément. Par exemple :
- calc( ( 100% / var(--x) * 1) ).
- Pour placer chaque point au milieu de sa colonne, on le décale d’une demi-colonne
- — ce que l’on fait en ajoutant au calcul précédent var(--offset), qui correspond
- à calc( ( 100% / var(--x) ) / 2 ).
- La position finale est donc, ici pour le troisième point :
- calc( ( 100% / var(--x) * 3) + var(--offset) ).
-
-
La position en ordonnée
-
- Dans ce graphique, l’ordonnée est l’axe le plus important. Ainsi pour placer le point,
- on commence par calculer le ratio de sa valeur sur l’échelle — formulé
- ainsi : var(--1) / var(--y). Et parce que polygon() utilise
- des valeurs en pourcentage, on rapporte ce calcul sur 100% :
- ( var(--1) / var(--y) * 100% ).
- Et pour finir, les référentiels du polygone partant d’en haut à gauche, la position
- doit être définie en fonction du haut de la boîte. La formule finale ressemble
- alors à ça — toujours pour le troisième élément :
- calc( 100% - ( var(--3) / var(--y) * 100% ) ).
-
-
-
-
Graphique à point
-
-
Cette variante diffère finalement assez peu de la précédente mouture :
-
-
-
- le polygon() est poursuivi pour former une ligne,
- en dupliquant chaque point avec un décalage de 4px
- — l’épaisseur du trait — et dans l’ordre inverse ;
-
-
- le pseudo-élément ::before qui permet d’afficher l’infobulle prend ici la forme d’un
- point sur la courbe — positionné à l’aide des mêmes calculs qui servent dans le polygone ;
-
-
- et surtout, puisque clip-path est appliqué sur la ligne
- <tr> : vous pouvez en mettre plusieurs !
- Il nous faut donc ajouter une combinaison de couleur et motif pour distinguer chaque ligne
- et les associer visuellement à leur légende.
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
- la fonction repeat() appliquée avec la variable --scale
- permet de gérer une échelle dynamique ;
-
-
- les conteneurs <thead>, <tbody> et <tr>
- sont neutralisés dans la gestion de la grille à l’aide de display: contents ;
-
- chaque cellule est placée sur la grille en fonction de --value
- — sa valeur, donc — sa couleur d’arrière-plan dépend également de
- sa valeur ;
-
-
- et finalement la valeur textuelle — contenue dans un élément
- <span> — est positionnée en haut de la colonne
- à l’aide de la même astuce que dans le graphique en barre.
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
-
Parts de marché navigateurs en France en janvier 2019
+ la fonction repeat() appliquée avec la variable --scale
+ permet de gérer une échelle dynamique ;
+
+
+ les conteneurs <thead>, <tbody> et <tr>
+ sont neutralisés dans la gestion de la grille à l’aide de display: contents ;
+
+
+ chaque cellule est placée sur la grille en fonction de --value
+ — sa valeur, donc — sa couleur d’arrière-plan dépend également de
+ sa valeur ;
+
+
+ et finalement la valeur textuelle — contenue dans un élément
+ <span> — est positionnée en haut de la colonne
+ à l’aide de la même astuce que dans le graphique en barre.
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Parts de marché navigateurs en France en janvier 2019
- Pour disposer de deux valeurs pour chaque colonne principale, nous devons également
- disposer de deux sous-titres.
- Concrètement parlant :
-
-
-
-
- on ajoute une seconde ligne dans l’entête<thead> :
-
-
- avec deux cellules d’entête de colonne <th scope="col">
- pour chaque cellule d’entête de colonne dans la première ligne d’entête ;
-
-
- n’oublions pas d’ajouter un colspan="2" sur les cellules d’entête de
- la première ligne pour faire correspondre la structure du tableau ;
-
-
- et enfin ajouter un identifiant à chaque cellule d’entête
- afin de les référencer sur les cellules de données concernées — à l’aide
- de l’attribut headers, par exemple pour la première cellule :
- headers="navigateur chrome annee chrome-2018" où chaque valeur est un
- identifiant de cellule d’entête.
-
-
-
-
- Côté styles :
-
-
- les cellules d’entête de premier niveau doivent s’étendre sur deux colonnes de la grille,
- comme le réclame leur attribut colspan pour la structure du tableau. Il est
- malheureusement impossible d’utiliser la valeur d’un attribut dans une autre
- propriété que content — sinon nous pourrions simplement écrire
- grid-column: 2 / span attr(colspan); et ça serait magnifique…
-
-
- mais non ! Ainsi, une variable --span est ajoutée sur <table>,
- et doit correspondre à la valeur des attributs colspan cités plus tôt :
- elle sert donc à étendre les entêtes de premier niveau sur le nombre de colonnes adéquat.
-
-
- les couleurs et motifs ne sont plus appliqués en fonction
- de chaque valeur, mais en fonction de chaque colonne — dans l’exemple, un élément
- sur deux (puisque nous avons deux entrées par colonne).
- Là aussi, si nous pouvions utiliser une valeur d’attribut ou une propriété personnalisée
- dans un sélecteur, ce serait génial. Imaginez un peu
- tbody td:nth-of-type(var(--span)n + var(--span)) ou encore
- tbody td:nth-of-type(attr(colspan)n + attr(colspan)) !
-
-
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
-
Parts de marché navigateurs en France en janvier 2019
+ Pour disposer de deux valeurs pour chaque colonne principale, nous devons également
+ disposer de deux sous-titres.
+ Concrètement parlant :
+
+
+
+
+ on ajoute une seconde ligne dans l’entête<thead> :
+
+
+ avec deux cellules d’entête de colonne <th scope="col">
+ pour chaque cellule d’entête de colonne dans la première ligne d’entête ;
+
+
+ n’oublions pas d’ajouter un colspan="2" sur les cellules d’entête de
+ la première ligne pour faire correspondre la structure du tableau ;
+
+
+ et enfin ajouter un identifiant à chaque cellule d’entête
+ afin de les référencer sur les cellules de données concernées — à l’aide
+ de l’attribut headers, par exemple pour la première cellule :
+ headers="navigateur chrome annee chrome-2018" où chaque valeur est un
+ identifiant de cellule d’entête.
+
+
+
+
+ Côté styles :
+
+
+ les cellules d’entête de premier niveau doivent s’étendre sur deux colonnes de la grille,
+ comme le réclame leur attribut colspan pour la structure du tableau. Il est
+ malheureusement impossible d’utiliser la valeur d’un attribut dans une autre
+ propriété que content — sinon nous pourrions simplement écrire
+ grid-column: 2 / span attr(colspan); et ça serait magnifique…
+
+
+ mais non ! Ainsi, une variable --span est ajoutée sur <table>,
+ et doit correspondre à la valeur des attributs colspan cités plus tôt :
+ elle sert donc à étendre les entêtes de premier niveau sur le nombre de colonnes adéquat.
+
+
+ les couleurs et motifs ne sont plus appliqués en fonction
+ de chaque valeur, mais en fonction de chaque colonne — dans l’exemple, un élément
+ sur deux (puisque nous avons deux entrées par colonne).
+ Là aussi, si nous pouvions utiliser une valeur d’attribut ou une propriété personnalisée
+ dans un sélecteur, ce serait génial. Imaginez un peu
+ tbody td:nth-of-type(var(--span)n + var(--span)) ou encore
+ tbody td:nth-of-type(attr(colspan)n + attr(colspan)) !
+
+
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
+
+
+
+
+
Parts de marché navigateurs en France en janvier 2019
- Every charts in this project relies solely on semantic markup
- — <table> based — and a spread of
- CSS variables carried by the tags.
- No JavaScript required for display, and styles are
- progressively enhanced depending on your browser's capabilities.
-
-
-
- Note : by virtue of the experimental
- nature of these techniques and a solid foundation enhanced progressively,
- I don't mention browser support for each example — but
- it goes without saying that this is not magic, and only modern browsers handle this right,
- with the notable exception of Edge
- which does not (yet) support clip-path.
- Other browsers display a properly styled table, and that's nice.
-
-
-
Accessibility
-
-
- A major effort has been made to ensure accessibility.
- As mentioned above, semantic and structured markup is a prerequisite
- — but it's not enough. CSS
- is being applied as gradually as possible, in order to guarantee
- the best possible display of data for each user.
-
-
-
Accessible table
-
-
Wakeup call :
-
-
-
a table must start with a <caption>;
-
- header cells <th> must carry a scope attribute,
- with a row or col value;
-
-
- and you'll usually need to distinguish the head from the body through
- <thead> and <tbody>;
-
-
- for values with a unit : if you venture to use the
- <abbr> element to use its abbreviated version, consider doubling the
- title with the aria-label attribute — this will considerably
- improve the interest for many users.
-
- To distinguish the different areas other than by colour, an
- svg
- pattern is applied in
- css
- — you can find some of them on the
- Hero Patterns website:
-
-
-
- in order to improve blending with background colors or gradients, the
- background-blend-mode proerty is used with the hard-light value;
-
-
- pattern's size and position depends directly on the value and scale of the chart,
- depending on the type of chart;
-
+ Every charts in this project relies solely on semantic markup
+ — <table> based — and a spread of
+ CSS variables carried by the tags.
+ No JavaScript required for display, and styles are
+ progressively enhanced depending on your browser's capabilities.
+
+
+
+ Note : by virtue of the experimental
+ nature of these techniques and a solid foundation enhanced progressively,
+ I don't mention browser support for each example — but
+ it goes without saying that this is not magic, and only modern browsers handle this right,
+ with the notable exception of Edge
+ which does not (yet) support clip-path.
+ Other browsers display a properly styled table, and that's nice.
+
+
+
Accessibility
+
+
+ A major effort has been made to ensure accessibility.
+ As mentioned above, semantic and structured markup is a prerequisite
+ — but it's not enough. CSS
+ is being applied as gradually as possible, in order to guarantee
+ the best possible display of data for each user.
+
+
+
Accessible table
+
+
Wakeup call :
+
+
+
a table must start with a <caption>;
+
+ header cells <th> must carry a scope attribute,
+ with a row or col value;
+
+
+ and you'll usually need to distinguish the head from the body through
+ <thead> and <tbody>;
+
+
+ for values with a unit : if you venture to use the
+ <abbr> element to use its abbreviated version, consider doubling the
+ title with the aria-label attribute — this will considerably
+ improve the interest for many users.
+
+ To distinguish the different areas other than by colour, an
+ svg
+ pattern is applied in
+ css
+ — you can find some of them on the
+ Hero Patterns website:
+
+
+
+ in order to improve blending with background colors or gradients, the
+ background-blend-mode proerty is used with the hard-light value;
+
+
+ pattern's size and position depends directly on the value and scale of the chart,
+ depending on the type of chart;
+
- In order to respect as much as possible the preferences of the visitors,
- many elements have been adapted:
-
-
-
- dimensions are in relatives units (em or rem as the case may be),
- in order to fit coherently with the body of text inherited from the browser and to be able
- to be enlarged or reduced without loss;
-
- animations and transitions are disabled when the system exposes
- this preference through prefers-reduced-motion: reduce ;
-
-
- hover effects whose initial state consists in hiding content
- are activated contextually in the @media (hover: hover) { … } media query.
-
-
-
-
display and semantics
-
- Adrian Roselli explains that playing with a <table> or <dl>
- element's display endangers its semantics.
- The latter is therefoore "locked" using dedicated
- aria
- roles — as he explains
- in a detailed article.
-
+ In order to respect as much as possible the preferences of the visitors,
+ many elements have been adapted:
+
+
+
+ dimensions are in relatives units (em or rem as the case may be),
+ in order to fit coherently with the body of text inherited from the browser and to be able
+ to be enlarged or reduced without loss;
+
+ animations and transitions are disabled when the system exposes
+ this preference through prefers-reduced-motion: reduce ;
+
+
+ hover effects whose initial state consists in hiding content
+ are activated contextually in the @media (hover: hover) { … } media query.
+
+
+
+
display and semantics
+
+ Adrian Roselli explains that playing with a <table> or <dl>
+ element's display endangers its semantics.
+ The latter is therefoore "locked" using dedicated
+ aria
+ roles — as he explains
+ in a detailed article.
+
- This chart is based on CSS custom properties, grids and clip-path
- — the latter being the most important.
-
-
-
-
- Scales are set on the table:
-
-
- --y defines the y-axis scale, used to indicate the scale
- in the background but also to place the points on the curve;
-
-
- --x is the x-axis scale,
- simply expressed as the number of columns to display;
-
-
--unit defines unit to be displayed in simulated tooltip (see below).
-
-
-
- Each line <tr> in <tbody> carries a set of variables,
- corresponding to all the values it contains.
- In a ::before pseudo-element, a position is defined for each value
- within the clip-pathpolygon() function.
-
-
- Since this function accepts two percentage values at each point,
- the method is pretty straightforward.
- The x-axis position is the number of columns (i.e., the offset from the left) and
- the y-axis position is the ratio of the value on the scale, formulated as follows:
- calc( ( 100% / var(--x) * 1 ) + var(--offset) ) calc( 100% - ( var(--1) / var(--y) * 100% ) ),
- where * 1 and var(--1) is the index of the value as a whole,
- and var(--offset) is the value of half a column,
- to place the point in the middle of its column.
-
-
- As you may have understood, the main pitfall of this graph is
- that it requires to know the number of points in advance.
-
- Each cell <td> in <tbody> carries an
- ::after pseudo-element used to summarize
- its headers and value in a simulated tooltip, and a ::before pseudo-element
- to manage an interactive layer on the cell:
-
- a big padding-top on the table is used to reserve space
- for the charts — caution:
- it is necessary to apply border-collapse: separate; on the table
- for the padding to have an impact;
-
-
each line's ::before is stretched in order to occupy all the reserved space;
-
a gradient background to represent the full area of the same ::before;
-
- a repeating-linear-gradient() to represent the vertical scale
- in the table's background;
-
-
- and hover interactions to highlight the hovered value:
- its column using a pseudo-element — positioned with the help of clever calculations —
- and mix-blend-mode for a wow effect.
-
-
-
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
+ Each cell <td> in <tbody> carries an
+ ::after pseudo-element used to summarize
+ its headers and value in a simulated tooltip, and a ::before pseudo-element
+ to manage an interactive layer on the cell:
+
+ a big padding-top on the table is used to reserve space
+ for the charts — caution:
+ it is necessary to apply border-collapse: separate; on the table
+ for the padding to have an impact;
+
+
each line's ::before is stretched in order to occupy all the reserved space;
+
a gradient background to represent the full area of the same ::before;
+
+ a repeating-linear-gradient() to represent the vertical scale
+ in the table's background;
+
+
+ and hover interactions to highlight the hovered value:
+ its column using a pseudo-element — positioned with the help of clever calculations —
+ and mix-blend-mode for a wow effect.
+
+
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
- To begin with, you need to understand that clip-path is a path,
- just like a vector shape. It must therefore be closed.
- So the path starts at 0% 100% — bottom left, does its path life,
- toggles to 100% 100% and comes back looping at 0% 100%.
-
-
And in its path, each point must be positioned in abscissa and ordinate.
-
The X-axis position
-
- The first position is simple: divide 100% by the
- var(--x) scale, and multiply by the index of the element.
- For example: calc( ( 100% / var(--x) * 1) ).
- To place each point in the middle of its column, we shift it by half a column
- — which we do by adding to the previous calculation var(--offset),
- which corresponds to calc( ( 100% / var(--x) ) / 2 ).
- The final position is therefore, here for the third point:
- calc( ( 100% / var(--x) * 3) + var(--offset) ).
-
-
The Y-axis position
-
- In this graph, the Y-axis is the most important axis. So to place the point,
- we start by calculating the ratio of its value on the scale
- — formulated as follows: var(--1) / var(--y). And because
- polygon() uses percentage values, we report this calculation on 100%:
- ( var(--1) / var(--y) * 100% ).
- And finally, since the polygon's datums start from the top left, the position
- position must be defined according to the top of the box.
- The final formula then looks like this — again for the third element:
- calc( 100% - ( var(--3) / var(--y) * 100% ) ).
-
-
-
-
-
Line chart with dots
-
-
In the end, this variant differs little from the previous version:
-
-
-
- the polygon() is continued to form a line,
- duplicating each point with an offset of 4px
- — the line thickness — and in the reverse order;
-
-
- the ::before pseudo-element that displays the tooltip takes
- here the form of a point on the curve
- — positioned using the same calculations that are used in the polygon;
-
-
- and especially, since clip-path is applied in the line
- <tr>: you can put more than one !
- So we need to add a combination of color and pattern to distinguish each line
- and associate them visually with their caption.
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
- The pie chart is used for representations of percentage proportions.
- It relies on CSS variables, an outrageous abuse of calc(),
- display: table-*, clip-path, mask-image,
- transform and a bit of SVG
- to distinguish each area. Yes, I know how to laugh. How do we use it?
-
-
-
-
- On each header<th>, a --color
- custom property allows you to assign, well… a color.
-
-
- Then each cell<td> must contain the value
- and its unit, as well as a style attribute to carry some variables:
-
-
- --value is the percentage value,
- useful for determining the angle the element should occupy on the circle.
- All points of the polygon() — used to draw the pie part thanks to clip-path —
- depend on this value (read the technical note after
- the example for details of the calculations).
-
-
- --start is used to define the starting point
- of the arc on the circle. It's the sum of the previous definitions, and is applied
- to the rotate() function of the transform poperty.
-
-
- And finally a series of pseudo-boolean variables, each worthing 0 or 1
- — according to and idea of
- Roman Komarov in "Conditions for CSS variables" —
- depend on the value: --lt-25, --gt-25, --lt-50…
- They allow to toggle the points from their original position
- (50% 50%) to their calculated position, by adding or subtracting from the initial value;
-
-
-
-
- a ::beforepseudo-element on each cell <td>is formatted
- in a clever way according to all our variables, including transform,
- clip-path and mask-image.
-
- a ::afterpseudo-element is used as a tooltip, to summarize header and value for each cell
- —but the display of custom properties in a pseudo-element is not so trivial:
-
-
- content only accepts strings, and our custom properties contains… number.
-
- And finally a pattern is applied to the background,
- in order to better associate it visually with the corresponding legend.
-
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Distribution of the weight of resources for ffoodd.fr
-
-
-
Resource
-
Proportion
-
-
-
-
-
-
HTML
-
-
-
-
- 2 %
-
-
-
-
-
CSS
-
-
-
-
- 2 %
-
-
-
-
-
JS
-
-
-
-
- 32 %
-
-
-
-
-
Json
-
-
-
-
- 1 %
-
-
-
-
-
Images
-
-
-
-
- 44 %
-
-
-
-
-
Webfonts
-
-
-
-
- 17 %
-
-
-
-
-
Other
-
-
-
-
- 2 %
-
-
-
-
-
-
-
- A bit of trigonometry
-
-
- In this graph, each portion represents an arc of a circle based on an angle (part of 360 degrees).
- To define the shape of this portion, a point must be placed on the circle.
-
-
- To do this, I divide the circle into four squares. The position of the point on the circle
- can then be calculated using the properties of the right-angled triangle formed by:
-
-
-
the center of the circle,
-
the point we're trying to position,
-
and the point perpendicular to the radius and passing through our target point.
-
-
- We know the hypotenuse of this triangle — the radius of the circle —,
- and the angle formed by the hypotenuse and starting from the center of the circle
- (reducing the value to 90 degrees, since the circle is divided into four square sectors:
- if the value is greater than 25: minus 90°, etc.)
- — plus a right angle, of course.
-
+ The pie chart is used for representations of percentage proportions.
+ It relies on CSS variables, an outrageous abuse of calc(),
+ display: table-*, clip-path, mask-image,
+ transform and a bit of SVG
+ to distinguish each area. Yes, I know how to laugh. How do we use it?
+
+
+
+
+ On each header<th>, a --color
+ custom property allows you to assign, well… a color.
+
+
+ Then each cell<td> must contain the value
+ and its unit, as well as a style attribute to carry some variables:
+
+
+ --value is the percentage value,
+ useful for determining the angle the element should occupy on the circle.
+ All points of the polygon() — used to draw the pie part thanks to clip-path —
+ depend on this value (read the technical note after
+ the example for details of the calculations).
+
+
+ --start is used to define the starting point
+ of the arc on the circle. It's the sum of the previous definitions, and is applied
+ to the rotate() function of the transform poperty.
+
+
+ And finally a series of pseudo-boolean variables, each worthing 0 or 1
+ — according to and idea of
+ Roman Komarov in "Conditions for CSS variables" —
+ depend on the value: --lt-25, --gt-25, --lt-50…
+ They allow to toggle the points from their original position
+ (50% 50%) to their calculated position, by adding or subtracting from the initial value;
+
+
+
+
+ a ::beforepseudo-element on each cell <td>is formatted
+ in a clever way according to all our variables, including transform,
+ clip-path and mask-image.
+
+ a ::afterpseudo-element is used as a tooltip, to summarize header and value for
+ each cell
+ —but the display of custom properties in a pseudo-element is not so trivial:
+
+
+ content only accepts strings, and our custom properties contains… number.
+
+ And finally a pattern is applied to the background,
+ in order to better associate it visually with the corresponding legend.
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
+ Distribution of the weight of resources for
+ ffoodd.fr
+
+
+
+
Resource
+
Proportion
+
+
+
+
+
HTML
+
+ 2 %
+
+
+
+
CSS
+
+ 2 %
+
+
+
+
JS
+
+ 32 %
+
+
+
+
Json
+
+ 1 %
+
+
+
+
Images
+
+ 44 %
+
+
+
+
Webfonts
+
+ 17 %
+
+
+
+
Other
+
+ 2 %
+
+
+
+
+
+
+
+ A bit of trigonometry
+
+
+ In this graph, each portion represents an arc of a circle based on an angle (part of 360 degrees).
+ To define the shape of this portion, a point must be placed on the circle.
+
+
+ To do this, I divide the circle into four squares. The position of the point on the circle
+ can then be calculated using the properties of the right-angled triangle formed by:
+
+
+
the center of the circle,
+
the point we're trying to position,
+
and the point perpendicular to the radius and passing through our target point.
+
+
+ We know the hypotenuse of this triangle — the radius of the circle —,
+ and the angle formed by the hypotenuse and starting from the center of the circle
+ (reducing the value to 90 degrees, since the circle is divided into four square sectors:
+ if the value is greater than 25: minus 90°, etc.)
+ — plus a right angle, of course.
+
- The use of pseudo-Boolean variables makes this calculation pseudo-algorithmic.
- Let's start with an essential pre-requisite: the polygon being a closed shape and CSS
- not being magical, points must pre-exist.
- Spoiler, we need eleven points:
-
-
-
- The initial axis, from centre upwards: 50% 50%
- and 50% 0%.
-
-
- One point for each angle at the ends: the first one is fixed, at
- 100% 0% (top right) — then each of the other angles has
- two states, reached or not reached. Some insights:
-
-
- For example, the point at the bottom right concerns values between 25% and 50%:
- if the value is less than 25%, it must be in the centre (so as not to interfere
- with the drawing), and if not, it must be in its corner:
- calc( 50% + ( var(--gt-25, 0) * 50% ) ) calc( 50% + ( var(--gt-25, 0) * 50% ) )
- Thus the calculated value will be 50% 50% if --gt-25 is 0,
- and 100% 100% if --gt-25 is 1.
-
-
- In addition, each angle has its target coordinate:
- 100% 100% for bottom right, 0% 100% for bottom left,
- 0% 0% for top left. It is therefore necessary to sometimes subtract
- and sometimes add to the initial value 50% 50%
- to switch to the right point.
-
-
-
-
- One point for each possible position per quarter circle, corresponding
- to each 25% slice. Like the points at the corners, these points must be in the centre
- if they are not used. That's where we laugh the most:
-
-
we start from 50%, to which we add or subtract the following calculation;
-
- then the calculated position is used — --pos-A
- or --pos-B as the case may be — which is converted into percentages using
- * 1%, and rendered inert if the value is less than the range concerned
- using * var(--lt-25, 1), for example.
-
- Notice the second value in var()?
- This is the default value if the variable is not defined. Cool, isn't it?
-
-
-
- finally when the range is exceeded, the point switches to
- 0% or 100% as appropriate.
-
-
-
-
- And lastly, we lose the path by going back to the centre of the circle,
- at 50% 50%.
-
-
-
That's it!
-
The positions illustrated
-
- These screenshots — taken in
- the shape editor of the
- Firefox devtools —
- show the points of the polygon in the different cases.
- You can see for each cited value the resolved polygon for clip-path
- — and see how the dynamic values tilt from one position to another.
-
-
-
-
- Rendering example for 44%
-
-
-
- Shape screenshot for 44%.
-
-
-
td[style*="--value: 44;"]::before {
+
+
+
+
+ The calculation twist
+
The positions of the polygon
+
+ The use of pseudo-Boolean variables makes this calculation pseudo-algorithmic.
+ Let's start with an essential pre-requisite: the polygon being a closed shape and CSS
+ not being magical, points must pre-exist.
+ Spoiler, we need eleven points:
+
+
+
+ The initial axis, from centre upwards: 50% 50%
+ and 50% 0%.
+
+
+ One point for each angle at the ends: the first one is fixed, at
+ 100% 0% (top right) — then each of the other angles has
+ two states, reached or not reached. Some insights:
+
+
+ For example, the point at the bottom right concerns values between 25% and 50%:
+ if the value is less than 25%, it must be in the centre (so as not to interfere
+ with the drawing), and if not, it must be in its corner:
+ calc( 50% + ( var(--gt-25, 0) * 50% ) ) calc( 50% + ( var(--gt-25, 0) * 50% ) )
+ Thus the calculated value will be 50% 50% if --gt-25 is 0,
+ and 100% 100% if --gt-25 is 1.
+
+
+ In addition, each angle has its target coordinate:
+ 100% 100% for bottom right, 0% 100% for bottom left,
+ 0% 0% for top left. It is therefore necessary to sometimes subtract
+ and sometimes add to the initial value 50% 50%
+ to switch to the right point.
+
+
+
+
+ One point for each possible position per quarter circle, corresponding
+ to each 25% slice. Like the points at the corners, these points must be in the centre
+ if they are not used. That's where we laugh the most:
+
+
we start from 50%, to which we add or subtract the following calculation;
+
+ then the calculated position is used — --pos-A
+ or --pos-B as the case may be — which is converted into percentages using
+ * 1%, and rendered inert if the value is less than the range concerned
+ using * var(--lt-25, 1), for example.
+
+ Notice the second value in var()?
+ This is the default value if the variable is not defined. Cool, isn't it?
+
+
+
+ finally when the range is exceeded, the point switches to
+ 0% or 100% as appropriate.
+
+
+
+
+ And lastly, we lose the path by going back to the centre of the circle,
+ at 50% 50%.
+
+
+
That's it!
+
The positions illustrated
+
+ These screenshots — taken in
+ the shape editor of
+ the
+ Firefox devtools —
+ show the points of the polygon in the different cases.
+ You can see for each cited value the resolved polygon for clip-path
+ — and see how the dynamic values tilt from one position to another.
+
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Pie chart example with a value between 50 and 75%
-
-
-
Resource
-
Proportion
-
-
-
-
-
-
HTML
-
-
-
-
- 2 %
-
-
-
-
-
CSS
-
-
-
-
- 2 %
-
-
-
-
-
JS
-
-
-
-
- 32 %
-
-
-
-
-
Images
-
-
-
-
- 64 %
-
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Pie chart example with a value greater than 75%
-
-
-
Resource
-
Proportion
-
-
-
-
-
-
HTML
-
-
-
-
- 2 %
-
-
-
-
-
CSS
-
-
-
-
- 2 %
-
-
-
-
-
JS
-
-
-
-
- 8 %
-
-
-
-
-
Images
-
-
-
-
- 88 %
-
-
-
-
-
-
-
-
Donut
-
-
- On the <table> element, we add an --offset variable
- that allows us to determine the size of the hole of the donut,
- generated using mask-image and radial-gradient().
- Ana Tudor has made
- many examples of using mask-* on CodePen, have a look!
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Distribution of the weight of resources for ffoodd.fr
-
-
-
Resource
-
Proportion
-
-
-
-
-
-
HTML
-
-
-
-
- 2 %
-
-
-
-
-
CSS
-
-
-
-
- 2 %
-
-
-
-
-
JS
-
-
-
-
- 32 %
-
-
-
-
-
Json
-
-
-
-
- 1 %
-
-
-
-
-
Images
-
-
-
-
- 44 %
-
-
-
-
-
Webfonts
-
-
-
-
- 17 %
-
-
-
-
-
Other
-
-
-
-
- 2 %
-
-
-
-
-
-
-
- css
-
.chaarts.donut {
+ Code generated for 88%.
+
+
+
+
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
Pie chart example with a value between 50 and 75%
+
+
+
Resource
+
Proportion
+
+
+
+
+
HTML
+
+ 2 %
+
+
+
+
CSS
+
+ 2 %
+
+
+
+
JS
+
+ 32 %
+
+
+
+
Images
+
+ 64 %
+
+
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
Pie chart example with a value greater than 75%
+
+
+
Resource
+
Proportion
+
+
+
+
+
HTML
+
+ 2 %
+
+
+
+
CSS
+
+ 2 %
+
+
+
+
JS
+
+ 8 %
+
+
+
+
Images
+
+ 88 %
+
+
+
+
+
+
+
+
Donut
+
+
+ On the <table> element, we add an --offset variable
+ that allows us to determine the size of the hole of the donut,
+ generated using mask-image and radial-gradient().
+ Ana Tudor has made
+ many examples of using mask-* on CodePen, have a look!
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
Distribution of the weight of resources for ffoodd.fr
+
+
+
+
Resource
+
Proportion
+
+
+
+
+
HTML
+
+ 2 %
+
+
+
+
CSS
+
+ 2 %
+
+
+
+
JS
+
+ 32 %
+
+
+
+
Json
+
+ 1 %
+
+
+
+
Images
+
+ 44 %
+
+
+
+
Webfonts
+
+ 17 %
+
+
+
+
Other
+
+ 2 %
+
+
+
+
+
+
+
+ css
+
.chaarts.donut {
--mask: radial-gradient(
circle at 50% calc(50% - .25rem),
transparent 0 var(--offset),
@@ -895,126 +824,103 @@
Donut
--away: calc( var(--radius) / 2 - 2.5rem );
}
-
-
-
-
Conical gradient
-
- The use of conic-gradient() is promising for this case.
- You'll find examples made by Ana Tudor and Léa Verou
- — who actually wrote the specification, and designed
- a polyfill.
- However, current support is limited to WebKit based browsers
- is depressing, and still raises some accessibility issues
- since you can't assign a pattern to each color of the conic-gradient().
-
-
-
-
Polar chart
-
-
- For this variant, wa change almost nothing: only the --zoom variable
- and its implication in the scaling of portions using scale().
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Distribution of the weight of resources for ffoodd.fr
-
-
-
Resource
-
Proportion
-
-
-
-
-
-
HTML
-
-
-
-
- 2 %
-
-
-
-
-
CSS
-
-
-
-
- 2 %
-
-
-
-
-
JS
-
-
-
-
- 32 %
-
-
-
-
-
Json
-
-
-
-
- 1 %
-
-
-
-
-
Images
-
-
-
-
- 44 %
-
-
-
-
-
Webfonts
-
-
-
-
- 17 %
-
-
-
-
-
Other
-
-
-
-
- 2 %
-
-
-
-
-
-
-
- css
-
.chaarts.polar td::before {
+
+
+
+
Conical gradient
+
+ The use of conic-gradient() is promising for this case.
+ You'll find examples made by Ana Tudor and Léa Verou
+ — who actually wrote the specification, and designed
+ a polyfill.
+ However, current support is limited to WebKit based
+ browsers
+ is depressing, and still raises some accessibility issues
+ since you can't assign a pattern to each color of the conic-gradient().
+
+
+
+
Polar chart
+
+
+ For this variant, wa change almost nothing: only the --zoom variable
+ and its implication in the scaling of portions using scale().
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
+
+
+
+
+
Distribution of the weight of resources for ffoodd.fr
+
- This one's kind of fun. We define some CSS
- variables on the table: the scale (and tiers), the number of elements, and the values.
-
-
-
- On the CSS side, it's getting complicated:
-
-
-
-
- on the <table> element, the circular scale is created using two successive
- repeating-radial-gradient() — depending on the
- --scale and --step variables;
-
each one is decorated with a border at the bottom;
-
- then we use again clip-pathpolygon() function
- on each direct child <span> — extended to occupy the whole surface
- of its parent <td> — in order to form a triangle, based for one side
- on the ratio value of the current element / scale, and on another side a ratio based on the
- value of the next element (yum calc())
- — but on another scale…
-
-
- because to compensate for the distortion
- due to the skew() function,
- we need to correct the scale on which the second ratio is calculated
- using a little trigonometry:
-
-
- we know one side of the right-angled triangle obtained after the deformation,
- as well as two angles — the right one, of course, and we deduce
- the second from the angle used to deform the element;
-
-
- so we can calculate the hypothenuse using the sine law,
- — as before in the pie chart;
-
-
- and finally, all we have to do is calculate the ratio between the initial dimension
- — the side — and the final dimension — the hypothenuse —
- and apply this ratio to the scale on which the second point of the polygon is placed.
-
-
-
-
- The third point of the polygon is the bottom right corner, whose coordinates are
- 100% 100%;
-
-
-
- one last trick is necessary to close the shape you have seen,
- we use the current and next value for each element. But when we get to the last element,
- there is no next! So we need to add a value, to which we assign
- the first value — in this example, --8: var(--1);.
-
-
-
-
And that's it!
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
+ This one's kind of fun. We define some CSS
+ variables on the table: the scale (and tiers), the number of elements, and the values.
+
+
+
+ On the CSS side, it's getting complicated:
+
+
+
+
+ on the <table> element, the circular scale is created using two successive
+ repeating-radial-gradient() — depending on the
+ --scale and --step variables;
+
each one is decorated with a border at the bottom;
+
+ then we use again clip-pathpolygon() function
+ on each direct child <span> — extended to occupy the whole surface
+ of its parent <td> — in order to form a triangle, based for one side
+ on the ratio value of the current element / scale, and on another side a ratio based on the
+ value of the next element (yum calc())
+ — but on another scale…
+
+
+ because to compensate for the distortion
+ due to the skew() function,
+ we need to correct the scale on which the second ratio is calculated
+ using a little trigonometry:
+
+
+ we know one side of the right-angled triangle obtained after the deformation,
+ as well as two angles — the right one, of course, and we deduce
+ the second from the angle used to deform the element;
+
+
+ so we can calculate the hypothenuse using the sine law,
+ — as before in the pie chart;
+
+
+ and finally, all we have to do is calculate the ratio between the initial dimension
+ — the side — and the final dimension — the hypothenuse —
+ and apply this ratio to the scale on which the second point of the polygon is placed.
+
+
+
+
+ The third point of the polygon is the bottom right corner, whose coordinates are
+ 100% 100%;
+
+
+
+
+ one last trick is necessary to close the shape you have seen,
+ we use the current and next value for each element. But when we get to the last element,
+ there is no next! So we need to add a value, to which we assign
+ the first value — in this example, --8: var(--1);.
+
+
+
+
And that's it!
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
- There is currently a bug in Chromium — I filled
- an issue on bugs.chromium.org —
- when using the border-spacing property on the table:
- it prevents Chrome to define the dimensions of the table…
- For Chrome user, use the inspector to uncheck this property on the
- <table> tag of these examples!
-
-
Reduced test case
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
Very few changes compared to the previous version:
-
-
-
- the <table> element no longer carries the values,
- but has a new --areas custom property to indicate the number of rows in the table;
-
-
- however we multiply the number of rows in the body of the table:
-
-
- each one carries several variables:
- --color then the values — --1, etc.;
-
-
- and contains several cells: a <th scope="row"> row header cell
- and <td> data cells;
-
-
-
- the rest is relatively common now — if you've gone through the previous examples:
-
-
- a color for each row, presented on the header cells
- and serving as a background for the data cells;
-
-
- a distinctive hover effect over each row: the values appear
- verbatim on hovering, and the hovered row is highlighted. In order not to deprive users
- who do not have a good hover pointer, this effect is a progressive enhancement
- based on the @media (hover: hover) { … } media query.
-
-
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
+ There is currently a bug in Chromium — I filled
+ an issue on bugs.chromium.org —
+ when using the border-spacing property on the table:
+ it prevents Chrome to define the dimensions of the table…
+ For Chrome user, use the inspector to uncheck this property on the
+ <table> tag of these examples!
+
+
Reduced test case
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
Very few changes compared to the previous version:
+
+
+
+ the <table> element no longer carries the values,
+ but has a new --areas custom property to indicate the number of rows in the table;
+
+
+ however we multiply the number of rows in the body of the table:
+
+
+ each one carries several variables:
+ --color then the values — --1, etc.;
+
+
+ and contains several cells: a <th scope="row"> row header cell
+ and <td> data cells;
+
+
+
+
+ the rest is relatively common now — if you've gone through the previous examples:
+
+
+ a color for each row, presented on the header cells
+ and serving as a background for the data cells;
+
+
+ a distinctive hover effect over each row: the values appear
+ verbatim on hovering, and the hovered row is highlighted. In order not to deprive users
+ who do not have a good hover pointer, this effect is a progressive enhancement
+ based on the @media (hover: hover) { … } media query.
+
+
+
+
+
+
+
+
+
+ Switch
+ Allows you to disable styles on the following table.
+
- Celui-ci est plutôt amusant. On définit quelques variables
- CSS sur le tableau
- : l’échelle (et les paliers), le nombre d’éléments, et les valeurs.
-
-
-
- Côté CSS, ça se complique :
-
-
-
-
- sur l’élément <table>, on crée l’échelle circulaire à l’aide de deux
- repeating-radial-gradient() successifs — en fonction des variables
- --scale et --step ;
-
- puis on utilise de nouveau clip-path et la fonction polygon()
- sur chaque enfant direct <span> — étendu pour occuper toute la surface
- de son <td> de parent — afin de former un triangle, basé pour un côté
- sur le ratio valeur de l’élément courant / échelle, et sur un autre côté un ratio basé sur
- la valeur de l’élément suivant (miam les calc())
- — mais sur une autre échelle…
-
-
- car pour compenser la distorsiondue à la fonction skew(),
- nous devons corriger l’échelle sur laquelle est calculée le second ratio à l’aide d’un peu
- de trigonométrie :
-
-
- nous connaissons un côté du triangle rectangle obtenu après la déformation,
- ainsi que deux angles — le droit, bien entendu, et nous déduisons le deuxième de
- l’angle utilisé pour déformer l’élément ;
-
-
- nous pouvons donc calculer l’hypothénuse en utilisant la loi des sinus,
- — comme précédemment dans le graphique en tarte ;
-
-
- et finalement, il ne nous reste qu’à calculer le ratio entre la dimension initiale
- — le côté — et la dimension finale — l’hypothénuse — et appliquer ce ratio
- à l’échelle sur laquelle est placée le deuxième point du polygone.
-
-
-
-
- le troisième point du polygône est l’angle en bas à droite, dont les coordonnées sont
- 100% 100% ;
-
-
-
- une dernière astuce est nécessaire pour fermer la forme vous l’avez vu, nous utilisons
- la valeur courante et la valeur suivante pour chaque élément. Mais arrivé au dernier élément,
- il n’y a plus de suivant ! Il faut donc ajouter une valeur,
- à laquelle on attribue la première valeur — dans cet exemple, --8: var(--1);.
-
-
-
-
Et voilà, c’est tout !
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
+ Celui-ci est plutôt amusant. On définit quelques variables
+ CSS sur le tableau
+ : l’échelle (et les paliers), le nombre d’éléments, et les valeurs.
+
+
+
+ Côté CSS, ça se complique :
+
+
+
+
+ sur l’élément <table>, on crée l’échelle circulaire à l’aide de deux
+ repeating-radial-gradient() successifs — en fonction des variables
+ --scale et --step ;
+
+ puis on utilise de nouveau clip-path et la fonction polygon()
+ sur chaque enfant direct <span> — étendu pour occuper toute la surface
+ de son <td> de parent — afin de former un triangle, basé pour un côté
+ sur le ratio valeur de l’élément courant / échelle, et sur un autre côté un ratio basé sur
+ la valeur de l’élément suivant (miam les calc())
+ — mais sur une autre échelle…
+
+
+ car pour compenser la distorsiondue à la fonction skew(),
+ nous devons corriger l’échelle sur laquelle est calculée le second ratio à l’aide d’un peu
+ de trigonométrie :
+
+
+ nous connaissons un côté du triangle rectangle obtenu après la déformation,
+ ainsi que deux angles — le droit, bien entendu, et nous déduisons le deuxième de
+ l’angle utilisé pour déformer l’élément ;
+
+
+ nous pouvons donc calculer l’hypothénuse en utilisant la loi des sinus,
+ — comme précédemment dans le graphique en tarte ;
+
+
+ et finalement, il ne nous reste qu’à calculer le ratio entre la dimension initiale
+ — le côté — et la dimension finale — l’hypothénuse — et appliquer ce ratio
+ à l’échelle sur laquelle est placée le deuxième point du polygone.
+
+
+
+
+ le troisième point du polygône est l’angle en bas à droite, dont les coordonnées sont
+ 100% 100% ;
+
+
+
+
+ une dernière astuce est nécessaire pour fermer la forme vous l’avez vu, nous utilisons
+ la valeur courante et la valeur suivante pour chaque élément. Mais arrivé au dernier élément,
+ il n’y a plus de suivant ! Il faut donc ajouter une valeur,
+ à laquelle on attribue la première valeur — dans cet exemple, --8: var(--1);.
+
+
+
+
Et voilà, c’est tout !
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
- Il y a en ce moment un bug dans Chromium — j’ai saisi
- un ticket sur bugs.chromium.org —
- lors de l’utilisation de la propriété border-spacing sur le tableau :
- cela empêche Chrome de définir les dimensions du tableau…
- Pour les utilisateurs de Chrome, utilisez l’inspecteur pour décocher cette propriété
- sur la balise <table> de ces exemples !
-
-
Cas de test réduit
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
Très peu de changements par rapport à la version précédente :
-
-
-
- l’élément <table> ne porte plus les valeurs, mais dispose d’une nouvelle
- variable --areas pour indiquer le nombre de lignes dans le tableau ;
-
-
- en revanche on multiplie le nombre de lignes dans le corps du tableau :
-
-
- chacune porte plusieurs variables :
- --color puis les valeurs — --1, etc. ;
-
-
- et contient plusieurs cellules : une d’entête de ligne <th scope="row">
- et des cellules de données <td> ;
-
-
-
- le reste est relativement commun désormais — si vous avez parcourus les exemples précédents :
-
-
- une couleur pour chaque ligne, présentée sur les cellules d’entête et servant d’arrière-plan aux
- cellules de données ;
-
-
- un effet distinctif au survol de chaque ligne : les valeurs apparaissent
- textuellement au survol, et la ligne survolée est mise en exergue. Afin de ne pas priver les utilisateurs
- n’ayant pas de pointeur doué pour le survol, cet effet est une amélioration progressive
- basé sur la media query@media (hover: hover) { … }.
-
-
-
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
+ Il y a en ce moment un bug dans Chromium — j’ai saisi
+ un ticket sur bugs.chromium.org —
+ lors de l’utilisation de la propriété border-spacing sur le tableau :
+ cela empêche Chrome de définir les dimensions du tableau…
+ Pour les utilisateurs de Chrome, utilisez l’inspecteur pour décocher cette propriété
+ sur la balise <table> de ces exemples !
+
+
Cas de test réduit
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
Très peu de changements par rapport à la version précédente :
+
+
+
+ l’élément <table> ne porte plus les valeurs, mais dispose d’une nouvelle
+ variable --areas pour indiquer le nombre de lignes dans le tableau ;
+
+
+ en revanche on multiplie le nombre de lignes dans le corps du tableau :
+
+
+ chacune porte plusieurs variables :
+ --color puis les valeurs — --1, etc. ;
+
+
+ et contient plusieurs cellules : une d’entête de ligne <th scope="row">
+ et des cellules de données <td> ;
+
+
+
+
+ le reste est relativement commun désormais — si vous avez parcourus les exemples précédents :
+
+
+ une couleur pour chaque ligne, présentée sur les cellules d’entête et servant d’arrière-plan aux
+ cellules de données ;
+
+
+ un effet distinctif au survol de chaque ligne : les valeurs apparaissent
+ textuellement au survol, et la ligne survolée est mise en exergue. Afin de ne pas priver les utilisateurs
+ n’ayant pas de pointeur doué pour le survol, cet effet est une amélioration progressive
+ basé sur la media query@media (hover: hover) { … }.
+
+
+
+
+
+
+
+
+
+ Interrupteur
+ Permet de désactiver les styles sur le tableau suivant.
+
- Les différentes versions de graphiques présentées pour le moment reposent uniquement
- sur un balisage sémantique — à base de <table> —
- et une tartine de variables CSS portées par les balises.
- Aucun JavaScript n’est requis pour l’affichage, et les styles sont
- améliorés progressivement selon les capacités de votre navigateur.
-
-
-
- Note : en vertu du caractère expérimental
- de ces techniques et d’une fondation solide améliorée progressivement,
- je ne précise pas le support navigateur de chaque exemple — mais
- il va de soi que ce n’est pas magique, et que seuls les navigateurs modernes répondent à l’appel,
- à l’exception notable de Edge
- qui ne supporte pas (encore) clip-path.
- Les autres navigateurs affichent un tableau correctement stylé, et c’est chouette.
-
-
-
L’accessibilité
-
-
- Un effort conséquent a été porté à l’accessibilité.
- Comme évoqué précédement, un balisage sémantique et structuré est un pré-requis
- — mais ça ne suffit pas. Les CSS
- sont appliqués aussi progressivement que possible, afin de garantir le meilleur affichage
- possible des données pour chaque internaute.
-
-
-
Tableau accessible
-
-
Piqure de rappel :
-
-
-
un tableau doit démarrer par un <caption> ;
-
- les cellules d’en-tête <th> doivent porter un attribut scope,
- avec une valeur row ou col selon le cas ;
-
-
- et vous aurez généralement besoin de distinguer l’entête du corps grâce à
- <thead> et <tbody> ;
-
-
- pour les valeurs disposant d’une unité : si vous vous aventurez à utiliser l’élement
- <abbr> pour utiliser sa version abrégée, pensez à doubler l’attribut
- title avec l’attribut aria-label — cela en améliorera
- considérablement l’intérêt pour de nombreux internautes.
-
- Pour distinguer les différentes zones autrement que par la couleur, un motif
- svg
- est appliqué en
- css
- — vous en trouverez quelques-uns sur le site
- Hero Patterns :
-
-
-
- afin d’améliorer le mélange avec les couleurs ou dégradés d’arrière-plan, la propriété
- background-blend-mode est utilisée avec la valeur hard-light ;
-
-
- les tailles et positions du motif dépendent directement de la valeur et de l’échelle du graphique,
- selon le type de graphique ;
-
-
- {% include 'includes/_svg-encoding.html' %}
-
-
Respect des préférences
-
- Afin de respecter autant que possible les préférences des visiteurs,
- de nombreux éléments ont été adaptés :
-
-
-
- les dimensions sont en unités relatives (em ou rem selon les cas),
- afin de s’ajuster de manière cohérente au corps de texte hérité du navigateur et de pouvoir
- être agrandi ou réduit sans perte ;
-
- les animations et transitions sont désactivées lorsque le système
- expose cette préférence grâce à prefers-reduced-motion: reduce ;
-
-
- les effets de survol dont l’état initial consiste à masquer du contenu
- sont activés contextuellement dans la requête média @media (hover: hover) { … }.
-
-
-
-
display et sémantique
-
- Adrian Roselli explique que jouer avec le display d’un élément
- <table> ou <dl> met en péril sa sémantique.
- Cette dernière est donc « verrouillée » à l’aide des rôles
- aria
- dédiés — comme il l’explique
- dans un article détaillé.
-
-
- C’est pourquoi chaque tableau est précédé d’un interrupteur — basé sur
- le composant inclusif
- conçu par Heydon Pickering —
- dont le seul et unique rôle est de désactiver les styles supplémentaires :
-
-
- {% include 'includes/_inclusive-toggle.html' %}
-
-
- Voilà, nous sommes prêts à entrer dans le vif du sujet.
- Faites chauffer votre inspecteur !
-
- This type of graph is used to represent one-dimensional data
- (in our example, a timeline).
- It's based on CSS grids and custom properties,
- a technique inspired by
- an article by Miriam Suzanne on
- CSS Tricks
- with a slight enhancement to improve accessibility.
- Here's how to use it:
-
-
-
-
- On the table itself, the --scale custom property is used to define the maximum value for the graph,
- in order to determine its scale. Concretely, a grid will be generated with:
-
-
the first column dedicated to header cells <th> arbitrarily set to 12.5em;
-
then the CSS repeat() function creates a column per scale unit — in the example, 3000 columns;
- On each cell<td>, a --value custom property
- allows to place it on the grid, applied to grid-column-end.
- Moreover, thanks to clever calculations based on this value, the background gradient is sized
- and positioned to reflect the proportion represented by this value on the given scale
- (from green for almost nothing to red for almost everything).
-
-
- In each cell, the content must include the value and its unit in a
- <span> element, possibly tagged with <abbr>
- (and aria-label to complement title) if a title can explicit the unit.
- This value is pushed to the right of the grid, and its text serves as a mask for the background
- gradient — thanks to S. Shaw's trick to
- apply background-clip: text as a progressively enhancement — allowing it to be the
- corresponding color at the end of the gradient for the given position.
-
-
-
- {% import 'macros/_table-bar.html' as table %}
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
- The principle is the same for this variant, except for one detail: we also manage
- the starting point for each measurement
- — which is, very simply, the value of the previous point…
- However, all the values must be passed as variables on the parent <table>.
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
- Ce type de graphique sert à représenter des données à une dimension
- (dans notre exemple, une ligne de temps).
- Il repose sur les grilles et les variables CSS,
- technique inspirée
- d’un article de Miriam Suzanne sur
- CSS Tricks
- légèrement agrémentée pour en améliorer l’accessibilité.
- Pour vous en servir, c’est simple :
-
-
-
-
- Sur le tableau, une variable --scale permet de définir la valeur maximale du graphique,
- afin d’en déterminer l’échelle. Concrètement, une grille va être générée avec :
-
-
la première colonne pour les entêtes <th> arbitrairement fixée à 12.5em ;
-
puis la fonction CSS repeat() crée une colonne par unité de l’échelle — dans l’exemple, 3000 colonnes ;
- Sur chaque cellule<td>, une variable --value permet de la placer sur la grille,
- appliquée à grid-column-end.
- De plus grâce à de savants calculs reposant sur cette valeur, le dégradé en arrière-plan est dimensionné et positionné de façon à
- refléter la proportion représentée par cette valeur sur l’échelle donnée (du vert pour presque rien au rouge pour presque tout).
-
-
- Dans chaque cellule, le contenu doit reprendre la valeur et son unité dans un élément <span>, éventuellement
- balisée avec <abbr> (et aria-label pour suppléer title) si un intitulé peut être explicité pour l’unité.
- Cette valeur est poussée à droite de la grille, et son texte sert de masque pour le dégradé en arrière-plan
- — grâce à une astuce de S. Shaw's pour
- appliquer background-clip: text en amélioration progressive — lui permettant d’être de la couleur correspondante
- à la fin du dégradé pour la position donnée.
-
-
-
- {% import 'macros/_table-bar.html' as table %}
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
- Le principe est le même pour cette variante, à un détail près :
- on gère également le point de départ pour chaque mesure
- — qui est, très simplement, la valeur du point précédent…
- Il faut cependant passer toutes les valeurs en tant que variables sur
- le parent <table>.
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
- Le graphique en tarte sert pour les représentations de proportions en pourcentage.
- Il s’appuie sur des variables CSS, un abus outrancier de calc(),
- display: table-*, clip-path, mask-image,
- transform et un tantinet de SVG
- pour distinguer chaque zone. Oui, je sais rigoler. Comment qu’on s’en sert ?
-
-
-
-
- Sur chaque entête<th>, une variable --color
- permet d’attribuer, et bien… une couleur.
-
-
- Puis chaque cellule<td> doit contenir la valeur et son unité,
- ainsi qu’un attribut style pour porter quelques variables :
-
-
- --value correspond à la valeur en pourcentage,
- utile pour déterminer l’angle que doit occuper l’élément sur le cercle.
- Tous les points du polygon() — servant à tracer la part du fromage
- à l’aide de clip-path — dépendent de cette valeur (lire la note technique après l’exemple pour le détail
- des calculs).
-
-
- --start permet de définir le point de départ de l’arc
- sur le cercle. Il s’agit de la somme des précédentes définitions, et est appliqué
- à la fonction rotate() de la propriété transform.
-
-
- Et enfin une série de variables booléennes valant chacune 0 ou 1
- — d’après une idée de
- Roman Komarov dans son article "Conditions for CSS variables" —
- dépendent de la valeur : --lt-25, --gt-25, --lt-50…
- Elles permettent de faire basculer les points de leur position d’origine
- (50% 50%) à leur position calculée, en s’additionnant ou se soustrayant
- à la valeur initiale ;
-
-
-
-
- un pseudo-élément::before sur chaque cellule <td> est mis en forme
- de savante manière en fonction de toutes nos variables, avec notamment transform,
- clip-path et mask-image.
-
- un pseudo-élément::after est utilisé pour simuler une infobulle, récapitulant
- l’entête et la valeur de la cellule — l’affichage de propriétés personnalisées dans un pseudo-élément n’est pas si triviale :
-
-
- content n’accepte que les chaînes de caractères, et nos propriétés personnalisées contiennent…
- des nombres.
-
- Dans ce graphique, chaque portion représente un arc de cercle basé sur un angle (une partie de 360 degrés).
- Pour définir la forme de cette portion, il faut donc placer un point sur le cercle.
-
-
- Pour ce faire, je divise le cercle en quatre carrés. La position du point sur le cercle peut ainsi
- être calculée en utilisant les propriétés du triangle rectangle formé par :
-
-
-
le centre du cercle,
-
le point que nous cherchons à positionner,
-
et le point perpendiculaire au rayon et passant par notre point cible.
-
-
- Nous connaissons l’hypoténuse de ce triangle — le rayon du cercle —,
- et l’angle formé par l’hypoténuse et partant du centre du cercle
- (en ramenant la valeur sur 90 degrés, puisque le cercle est divisé en quatre secteurs carrés :
- si la valeur est supérieure à 25 : moins 90°, etc.)
- — plus un angle droit, bien entendu.
-
- L’utilisation de variables pseudo-booléennes rend ce calcul pseudo-algorithmique.
- Démarrons par un pré-requis essentiel : le polygone étant un tracé fermé et CSS
- n’étant pas magique, les points doivent pré-exister.
- Spoiler, il nous faut onze points :
-
-
-
- L’axe initial, du centre vers le milieu en haut : 50% 50%
- et 50% 0%.
-
-
- Un point pour chaque angle aux extrémités : le premier est fixe, à
- 100% 0% (en haut à droite) — puis chacun des autres angles
- a deux états, atteint ou non. Quelques détails :
-
-
- Par exemple le point en bas à droite concerne
- les valeurs entre 25% et 50% : si la valeur est inférieure à 25%, il doit
- être au centre (pour ne pas gêner le tracé), et dans le cas contraire être
- dans son coin. ce qui s’exprime ainsi :
- calc( 50% + ( var(--gt-25, 0) * 50% ) ) calc( 50% + ( var(--gt-25, 0) * 50% ) )
- Ainsi la valeur calculée sera 50% 50% si --gt-25 vaut 0,
- et 100% 100% si --gt-25 vaut 1.
-
-
- De plus, chaque angle a sa coordonnée cible :
- 100% 100% pour en bas à droite, 0% 100% pour en bas à gauche,
- 0% 0% pour en haut à gauche. Il faut donc tantôt soustraire et
- tantôt ajouter 50% à la valeur intitiale 50% 50%
- pour basculer sur le bon point.
-
-
-
-
- Un point pour chaque position possible par quart de cercle, correspondant à
- chaque tranche de 25%. À l’instar des points aux angles, ces points doivent être au centre
- s’ils ne sont pas utilisés. C’est là qu’on rigole le plus :
-
-
on part de 50%, auxquels on ajoute ou soustrait la suite du calcul ;
-
- on utilise enfinla position calculée — --pos-A
- ou --pos-B selon le cas — qu’on convertit en pourcentages à l’aide de
- * 1%, et qu’on rend inerte si la valeur est inférieure à la tranche concernée
- grâce à * var(--lt-25, 1), par exemple.
-
- Remarquez le seconde valeur dans var(), qui est la valeur par défaut
- si la variable n’est pas définie. Cool, non ?
-
-
-
- et finalement lorsque la tranche est dépassée, le point bascule vers
- 0% ou 100% selon le cas.
-
-
-
-
- Et enfin, on referme le tracé en revenant au centre du cercle,
- à 50% 50%.
-
-
-
C’est tout !
-
Les positions illustrées
-
- Ces captures d’écran — effectuées dans
- l’éditeur de formes
- des outils de développement de Firefox —
- montrent les points du polygone dans les différents cas. Vous pouvez consulter pour chaque valeur citée
- le polygone résolu pour clip-path — et constater le basculement des valeurs dynamiques d’une position à une autre.
-
-
-
-
- Exemple de rendu pour 44%
-
-
-
- Capture d’écran du tracé pour 44%.
-
-
- {% include 'includes/_pie-styles:44.html' %}
- Code généré pour 44%.
-
-
-
-
-
-
- Exemple de rendu pour 64%
-
-
-
- Capture d’écran du tracé pour 64%.
-
-
- {% include 'includes/_pie-styles:64.html' %}
- Code généré pour 64%.
-
-
-
-
-
-
- Exemple de rendu pour 88%
-
-
-
- Capture d’écran du tracé pour 88%.
-
-
- {% include 'includes/_pie-styles:88.html' %}
- Code généré pour 88%.
-
-
-
-
-
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
- L’utilisation de conic-gradient() est prometteuse pour ce cas précis.
- Vous en trouverez des exemples réalisés par Ana Tudor ou Léa Verou — qui a carrément rédigé la spécification,
- et conçu un polyfill.
- Cependant le support limité aux navigateurs basés sur WebKit est déprimant, et pose tout de même quelques questions
- en matière d’accessibilité puisqu’on ne peut pas affecter un motif à chaque couleur du dégradé conique.
-
-
-
-
Polaire
-
-
- Pour cette déclinaison, on ne change presque rien : seulement la variable --zoom
- et son implication dans la mise à l’échelle des portions à l’aide de scale().
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
-
Répartition du poids des ressources pour ffoodd.fr
- the repeat() function applied with the --scale custom property
- enables us to handle a dynamic scale;
-
-
- <thead>, <tbody> and <tr> containers
- are neutralized in the grid structure using display: contents;
-
- each cell is placed on the grid depending its --value
- — its background color also depending on its value;
-
-
- and finally its text value — wrapped in a <span> element —
- is positioned at the top of the column using the same trick as in the bar chart.
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Browser market shares in France in January 2019
-
-
-
Browser
-
Chrome
-
Firefox
-
Safari
-
Edge
-
IE
-
Others
-
-
-
-
-
Market shares
-
62%
-
15%
-
9%
-
5%
-
6%
-
3%
-
-
-
-
-
-
- HTML
-
{% include 'includes/_column-markup.html' %}
-
-
- css
-
{% include 'includes/_column-styles.html' %}
-
-
-
Multiple columns
-
-
- In order to have two values for each main column, we must also have
- two subheadings. Concretely speaking:
-
-
-
-
- we add a second row in <thead>:
-
-
- with two column header cells <th scope="col">
- for each column header cell in the first row;
-
-
- remember to add colspan="2" on the first row's header cell
- to match the new table layout;
-
-
- and finally add an identifier to each header cell
- to referenced them to the relevant data cells — using the
- headers attribute, par exemple pour la première cellule:
- headers="browser chrome year chrome-2018" where each value
- is a header cell's identifier.
-
-
-
-
- Styles:
-
-
- the first-level header cells must span two columns of the grid,
- as required by their colspan for the table layout. It is
- unfortunately impossible to use an attribute value in another
- property than content — otherwise we could simply write
- grid-column: 2 / span attr(colspan);, and that would be awesome…
-
-
- but no! Thus, a --span custom property is added on <table>,
- and must match the colspan attributes values mentionned earlier:
- it is therefore used to extend the first level headers to the appropriate number of columns.
-
-
- Colors and patterns are no longer applied according to each value,
- but according to each column — in the example, every second element
- (since we have two entries per column).
- Again, if we could use an attribute value or a custom property
- in a selector, that would be great. Imagine
- tbody td:nth-of-type(var(--span)n + var(--span)) or even
- tbody td:nth-of-type(attr(colspan)n + attr(colspan))!
-
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
- Ce graphique repose sur les variables CSS, les grilles et clip-path.
- Cette dernière propriété est la plus importante.
-
-
-
-
- Sur le tableau, les échelles et l’unité sont indiquées :
-
-
- --y définit l’échelle des ordonnées, utilisée
- pour indiquer l’échelle en arrière-plan mais aussi placer
- les points sur la courbe ;
-
-
- --x correspond à l’échelle des abscisses, exprimée
- simplement comme le nombre de colonnes à afficher ;
-
-
--unit permet de définir l’unité à afficher dans l’infobulle simulée.
-
-
-
- Chaque ligne <tr> dans <tbody> porte une palanquée
- de variables, correspondant à toutes les valeurs qu’elle contient.
- Dans un pseudo-élément ::before, une position est définie pour chaque valeur
- au sein de la fonction polygon() de clip-path.
-
-
- Étant donné que cette fonction accepte deux valeurs en pourcentage
- chaque point, la méthode est relativement simple.
- La position en abscisse est le nombre de colonnes (le décalage depuis la gauche, donc)
- et la position en ordonnée est le ratio de la valeur sur l’échelle, le tout formulé ainsi :
- calc( ( 100% / var(--x) * 1 ) + var(--offset) ) calc( 100% - ( var(--1) / var(--y) * 100% ) ),
- où * 1 et var(--1) correspondent à l’index de la valeur dans l’ensemble,
- et var(--offset) est la valeur d’une demi-colonne, pour placer le point au milieu
- de sa colonne.
-
-
- Vous l’aurez peut-être compris, le principal écueil de ce graphique est qu’il
- nécessite de connaître le nombre de points par avance.
-
- Chaque cellule <td> dans <tbody> porte un pseudo-élément
- ::after qui sert à récapituler ses entêtes et valeur dans
- une infobulle simulée, et un pseudo-élément ::before pour gérer un calque interactif sur la cellule :
-
Et finalement la propriété personnalisée --unit sert de finition.
-
-
-
- Tout le reste n’est que décoration :
-
-
- un padding-top important sur le tableau pour
- réserver l’espace d’affichage des graphiques — attention :
- il est nécessaire d’appliquer border-collapse: separate; sur le tableau
- afin que le padding ait un impact ;
-
-
le ::before de chaque ligne est étiré afin d’occuper tout l’espace réservé ;
-
un arrière-plan dégradé pour représenter la surface pleine du même ::before ;
-
- un repeating-linear-gradient() pour représenter l’échelle verticale,
- en arrière-plan du tableau ;
-
-
- et des interactions au survol pour mettre en exergue la valeur survolée :
- sa colonne à l’aide d’un pseudo-élément — positionné à l’aide de de savants calculs —
- et mix-blend-mode pour un effet waouh.
-
-
-
-
-
-{% import 'macros/_table-line.html' as table %}
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
- Pour commencer, il faut bien intégrer que clip-path est un tracé,
- au même titre qu’une forme vectorielle. Il doit donc être fermé.
- Ainsi le tracé démarre à 0% 100% — en bas à gauche, fait sa vie
- de tracé, bascule à 100% 100% et revient boucler à 0% 100%.
-
-
Et dans son chemin, chaque point doit être positionné en abscisses et en ordonnées.
-
La position en abscisse
-
- La première position est simple : on divise 100% par l’échelle
- var(--x), et on multiplie par l’index de l’élément. Par exemple :
- calc( ( 100% / var(--x) * 1) ).
- Pour placer chaque point au milieu de sa colonne, on le décale d’une demi-colonne
- — ce que l’on fait en ajoutant au calcul précédent var(--offset), qui correspond
- à calc( ( 100% / var(--x) ) / 2 ).
- La position finale est donc, ici pour le troisième point :
- calc( ( 100% / var(--x) * 3) + var(--offset) ).
-
-
La position en ordonnée
-
- Dans ce graphique, l’ordonnée est l’axe le plus important. Ainsi pour placer le point,
- on commence par calculer le ratio de sa valeur sur l’échelle — formulé
- ainsi : var(--1) / var(--y). Et parce que polygon() utilise
- des valeurs en pourcentage, on rapporte ce calcul sur 100% :
- ( var(--1) / var(--y) * 100% ).
- Et pour finir, les référentiels du polygone partant d’en haut à gauche, la position
- doit être définie en fonction du haut de la boîte. La formule finale ressemble
- alors à ça — toujours pour le troisième élément :
- calc( 100% - ( var(--3) / var(--y) * 100% ) ).
-
-
-
-
Graphique à point
-
-
Cette variante diffère finalement assez peu de la précédente mouture :
-
-
-
- le polygon() est poursuivi pour former une ligne,
- en dupliquant chaque point avec un décalage de 4px
- — l’épaisseur du trait — et dans l’ordre inverse ;
-
-
- le pseudo-élément ::before qui permet d’afficher l’infobulle prend ici la forme d’un
- point sur la courbe — positionné à l’aide des mêmes calculs qui servent dans le polygone ;
-
-
- et surtout, puisque clip-path est appliqué sur la ligne
- <tr> : vous pouvez en mettre plusieurs !
- Il nous faut donc ajouter une combinaison de couleur et motif pour distinguer chaque ligne
- et les associer visuellement à leur légende.
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
- la fonction repeat() appliquée avec la variable --scale
- permet de gérer une échelle dynamique ;
-
-
- les conteneurs <thead>, <tbody> et <tr>
- sont neutralisés dans la gestion de la grille à l’aide de display: contents ;
-
- chaque cellule est placée sur la grille en fonction de --value
- — sa valeur, donc — sa couleur d’arrière-plan dépend également de
- sa valeur ;
-
-
- et finalement la valeur textuelle — contenue dans un élément
- <span> — est positionnée en haut de la colonne
- à l’aide de la même astuce que dans le graphique en barre.
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
-
Parts de marché navigateurs en France en janvier 2019
-
-
-
Navigateur
-
Chrome
-
Firefox
-
Safari
-
Edge
-
IE
-
Autres
-
-
-
-
-
Parts de marché
-
62 %
-
15 %
-
9 %
-
5 %
-
6 %
-
3 %
-
-
-
-
-
-
- Le HTML
-
{% include 'includes/_column-markup.html' %}
-
-
- Le css
-
{% include 'includes/_column-styles.html' %}
-
-
-
Colonnes multiples
-
-
- Pour disposer de deux valeurs pour chaque colonne principale, nous devons également
- disposer de deux sous-titres.
- Concrètement parlant :
-
-
-
-
- on ajoute une seconde ligne dans l’entête<thead> :
-
-
- avec deux cellules d’entête de colonne <th scope="col">
- pour chaque cellule d’entête de colonne dans la première ligne d’entête ;
-
-
- n’oublions pas d’ajouter un colspan="2" sur les cellules d’entête de
- la première ligne pour faire correspondre la structure du tableau ;
-
-
- et enfin ajouter un identifiant à chaque cellule d’entête
- afin de les référencer sur les cellules de données concernées — à l’aide
- de l’attribut headers, par exemple pour la première cellule :
- headers="navigateur chrome annee chrome-2018" où chaque valeur est un
- identifiant de cellule d’entête.
-
-
-
-
- Côté styles :
-
-
- les cellules d’entête de premier niveau doivent s’étendre sur deux colonnes de la grille,
- comme le réclame leur attribut colspan pour la structure du tableau. Il est
- malheureusement impossible d’utiliser la valeur d’un attribut dans une autre
- propriété que content — sinon nous pourrions simplement écrire
- grid-column: 2 / span attr(colspan); et ça serait magnifique…
-
-
- mais non ! Ainsi, une variable --span est ajoutée sur <table>,
- et doit correspondre à la valeur des attributs colspan cités plus tôt :
- elle sert donc à étendre les entêtes de premier niveau sur le nombre de colonnes adéquat.
-
-
- les couleurs et motifs ne sont plus appliqués en fonction
- de chaque valeur, mais en fonction de chaque colonne — dans l’exemple, un élément
- sur deux (puisque nous avons deux entrées par colonne).
- Là aussi, si nous pouvions utiliser une valeur d’attribut ou une propriété personnalisée
- dans un sélecteur, ce serait génial. Imaginez un peu
- tbody td:nth-of-type(var(--span)n + var(--span)) ou encore
- tbody td:nth-of-type(attr(colspan)n + attr(colspan)) !
-
-
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
-
Parts de marché navigateurs en France en janvier 2019
- Every charts in this project relies solely on semantic markup
- — <table> based — and a spread of
- CSS variables carried by the tags.
- No JavaScript required for display, and styles are
- progressively enhanced depending on your browser's capabilities.
-
-
-
- Note : by virtue of the experimental
- nature of these techniques and a solid foundation enhanced progressively,
- I don't mention browser support for each example — but
- it goes without saying that this is not magic, and only modern browsers handle this right,
- with the notable exception of Edge
- which does not (yet) support clip-path.
- Other browsers display a properly styled table, and that's nice.
-
-
-
Accessibility
-
-
- A major effort has been made to ensure accessibility.
- As mentioned above, semantic and structured markup is a prerequisite
- — but it's not enough. CSS
- is being applied as gradually as possible, in order to guarantee
- the best possible display of data for each user.
-
-
-
Accessible table
-
-
Wakeup call :
-
-
-
a table must start with a <caption>;
-
- header cells <th> must carry a scope attribute,
- with a row or col value;
-
-
- and you'll usually need to distinguish the head from the body through
- <thead> and <tbody>;
-
-
- for values with a unit : if you venture to use the
- <abbr> element to use its abbreviated version, consider doubling the
- title with the aria-label attribute — this will considerably
- improve the interest for many users.
-
- To distinguish the different areas other than by colour, an
- svg
- pattern is applied in
- css
- — you can find some of them on the
- Hero Patterns website:
-
-
-
- in order to improve blending with background colors or gradients, the
- background-blend-mode proerty is used with the hard-light value;
-
-
- pattern's size and position depends directly on the value and scale of the chart,
- depending on the type of chart;
-
-
- {% include 'includes/_svg-encoding.html' %}
-
-
User preferences
-
- In order to respect as much as possible the preferences of the visitors,
- many elements have been adapted:
-
-
-
- dimensions are in relatives units (em or rem as the case may be),
- in order to fit coherently with the body of text inherited from the browser and to be able
- to be enlarged or reduced without loss;
-
- animations and transitions are disabled when the system exposes
- this preference through prefers-reduced-motion: reduce ;
-
-
- hover effects whose initial state consists in hiding content
- are activated contextually in the @media (hover: hover) { … } media query.
-
-
-
-
display and semantics
-
- Adrian Roselli explains that playing with a <table> or <dl>
- element's display endangers its semantics.
- The latter is therefoore "locked" using dedicated
- aria
- roles — as he explains
- in a detailed article.
-
- This chart is based on CSS custom properties, grids and clip-path
- — the latter being the most important.
-
-
-
-
- Scales are set on the table:
-
-
- --y defines the y-axis scale, used to indicate the scale
- in the background but also to place the points on the curve;
-
-
- --x is the x-axis scale,
- simply expressed as the number of columns to display;
-
-
--unit defines unit to be displayed in simulated tooltip (see below).
-
-
-
- Each line <tr> in <tbody> carries a set of variables,
- corresponding to all the values it contains.
- In a ::before pseudo-element, a position is defined for each value
- within the clip-pathpolygon() function.
-
-
- Since this function accepts two percentage values at each point,
- the method is pretty straightforward.
- The x-axis position is the number of columns (i.e., the offset from the left) and
- the y-axis position is the ratio of the value on the scale, formulated as follows:
- calc( ( 100% / var(--x) * 1 ) + var(--offset) ) calc( 100% - ( var(--1) / var(--y) * 100% ) ),
- where * 1 and var(--1) is the index of the value as a whole,
- and var(--offset) is the value of half a column,
- to place the point in the middle of its column.
-
-
- As you may have understood, the main pitfall of this graph is
- that it requires to know the number of points in advance.
-
- Each cell <td> in <tbody> carries an
- ::after pseudo-element used to summarize
- its headers and value in a simulated tooltip, and a ::before pseudo-element
- to manage an interactive layer on the cell:
-
- a big padding-top on the table is used to reserve space
- for the charts — caution:
- it is necessary to apply border-collapse: separate; on the table
- for the padding to have an impact;
-
-
each line's ::before is stretched in order to occupy all the reserved space;
-
a gradient background to represent the full area of the same ::before;
-
- a repeating-linear-gradient() to represent the vertical scale
- in the table's background;
-
-
- and hover interactions to highlight the hovered value:
- its column using a pseudo-element — positioned with the help of clever calculations —
- and mix-blend-mode for a wow effect.
-
-
-
-
-
-{% import 'macros/_table-line.html' as table %}
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
- To begin with, you need to understand that clip-path is a path,
- just like a vector shape. It must therefore be closed.
- So the path starts at 0% 100% — bottom left, does its path life,
- toggles to 100% 100% and comes back looping at 0% 100%.
-
-
And in its path, each point must be positioned in abscissa and ordinate.
-
The X-axis position
-
- The first position is simple: divide 100% by the
- var(--x) scale, and multiply by the index of the element.
- For example: calc( ( 100% / var(--x) * 1) ).
- To place each point in the middle of its column, we shift it by half a column
- — which we do by adding to the previous calculation var(--offset),
- which corresponds to calc( ( 100% / var(--x) ) / 2 ).
- The final position is therefore, here for the third point:
- calc( ( 100% / var(--x) * 3) + var(--offset) ).
-
-
The Y-axis position
-
- In this graph, the Y-axis is the most important axis. So to place the point,
- we start by calculating the ratio of its value on the scale
- — formulated as follows: var(--1) / var(--y). And because
- polygon() uses percentage values, we report this calculation on 100%:
- ( var(--1) / var(--y) * 100% ).
- And finally, since the polygon's datums start from the top left, the position
- position must be defined according to the top of the box.
- The final formula then looks like this — again for the third element:
- calc( 100% - ( var(--3) / var(--y) * 100% ) ).
-
-
-
-
-
Line chart with dots
-
-
In the end, this variant differs little from the previous version:
-
-
-
- the polygon() is continued to form a line,
- duplicating each point with an offset of 4px
- — the line thickness — and in the reverse order;
-
-
- the ::before pseudo-element that displays the tooltip takes
- here the form of a point on the curve
- — positioned using the same calculations that are used in the polygon;
-
-
- and especially, since clip-path is applied in the line
- <tr>: you can put more than one !
- So we need to add a combination of color and pattern to distinguish each line
- and associate them visually with their caption.
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
- The pie chart is used for representations of percentage proportions.
- It relies on CSS variables, an outrageous abuse of calc(),
- display: table-*, clip-path, mask-image,
- transform and a bit of SVG
- to distinguish each area. Yes, I know how to laugh. How do we use it?
-
-
-
-
- On each header<th>, a --color
- custom property allows you to assign, well… a color.
-
-
- Then each cell<td> must contain the value
- and its unit, as well as a style attribute to carry some variables:
-
-
- --value is the percentage value,
- useful for determining the angle the element should occupy on the circle.
- All points of the polygon() — used to draw the pie part thanks to clip-path —
- depend on this value (read the technical note after
- the example for details of the calculations).
-
-
- --start is used to define the starting point
- of the arc on the circle. It's the sum of the previous definitions, and is applied
- to the rotate() function of the transform poperty.
-
-
- And finally a series of pseudo-boolean variables, each worthing 0 or 1
- — according to and idea of
- Roman Komarov in "Conditions for CSS variables" —
- depend on the value: --lt-25, --gt-25, --lt-50…
- They allow to toggle the points from their original position
- (50% 50%) to their calculated position, by adding or subtracting from the initial value;
-
-
-
-
- a ::beforepseudo-element on each cell <td>is formatted
- in a clever way according to all our variables, including transform,
- clip-path and mask-image.
-
- a ::afterpseudo-element is used as a tooltip, to summarize header and value for each cell
- —but the display of custom properties in a pseudo-element is not so trivial:
-
-
- content only accepts strings, and our custom properties contains… number.
-
- In this graph, each portion represents an arc of a circle based on an angle (part of 360 degrees).
- To define the shape of this portion, a point must be placed on the circle.
-
-
- To do this, I divide the circle into four squares. The position of the point on the circle
- can then be calculated using the properties of the right-angled triangle formed by:
-
-
-
the center of the circle,
-
the point we're trying to position,
-
and the point perpendicular to the radius and passing through our target point.
-
-
- We know the hypotenuse of this triangle — the radius of the circle —,
- and the angle formed by the hypotenuse and starting from the center of the circle
- (reducing the value to 90 degrees, since the circle is divided into four square sectors:
- if the value is greater than 25: minus 90°, etc.)
- — plus a right angle, of course.
-
- The use of pseudo-Boolean variables makes this calculation pseudo-algorithmic.
- Let's start with an essential pre-requisite: the polygon being a closed shape and CSS
- not being magical, points must pre-exist.
- Spoiler, we need eleven points:
-
-
-
- The initial axis, from centre upwards: 50% 50%
- and 50% 0%.
-
-
- One point for each angle at the ends: the first one is fixed, at
- 100% 0% (top right) — then each of the other angles has
- two states, reached or not reached. Some insights:
-
-
- For example, the point at the bottom right concerns values between 25% and 50%:
- if the value is less than 25%, it must be in the centre (so as not to interfere
- with the drawing), and if not, it must be in its corner:
- calc( 50% + ( var(--gt-25, 0) * 50% ) ) calc( 50% + ( var(--gt-25, 0) * 50% ) )
- Thus the calculated value will be 50% 50% if --gt-25 is 0,
- and 100% 100% if --gt-25 is 1.
-
-
- In addition, each angle has its target coordinate:
- 100% 100% for bottom right, 0% 100% for bottom left,
- 0% 0% for top left. It is therefore necessary to sometimes subtract
- and sometimes add to the initial value 50% 50%
- to switch to the right point.
-
-
-
-
- One point for each possible position per quarter circle, corresponding
- to each 25% slice. Like the points at the corners, these points must be in the centre
- if they are not used. That's where we laugh the most:
-
-
we start from 50%, to which we add or subtract the following calculation;
-
- then the calculated position is used — --pos-A
- or --pos-B as the case may be — which is converted into percentages using
- * 1%, and rendered inert if the value is less than the range concerned
- using * var(--lt-25, 1), for example.
-
- Notice the second value in var()?
- This is the default value if the variable is not defined. Cool, isn't it?
-
-
-
- finally when the range is exceeded, the point switches to
- 0% or 100% as appropriate.
-
-
-
-
- And lastly, we lose the path by going back to the centre of the circle,
- at 50% 50%.
-
-
-
That's it!
-
The positions illustrated
-
- These screenshots — taken in
- the shape editor of the
- Firefox devtools —
- show the points of the polygon in the different cases.
- You can see for each cited value the resolved polygon for clip-path
- — and see how the dynamic values tilt from one position to another.
-
-
-
-
- Rendering example for 44%
-
-
-
- Shape screenshot for 44%.
-
-
- {% include 'includes/_pie-styles:44.html' %}
- Code generated for 44%.
-
-
-
-
-
-
- Rendering example for 64%
-
-
-
- Shape screenshot for 64%.
-
-
- {% include 'includes/_pie-styles:64.html' %}
- Code generated for 64%.
-
-
-
-
-
-
- Rendering example for 88%
-
-
-
- Shape screenshot for 88%.
-
-
- {% include 'includes/_pie-styles:88.html' %}
- Code generated for 88%.
-
-
-
-
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
- On the <table> element, we add an --offset variable
- that allows us to determine the size of the hole of the donut,
- generated using mask-image and radial-gradient().
- Ana Tudor has made
- many examples of using mask-* on CodePen, have a look!
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Distribution of the weight of resources for ffoodd.fr
- The use of conic-gradient() is promising for this case.
- You'll find examples made by Ana Tudor and Léa Verou
- — who actually wrote the specification, and designed
- a polyfill.
- However, current support is limited to WebKit based browsers
- is depressing, and still raises some accessibility issues
- since you can't assign a pattern to each color of the conic-gradient().
-
-
-
-
Polar chart
-
-
- For this variant, wa change almost nothing: only the --zoom variable
- and its implication in the scaling of portions using scale().
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Distribution of the weight of resources for ffoodd.fr
- This one's kind of fun. We define some CSS
- variables on the table: the scale (and tiers), the number of elements, and the values.
-
-
-
- On the CSS side, it's getting complicated:
-
-
-
-
- on the <table> element, the circular scale is created using two successive
- repeating-radial-gradient() — depending on the
- --scale and --step variables;
-
each one is decorated with a border at the bottom;
-
- then we use again clip-pathpolygon() function
- on each direct child <span> — extended to occupy the whole surface
- of its parent <td> — in order to form a triangle, based for one side
- on the ratio value of the current element / scale, and on another side a ratio based on the
- value of the next element (yum calc())
- — but on another scale…
-
-
- because to compensate for the distortion
- due to the skew() function,
- we need to correct the scale on which the second ratio is calculated
- using a little trigonometry:
-
-
- we know one side of the right-angled triangle obtained after the deformation,
- as well as two angles — the right one, of course, and we deduce
- the second from the angle used to deform the element;
-
-
- so we can calculate the hypothenuse using the sine law,
- — as before in the pie chart;
-
-
- and finally, all we have to do is calculate the ratio between the initial dimension
- — the side — and the final dimension — the hypothenuse —
- and apply this ratio to the scale on which the second point of the polygon is placed.
-
-
-
-
- The third point of the polygon is the bottom right corner, whose coordinates are
- 100% 100%;
-
-
-
- one last trick is necessary to close the shape you have seen,
- we use the current and next value for each element. But when we get to the last element,
- there is no next! So we need to add a value, to which we assign
- the first value — in this example, --8: var(--1);.
-
-
-
-
And that's it!
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
-
-
-
-
-
Level of interest by domain, out of 20
-
-
-
Accessibility
-
SEO
-
Performance
-
Compatibility
-
Security
-
Code quality
-
Test
-
-
-
-
-
14
-
11
-
13
-
16
-
10
-
12
-
4
-
-
-
-
-
-
- HTML
-
{% include 'includes/_radar-markup.html' %}
-
-
- css
-
{% include 'includes/_radar-styles.html' %}
-
-
- A Chromium bug
-
- There is currently a bug in Chromium — I filled
- an issue on bugs.chromium.org —
- when using the border-spacing property on the table:
- it prevents Chrome to define the dimensions of the table…
- For Chrome user, use the inspector to uncheck this property on the
- <table> tag of these examples!
-
-
Reduced test case
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
Very few changes compared to the previous version:
-
-
-
- the <table> element no longer carries the values,
- but has a new --areas custom property to indicate the number of rows in the table;
-
-
- however we multiply the number of rows in the body of the table:
-
-
- each one carries several variables:
- --color then the values — --1, etc.;
-
-
- and contains several cells: a <th scope="row"> row header cell
- and <td> data cells;
-
-
-
- the rest is relatively common now — if you've gone through the previous examples:
-
-
- a color for each row, presented on the header cells
- and serving as a background for the data cells;
-
-
- a distinctive hover effect over each row: the values appear
- verbatim on hovering, and the hovered row is highlighted. In order not to deprive users
- who do not have a good hover pointer, this effect is a progressive enhancement
- based on the @media (hover: hover) { … } media query.
-
-
-
-
-
-
-
-
-
- Switch
- Allows you to disable styles on the following table.
-
- Celui-ci est plutôt amusant. On définit quelques variables
- CSS sur le tableau
- : l’échelle (et les paliers), le nombre d’éléments, et les valeurs.
-
-
-
- Côté CSS, ça se complique :
-
-
-
-
- sur l’élément <table>, on crée l’échelle circulaire à l’aide de deux
- repeating-radial-gradient() successifs — en fonction des variables
- --scale et --step ;
-
- puis on utilise de nouveau clip-path et la fonction polygon()
- sur chaque enfant direct <span> — étendu pour occuper toute la surface
- de son <td> de parent — afin de former un triangle, basé pour un côté
- sur le ratio valeur de l’élément courant / échelle, et sur un autre côté un ratio basé sur
- la valeur de l’élément suivant (miam les calc())
- — mais sur une autre échelle…
-
-
- car pour compenser la distorsiondue à la fonction skew(),
- nous devons corriger l’échelle sur laquelle est calculée le second ratio à l’aide d’un peu
- de trigonométrie :
-
-
- nous connaissons un côté du triangle rectangle obtenu après la déformation,
- ainsi que deux angles — le droit, bien entendu, et nous déduisons le deuxième de
- l’angle utilisé pour déformer l’élément ;
-
-
- nous pouvons donc calculer l’hypothénuse en utilisant la loi des sinus,
- — comme précédemment dans le graphique en tarte ;
-
-
- et finalement, il ne nous reste qu’à calculer le ratio entre la dimension initiale
- — le côté — et la dimension finale — l’hypothénuse — et appliquer ce ratio
- à l’échelle sur laquelle est placée le deuxième point du polygone.
-
-
-
-
- le troisième point du polygône est l’angle en bas à droite, dont les coordonnées sont
- 100% 100% ;
-
-
-
- une dernière astuce est nécessaire pour fermer la forme vous l’avez vu, nous utilisons
- la valeur courante et la valeur suivante pour chaque élément. Mais arrivé au dernier élément,
- il n’y a plus de suivant ! Il faut donc ajouter une valeur,
- à laquelle on attribue la première valeur — dans cet exemple, --8: var(--1);.
-
-
-
-
Et voilà, c’est tout !
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
-
-
-
-
-
Niveau d’intérêt par domaine, sur 20
-
-
-
Accessibilité
-
Référencement
-
Performance
-
Compatibilité
-
Sécurité
-
Qualité de code
-
Test
-
-
-
-
-
14
-
11
-
13
-
16
-
10
-
12
-
4
-
-
-
-
-
-
- Le HTML
-
{% include 'includes/_radar-markup.html' %}
-
-
- Le css
-
{% include 'includes/_radar-styles.html' %}
-
-
- Bug dans Chromium
-
- Il y a en ce moment un bug dans Chromium — j’ai saisi
- un ticket sur bugs.chromium.org —
- lors de l’utilisation de la propriété border-spacing sur le tableau :
- cela empêche Chrome de définir les dimensions du tableau…
- Pour les utilisateurs de Chrome, utilisez l’inspecteur pour décocher cette propriété
- sur la balise <table> de ces exemples !
-
-
Cas de test réduit
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-
Très peu de changements par rapport à la version précédente :
-
-
-
- l’élément <table> ne porte plus les valeurs, mais dispose d’une nouvelle
- variable --areas pour indiquer le nombre de lignes dans le tableau ;
-
-
- en revanche on multiplie le nombre de lignes dans le corps du tableau :
-
-
- chacune porte plusieurs variables :
- --color puis les valeurs — --1, etc. ;
-
-
- et contient plusieurs cellules : une d’entête de ligne <th scope="row">
- et des cellules de données <td> ;
-
-
-
- le reste est relativement commun désormais — si vous avez parcourus les exemples précédents :
-
-
- une couleur pour chaque ligne, présentée sur les cellules d’entête et servant d’arrière-plan aux
- cellules de données ;
-
-
- un effet distinctif au survol de chaque ligne : les valeurs apparaissent
- textuellement au survol, et la ligne survolée est mise en exergue. Afin de ne pas priver les utilisateurs
- n’ayant pas de pointeur doué pour le survol, cet effet est une amélioration progressive
- basé sur la media query@media (hover: hover) { … }.
-
-
-
-
-
-
-
-
-
- Interrupteur
- Permet de désactiver les styles sur le tableau suivant.
-