<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bastien Calou</title>
    <description>The latest articles on DEV Community by Bastien Calou (@bcalou).</description>
    <link>https://dev.to/bcalou</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F174713%2F76ebcfa1-65e5-4b2e-ad57-39e35fb25085.jpg</url>
      <title>DEV Community: Bastien Calou</title>
      <link>https://dev.to/bcalou</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bcalou"/>
    <language>en</language>
    <item>
      <title>« Toxic Data » : la menace de l'intermédiation algorithmique</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Tue, 26 Sep 2023 07:52:13 +0000</pubDate>
      <link>https://dev.to/bcalou/-toxic-data-la-menace-de-lintermediation-algorithmique-2gid</link>
      <guid>https://dev.to/bcalou/-toxic-data-la-menace-de-lintermediation-algorithmique-2gid</guid>
      <description>&lt;p&gt;Je sors de la lecture de &lt;a href="https://editions.flammarion.com/toxic-data/9782080419415"&gt;Toxic Data&lt;/a&gt;, ouvrage passionant de David Chavalarias, chercheur au CNRS, sur le rôle toxique que joue une grande partie des réseaux sociaux sur nos sociétés.&lt;/p&gt;

&lt;p&gt;Il met en mots simples un sentiment de malaise que nous sommes, j'en suis sûr, un grand nombre à partager. Pour ma part, ce sentiment est un moteur depuis quelques années pour adopter une attitude de grande méfiance à l'égard des réseaux en question, et en particulier à l'égard de ceux dont les contenus présentés sont régis par un algorithme opaque cherchant à maximiser les interactions sur la plateforme (c'est à dire beaucoup d'entre-eux).&lt;/p&gt;

&lt;p&gt;J'ai le sentiment que ma participation active aux réseaux dans le passé (toujours existante, mais moindre), ainsi que celle d'une grande partie de la société, ont sérieusement altéré la relation que j'entretiens avec mon entourage, notamment dans la façon dont les débats ont tendance à être, sans exception, hautement inflammables.&lt;/p&gt;

&lt;p&gt;Mais David Chavalarias le dit mieux que moi :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;À l'ère numérique, les sujets de discussion sont susceptibles de se polariser autour de points de vue toxiques à l'échelle d'une société entière. Pouvons-nous au moins espérer que la cohésion sociale, même affaiblie, ne sera pas rompue, et que deux camps qui s'opposent sur un thème trouveront toujours un terrain d'entente sur un autre ? [...] Que deux voisins en désaccord sur la vaccination continueront à échanger sur des questions politiques, que deux amis en désaccord sur des questions politiques continueront à discuter sur les questions environnementales ?&lt;br&gt;
Nous avons l'habitude de vivre à l'intersection de plusieurs cercles relationnels qui reflètent la diversité de nos centres d'intérêt et de nos rôles sociaux. [...] Nous nous appuyons activement sur le contexte pour filtrer l'information à laquelle nous accordons de l'importance et pour choisir quel type d'information échanger. Nous n'abordons pas partout, ni n'importe comment, des thèmes tels que l'alimentation, l'éducation, le sport, la contraception ou l'immigration. [...] Bref, nous sommes capables d'orienter notre attention et d'adapter notre comportement en fonction du contexte social.&lt;br&gt;
[...] Les algorithmes ne font pas la distinction entre vos différents cercles relationnels et traitent indifférement vos sujets de préoccupation. [...] Facebook peut très bien vous bombarder de messages que l'une de vos connaissances a appréciés alors même que vous n'abordez jamais ce type de sujets avec elle. Ce bombardement intempestif vous amènera peut-être à adopter un point de vue auquel vous ne vous seriez pas exposé naturellement ou, au contraire, à rompre un lien social par overdose de contenus dissonants, alors que vous auriez très bien pu continuer à sympathiser sur d'autres sujets avec cette personne.&lt;br&gt;
[Il en résulte que] la structure de vos cercles sociaux est brouillée. [...] Vous êtes privé(e) des filtres contextuels que vous appliquiez dans vos interactions quotidiennes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Les effets vont bien au-delà de l'impact sur l'individu lui-même :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Plus un réseau social se densifie avec l'ajout de liens, plus le nombre moyen d'intermédiaires entre deux personnes se réduit. Or les contenus négatifs ont tendance à se propager, de proche en proche, plus facilement que d'autres types de contenus. Dès lors qu'un certain seuil de densification est atteint, ces contenus négatifs sont donc les premiers à pouvoir toucher une très large fraction du réseau, même s'ils sont produits par un très petit nombre de personnes. &lt;br&gt;
Dernier effet potentiel à signaler : comme les mécanismes d'influence sociale ne respectent plus les frontières de vos cercles relationnels sur les réseaux sociaux numériques, les valeurs, les croyances et les comportements risque de s'y aligner en passant d'un cercle relationnel à l'autre. Ce phénomène favoriserait ainsi une polarisation globale de la société, sur plusieurs dimensions à la fois (par exemple, aux États-Unis, en général, les antivax sont aussi climatosceptiques et républicains). Bien que cet effet n'ait pas encore été documenté, il pourrait expliquer la polarisation importante de nos sociétés actuelles et la formation concomitante de plusieurs lignes de fracture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Et l'auteur de lister toutes les applications qui structurent nos vies aujourd'hui, qu'elles soient professionnelles, relationnelles (jusqu'aux relations les plus intimes), relatives aux voyages, à la consommation d'images et de vidéos...  C'est ce que l'auteur appelle &lt;strong&gt;l'intermédiation algorithmique&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;La liste est longue, et un seul ouvrage ne suffirait pas à examiner l'ensemble des configurations sociales au sein desquelles le numérique s'est immiscé, les choix algorithmiques qui ont été faits et leurs conséquences sociales. Il y a néamoins un point commun à toutes ces plateformes : elles se mettent en tête de gérer une partie de nos relations à autrui.&lt;br&gt;
[...] En se posant en intermédiaires dans le flux des échanges sociaux et en modelant la perception que nous avons de notre monde social, les réseaux sociaux numériques se sont arrogé le pouvoir de modeler à leur avantage les piliers de la cohésion sociale.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;David Chavalarias, &lt;a href="https://editions.flammarion.com/toxic-data/9782080419415"&gt;Toxic Data&lt;/a&gt;&lt;/p&gt;

</description>
      <category>socialmedia</category>
    </item>
    <item>
      <title>Do CSS framework users actually know CSS? We might have some data</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Fri, 09 Dec 2022 08:56:28 +0000</pubDate>
      <link>https://dev.to/bcalou/do-css-framework-users-actually-know-css-we-might-have-some-data-22o2</link>
      <guid>https://dev.to/bcalou/do-css-framework-users-actually-know-css-we-might-have-some-data-22o2</guid>
      <description>&lt;p&gt;This year's State of CSS survey offers a great tool they call the &lt;a href="https://2022.stateofcss.com/en-US/explorer"&gt;Data Explorer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For exemple, here is a view of developer's usage of scroll snap properties, combined with their usage of Bootstrap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5MOh7j8T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zmv78swy5rtnhg1r528.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5MOh7j8T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zmv78swy5rtnhg1r528.png" alt="Scroll Snap VS Bootstrap" width="880" height="774"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks a bit complicated, but I will explain that in a moment.&lt;/p&gt;

&lt;p&gt;We all have simplified beliefs about CSS :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"If you use Tailwind, it's because you don't want to learn CSS"&lt;/li&gt;
&lt;li&gt;"But Tailwind solved CSS, it's the way to go!"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, the reality is more complex, and I thought this tool was a great opportunity to explore the relationship between CSS frameworks and native CSS.&lt;/p&gt;

&lt;p&gt;Maybe a good start would be to agree on two things :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don't need to know every CSS property to be a good CSS developer. It's all about building a good mental model of how CSS works.&lt;/li&gt;
&lt;li&gt;At the same time, it's valuable to know a good quantity of CSS properties, so that we are able to use them when needed, like a toolbox.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope that's non-controversial. Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrap methodology
&lt;/h2&gt;

&lt;p&gt;Bootstrap has been used by 81% of this survey respondents. Historically, it is &lt;strong&gt;the&lt;/strong&gt; CSS framework.&lt;/p&gt;

&lt;p&gt;Let's define Bootstrap users categories :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;%&lt;/th&gt;
&lt;th&gt;Opinion&lt;/th&gt;
&lt;th&gt;Code name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;51.7%&lt;/td&gt;
&lt;td&gt;used it but would not use again&lt;/td&gt;
&lt;td&gt;The ex-users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;29%&lt;/td&gt;
&lt;td&gt;used it, would use it again&lt;/td&gt;
&lt;td&gt;The lovers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16.3%&lt;/td&gt;
&lt;td&gt;heard of it but are not interested&lt;/td&gt;
&lt;td&gt;The indifferent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.7%&lt;/td&gt;
&lt;td&gt;did not try it but are interested&lt;/td&gt;
&lt;td&gt;The curious&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.5%&lt;/td&gt;
&lt;td&gt;never heard of it&lt;/td&gt;
&lt;td&gt;The uninformed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Who do you think will have the best native CSS knowledge?&lt;/p&gt;

&lt;p&gt;So, let's look at what the data explorer tells us, with the exemple of the scroll snap properties. Here's a close-up on a specific cell:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AF6o2b6i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkb9pqgi650464gbpzfi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AF6o2b6i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkb9pqgi650464gbpzfi.png" alt="26% of bootstrap user have used scroll snap properties" width="880" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's how you read it: overall, 34% of this survey respondents used scroll snap properties. However, if you look only at bootstrap lovers, only 26% also used scroll snap, so 8 points less.&lt;/p&gt;

&lt;p&gt;So here's what I've done : in a &lt;a href="https://docs.google.com/spreadsheets/d/1R_FNL93XDzFRNXLUYo4IYuCKu5lIYFWIBmVmeJ2ln9M/edit?usp=sharing"&gt;horrible document that you don't need to open&lt;/a&gt;, I've notated these variations for the 53 presented properties, and for our 5 types of developers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KNWx7tYJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c54fect77kh05jh3obgk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KNWx7tYJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c54fect77kh05jh3obgk.png" alt="" width="880" height="55"&gt;&lt;/a&gt;&lt;/p&gt;
As explained before, bootstrap lovers use less scroll-snap (-8 points). But the ex-users and the indifferent use it more that the global population.



&lt;h2&gt;
  
  
  Bootstrap results
&lt;/h2&gt;

&lt;p&gt;Here are our five developers categories, from "less native CSS friendly" to "most native CSS friendly":&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code name&lt;/th&gt;
&lt;th&gt;Native CSS knowledge variation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The uninformed&lt;/td&gt;
&lt;td&gt;-11 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The curious&lt;/td&gt;
&lt;td&gt;-9 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The lovers&lt;/td&gt;
&lt;td&gt;-2 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The indifferent&lt;/td&gt;
&lt;td&gt;no variation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The ex-users&lt;/td&gt;
&lt;td&gt;+2 points&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The uninformed
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;uninformed&lt;/strong&gt; (who don't know what bootstrap is) category is correlated with a poor native CSS knowledge score: &lt;strong&gt;-11 points&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Personal theory: Bootstrap is so widely used that if you don't know about it (only 0.5% of respondents), you are probably new to CSS. So it makes sense you don't know a lot about native CSS yet.&lt;/p&gt;

&lt;p&gt;Please keep in mind that personal theories are theories. And personal.&lt;/p&gt;

&lt;h3&gt;
  
  
  The curious
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;curious&lt;/strong&gt; (who are interested in discovering it) category is also correlated with a decrease of &lt;strong&gt;-9 points&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Personal theory: they might also be beginners who did not have the time to try it yet. They want to try it because it's very popular and it's too soon for them to decide to pass on it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The lovers
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;lovers&lt;/strong&gt; (who used it and would use it again) are doing much better, but still &lt;strong&gt;-2 points&lt;/strong&gt; below the average. &lt;/p&gt;

&lt;p&gt;Personal theory: they know a lot more than the uninformed and the curious because they may been coding with bootstrap (among  other tools) for years and gathered lots of CSS knowledge along the way. Still, the usage of Bootstrap doesn't facilitate discovering new CSS features, or Boostrap is good enough for what they do and they don't care as much (or don't have the time to care!).&lt;/p&gt;

&lt;h3&gt;
  
  
  The indifferent
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;indifferent&lt;/strong&gt; (who know about Bootstrap but are not intersted) perform like the &lt;strong&gt;average&lt;/strong&gt; population.&lt;/p&gt;

&lt;p&gt;Personal theory: deciding you are not interested in a tool means you have a sufficient understanding of what are CSS challenges to decide that Bootstrap is not for you. Other tool might be stealing the attention too, but it does not prevent the indifferent from discovering native CSS features.&lt;/p&gt;

&lt;h3&gt;
  
  
  The ex-users
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;ex-users&lt;/strong&gt; (who used Bootstrap but would not used it again) do better than the average : &lt;strong&gt;+2 points&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Personal theory: learning a CSS framework and deciding to stop using it is a long process, so they have substential experience.  They said goodbye to Bootstrap because their approach of CSS evolved (and CSS evolved itself, allowing this move for some Bootstrap's users). They even may have witness the long transformation of CSS through the years. They decided this tool is not for them anymore and use modern native CSS more. Also, you don't always choose your tools: they could have been asked to use Bootstrap by an employer or a client, while still investing in native CSS knowledge in parallel.&lt;/p&gt;

&lt;p&gt;Here are the details grouped by categories:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lg-OQ9Pt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/td6u81q7asz5r52y8qbf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lg-OQ9Pt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/td6u81q7asz5r52y8qbf.png" alt="Details of the results grouped by categories" width="880" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The biggest gap (-8 points) between the ex-users and the lovers is the interaction category (scroll-snap, touch actions, overscroll-behavior...).&lt;/p&gt;

&lt;p&gt;I think it should also be noted that the lovers category is correlated with a lesser knowledge of accessibility related CSS features (-5 points compared to the ex-users).&lt;/p&gt;

&lt;h2&gt;
  
  
  Tailwind methodology
&lt;/h2&gt;

&lt;p&gt;Now let's talk about the new boss in CSS town.&lt;/p&gt;

&lt;p&gt;First, our users categories:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;%&lt;/th&gt;
&lt;th&gt;Opinion&lt;/th&gt;
&lt;th&gt;Code name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;36.4%&lt;/td&gt;
&lt;td&gt;used it, would use it again&lt;/td&gt;
&lt;td&gt;The lovers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;td&gt;heard of it but are not interested&lt;/td&gt;
&lt;td&gt;The indifferent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;td&gt;did not try it but are interested&lt;/td&gt;
&lt;td&gt;The curious&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.8%&lt;/td&gt;
&lt;td&gt;used it but would not use again&lt;/td&gt;
&lt;td&gt;The ex-users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4.1%&lt;/td&gt;
&lt;td&gt;never heard of it&lt;/td&gt;
&lt;td&gt;The uninformed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Who do you think will perform better this time?&lt;/p&gt;

&lt;h2&gt;
  
  
  Tailwind results
&lt;/h2&gt;

&lt;p&gt;The order has changed! Indeed, the lovers now perform better than the indifferent.&lt;/p&gt;

&lt;p&gt;And the numbers vastly changed too.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code name&lt;/th&gt;
&lt;th&gt;Native CSS knowledge variation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The uninformed&lt;/td&gt;
&lt;td&gt;-9 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The curious&lt;/td&gt;
&lt;td&gt;-5 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The indifferent&lt;/td&gt;
&lt;td&gt;+1 point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The lovers&lt;/td&gt;
&lt;td&gt;+2 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The ex-users&lt;/td&gt;
&lt;td&gt;+6 points&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The uninformed
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;uninformed&lt;/strong&gt; (who don't know what tailwind is) category is correlated with a poor native CSS knowledge score: &lt;strong&gt;-9 points&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Personal theory: same as people who don't know about Bootstrap. If you don't know about Tailwind you may be just starting to discover the CSS ecosystem. But you could also have years of experience and not be really informed about recent CSS news, which might be why this is "only" 9 points below the average (while for Bootstrap it was 11).&lt;/p&gt;

&lt;h3&gt;
  
  
  The curious
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;curious&lt;/strong&gt; (who are interested in discovering Tailwind) category is also correlated with a decrease of &lt;strong&gt;-5 points&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Personal theory: It's less than with Bootstrap (-9 points), but the logic could be the same. If you did not try this hugely popular tool yet or did not have enough perspective to decide to pass on it, you might still be discovering CSS, so it makes sense that you don't know everything about native CSS either. Still, it's less than with Bootstrap. If you heard about Tailwind, it means that you're interested in the current state of CSS, while you could have heard of Bootstrap a long time ago.&lt;/p&gt;

&lt;h3&gt;
  
  
  The indifferent
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;indifferent&lt;/strong&gt; (who know about Tailwind but are not intersted) do a little better than the average: &lt;strong&gt;1 point&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Personal theory: same as Bootstrap. These developers have enough experience to judge if a tool would be interesting to them or not. With this experience comes an good knowledge of native CSS, too, just above the average. But...&lt;/p&gt;

&lt;h3&gt;
  
  
  The lovers
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;lovers&lt;/strong&gt; (who used Tailwind and would use it again) are in completly different position than earlier. With Bootstrap, they knew less (-2 points), but with Tailwind, they know more : &lt;strong&gt;+2 points&lt;/strong&gt;! Even more than the indifferent.&lt;/p&gt;

&lt;p&gt;Personal theory: contrary to what is sometimes said, loving Tailwind is not correlated with a lesser knowledge of native CSS features. First, let's remember that with its utility classes, Tailwind uses an approach that is closer to native CSS than Bootstrap. So a Tailwind user knows about things like flex, whereas a Bootstrap user would use a "column" class (which is actually flexbox in disguise and has nothing to do with actual CSS columns...). Then, there's the fact that Tailwind is a recent tool. If you read articles about it, there's almost no way that you don't read articles about native CSS improvements too. It's part of the modern ecosystem. That being said...&lt;/p&gt;

&lt;h3&gt;
  
  
  The ex-users
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;ex-users&lt;/strong&gt; (who used Tailwind but would not used it again) perform much better than the average : &lt;strong&gt;+6 points&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Personal theory: while Tailwind users are part of a modern ecosystem and know their CSS, well, people who turned their back on Tailwind seem to know more. First, Tailwind does not (nor claims to) solve or cover everything. Some modern CSS features, like :has, container queries, cascade layers, @supports queries... just require you to know them natively to be used at their full potential. That doesn't mean that Tailwind users don't know about them and can't use both, but developers who were dissatisfied with the Tailwind approach simply seem to invest more in native CSS understanding. That doesn't make them better people, but their toolbox seems to be wider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dlZj4m7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/78nyt6924tgcrrzy23vc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dlZj4m7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/78nyt6924tgcrrzy23vc.png" alt="Details of the results grouped by categories" width="880" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, the biggest gap between the ex-users (-8 points) and the lovers is the selectors category, which contains &lt;code&gt;::marker&lt;/code&gt;, &lt;code&gt;:has&lt;/code&gt; and &lt;code&gt;:where&lt;/code&gt;. Tailwind lovers don't use them very much.&lt;/p&gt;

&lt;p&gt;Once again, there is also a huge gap in the accessibility deparment: while Tailwind lovers do perform better than the average (+2 points), the ex-users perform much better (+9 points).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this little experiment was interesting to you. This is not a scientific study reviewed by peers, so please take with a grain of salt, though I did my best with what I had. Don't forget about the sample bias: people participating to a CSS survey cannot be representative of all developers in the world.&lt;/p&gt;

&lt;p&gt;Here are some possible conclusions I submit to you:&lt;/p&gt;

&lt;h3&gt;
  
  
  About Bootstrap
&lt;/h3&gt;

&lt;p&gt;Bootstrap is on the decline, and maybe that's ok. It has been a part of a lot of developer's journeys, but still using it today correlates with a lesser knowledge of valuable CSS features. It's not a bad tool and saved many developers back in the days, but it now struggles to stay relevant.&lt;/p&gt;

&lt;p&gt;I don't want people to move away from Bootstrap if they are good with it: the only thing that matters is always the quality of what we're building. They just should be aware that there's a lot more to CSS today (and a lot of them already are, I'm sure).&lt;/p&gt;

&lt;h3&gt;
  
  
  About Tailwind
&lt;/h3&gt;

&lt;p&gt;No, someone loving Tailwind does not make them ignorant about "actual CSS". They use a modern CSS tool, and gathered substential native CSS knowledge along the way. They may have learn native CSS recently and their knowledge could be more up to date than someone who knew a lot about CSS a decade ago and did not keep up to date.&lt;/p&gt;

&lt;p&gt;However, they should also be conscious that mastering Tailwind is not and cannot be mastering CSS, if such a thing exists. Some features simply can't translate to Tailwind. It does not prevent to write good CSS with Tailwind, but it narrows the theorical toolbox size. Tailwind users eager to keep learning could reinvest the motivation that made them learn Tailwind to continue learning about native CSS features, which are there to stay and will transfer from tool to tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  About native CSS
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/bcalou/the-era-of-no-hacks-css-287l"&gt;2022 has been a great year for CSS&lt;/a&gt; and I feel that knowing about these native features is a powerful asset for any developer.&lt;br&gt;
Of course, it does not replace a deep understanding of CSS logic, which is not just a list of properties, but it provides a great toolbox to overcome various challenges.&lt;/p&gt;

&lt;p&gt;For both Bootstrap and Tailwind, people who knew more about native CSS were also the ones who had actually tried the framework. So maybe don't reject every tool based on some purity principle: discovering new ways of writing CSS — even if you realize they don't suit you in the end — may be valuable and could shed a new light on how you write native CSS.&lt;/p&gt;

&lt;p&gt;What are your thought on this? If you reach any different conclusions, let me know. Please be respectful to everyone, it's only CSS ;)&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>css</category>
      <category>tailwindcss</category>
      <category>bootstrap</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Paris Web 2022 — Jour 2, le récap !</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Fri, 14 Oct 2022 07:58:33 +0000</pubDate>
      <link>https://dev.to/bcalou/paris-web-2022-jour-2-le-recap--47nj</link>
      <guid>https://dev.to/bcalou/paris-web-2022-jour-2-le-recap--47nj</guid>
      <description>&lt;p&gt;Suite et fin de mes aventures chez Paris Web, avec les 8 conférences du deuxième jour (et toujours des petites étoiles &lt;strong&gt;subjectives&lt;/strong&gt; pour démarquer mes préférées).&lt;/p&gt;

&lt;p&gt;Voir &lt;a href="https://www.paris-web.fr/2022/07.php"&gt;le programme complet du jour 2&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Bien doser l'utilisation d'ARIA pour éviter les catastrophes ⭐⭐
&lt;/h2&gt;

&lt;p&gt;Une première présentation donnée par deux personnes : une voyante et une non-voyante (utilisant pour la présentation une barette braille).&lt;/p&gt;

&lt;blockquote&gt;
Nous sommes collègues. Il nous arrive souvent de regarder le même site mais de ne pas voir la même chose.
&lt;/blockquote&gt;

&lt;p&gt;Sophie et Bart définissent ARIA comme un moyen permettant de modifier l'&lt;em&gt;accessibility tree&lt;/em&gt; (que vous pouvez voir dans le dev tools au même titre que le &lt;em&gt;DOM tree&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Mais son utilisation est bien souvent maladroite : &lt;code&gt;aria-label&lt;/code&gt; qui masque le contenu réel, &lt;code&gt;aria-live&lt;/code&gt; sur un carrousel qui interrompt en permanence le flux normal de lecture...&lt;/p&gt;

&lt;p&gt;Jusqu'au paroxysme : un hopital belge dont le &lt;code&gt;body&lt;/code&gt; possédait un attribut &lt;code&gt;aria-hidden&lt;/code&gt;...&lt;/p&gt;

&lt;blockquote&gt;
Dans les audits, on demande plus souvent d'effacer de l'aria que d'en ajouter.
&lt;/blockquote&gt;

&lt;p&gt;Et donc un énième rappel : ARIA complète les informations du HTML, mais c'est bien la bonne écriture de ce dernier à la base qui garantit la bonne accessibilité.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gq_y9PDQgLw?start=697"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  2. DesignGouv : insuffler une culture du design au sein de l'État ⭐
&lt;/h2&gt;

&lt;p&gt;L'occasion d'abord de découvrir le nouveau site présentant le &lt;a href="https://accessibilite.numerique.gouv.fr/"&gt;référentiel général d'amélioration de l'accessibilité&lt;/a&gt;, beaucoup plus sympathique que l'ancien.&lt;/p&gt;

&lt;p&gt;Une autre ressource intéressante : &lt;a href="https://observatoire.numerique.gouv.fr/observatoire/"&gt;l'observatoire de la qualité des démarches en ligne&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Depuis 2021, l'équipe de DesignGouv est intervenu sur 112 projets, auprès de 14 ministères. Une belle performance dont on aurait aimé voir plus de détails concrets.&lt;/p&gt;

&lt;p&gt;Et un rappel simple mais important :&lt;/p&gt;

&lt;blockquote&gt;Plus on créé de nouveaux outils, plus il y en a à maintenir.&lt;/blockquote&gt;

&lt;p&gt;Un passage à noter lors des questions-réponses : le gouvernement reccommande-t-il les outils de surcouche d'accessibilité (que certains spécialistes avait osé critiqué, avant d'être poursuivis par les éditeurs) ? La réponse est donnée : non. Applaudissements nourris.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ym2sI8Jlu6A?start=4314"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Le making-of du RGESN : tout savoir sur le référentiel d’écoconception des services numériques ⭐⭐
&lt;/h2&gt;

&lt;p&gt;Une conférence très spécifique, non pas sur ce nouveau référentiel lui-même, mais sur les coulisses de sa conception.&lt;/p&gt;

&lt;p&gt;Plus de cent bénévoles, des centaines de critères ramenés au nombre final de 79, pour une version 1 qui devrait sortir ce mois-ci (en voici la &lt;a href="https://ecoresponsable.numerique.gouv.fr/publications/referentiel-general-ecoconception/"&gt;version bêta&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Le format est très proche du RGAA (le référentiel pour l'accessibilité), et pour cause : les deux projets ont des intervenants communs.&lt;/p&gt;

&lt;p&gt;La &lt;a href="https://www.vie-publique.fr/loi/278056-loi-15-novembre2021-reen-reduire-empreinte-environnementale-du-numerique"&gt;loi visant à réduire l'empreinte environnementale du numérique en France de 2021&lt;/a&gt; n'impose pas encore le respect de ce nouveau référentiel. Il n'y a encore aucune obligation légale à ce sujet.&lt;/p&gt;

&lt;p&gt;Et enfin, pour vous donner une idée, le nouveau site de l'ADEME (agence de la transition écologique) respecte ce référentiel à 70%.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gq_y9PDQgLw?start=7824"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Designer l'urgence ⭐⭐⭐
&lt;/h2&gt;

&lt;blockquote&gt;Designer dans l'urgence en mode pompier VS designer l'urgence &lt;em&gt;avec&lt;/em&gt; des pompiers&lt;/blockquote&gt;

&lt;p&gt;Une conférence drôle et passionnante pour répondre à une question très sérieuse : comment aborder le design lorsque des vies sont en jeu ?&lt;/p&gt;

&lt;p&gt;Pour reprendre en main le système d'information des pompiers, Julien s'est immergé dans le métier, et après son témoignage, vous ne pourrez plus dire que la recherche UX est trop difficile à mettre en œuvre dans votre secteur.&lt;/p&gt;

&lt;p&gt;Le monde de l'urgence est fait de contraintes physiques et mentales imprédictibles. Sous le choc d'un accident, même une interface applicative d'apparence simple ("êtes-vous témoin ou victime" ?) n'a plus rien d'évident.&lt;/p&gt;

&lt;p&gt;L'occasion également de tordre le cou au mythe du "produit minimum viable" (MVP). Une méthode excellente dans nombre de cas, mais tout simplement inapplicable lors de la refonte d'un service aussi critique : quand on sauve des vies, on ne peut pas commencer par la "version simple".&lt;/p&gt;

&lt;blockquote&gt;Move fast and don't break things&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gq_y9PDQgLw?start=10167"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Comment Canal+ travaille et intègre l’accessibilité numérique ? ⭐
&lt;/h2&gt;

&lt;p&gt;Depuis un an, Amélien a eu la délicate tâche de sensibiliser les équipes de Canal+ aux enjeux et aux techniques de l'accessibilité.&lt;/p&gt;

&lt;p&gt;Les améliorations sont là, mais on ne peut s'empêcher de constater que même dans une si grosse entreprise, les bases ne sont pas acquises : comment peux-t-on encore être en charge de l'intégration d'un service massivement utilisé tel que myCanal sans se soucier des problèmes de focus, une des bases de l'accessibilité ? Le chemin est long et le recrutement (et donc les formations) doivent évoluer.&lt;/p&gt;

&lt;p&gt;Enfin, je suis interpellé par ce rôle étrange chez Canal+ : &lt;em&gt;Legal Product Manager&lt;/em&gt;, en charge de la vie privée, l'accessibilité et l'éco-conception. Une si grosse entreprise pense-t-elle que ces trois domaines, qui n'ont de commun que l'obligation légale et/ou l'image de l'entreprise, ne mérite pas au moins 3 emplois distincts ?&lt;/p&gt;

&lt;p&gt;Force et courage à Amélien, donc ;)&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gq_y9PDQgLw?start=17964"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Numérique et éthique : l'impossible équation ? ⭐⭐
&lt;/h2&gt;

&lt;p&gt;Même si Audrey et Agnès avouent prêcher un public déjà convaincu ("c'est la première fois qu'on m'applaudit parce que je critique Amazon"), le sinistre tour d'horizon offert ici est nécessaire et percutant.&lt;/p&gt;

&lt;p&gt;200 composants, 50 minerais et 75 kilos de matière première pour produire un téléphone (la production représente 75% des émissions), téléphone dont la durée de vie atteindra en moyenne 2 ou 3 ans et ne sera probablement pas recyclé... Sans parler du travail des enfants.&lt;/p&gt;

&lt;p&gt;Et ce n'est que la partie production : saviez-vous que même si vous n'avez pas de profil Facebook, vous possédez malgré tout un &lt;em&gt;shadow account&lt;/em&gt; ? Que des drônes étaient capable de suivre des manifestants jusqu'à leur domicile, en France ? Que Facebook, encore lui, a joué un rôle déterminant dans le génocide des Rohingya ? Et la liste semble sans fin.&lt;/p&gt;

&lt;p&gt;L'invervention se clôture avec quelques conseils élémentaires : gardez votre téléphone (au moins 7 ans, idéalement). Utilisez le nouvel &lt;a href="https://www.ecologie.gouv.fr/indice-reparabilite"&gt;indice de réparabilité&lt;/a&gt; lors d'un achat. Réparez, et, si vraiment vous devez vous séparer de votre appareil encore en fonctionnement, ne le laissez pas trainer dans un tiroir : vendez ou donnez-le.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gq_y9PDQgLw?start=20357"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Thémiser un design system ⭐
&lt;/h2&gt;

&lt;p&gt;Nous atteignons la fin d'après-midi de ce deuxième jour et je ne vous cache pas que mon cerveau commence à se transformer en compote. 16 conférences, c'est beaucoup.&lt;/p&gt;

&lt;p&gt;En écoutant Matthieu, développeur responsable du design system des outils Proton (Mail, Drive...), je réalise à quel point mon propre travail (puisque je fais la même chose, à plus petite échelle) est difficile à expliquer &lt;em&gt;techniquement&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Car oui, les variables CSS sont géniales, mais quand on rajoute à cela des valeurs par défaut, des valeurs optionnelles, des valeurs configurables par les utilisateurs... Ça devient complexe !&lt;/p&gt;

&lt;p&gt;Matthieu a ainsi théorisé un modèle pour les noms de variables :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--usage-location-state-impact-property
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Une idée m'a particulièrement parlé : un design system est une "rationalisation" du design, et devient ainsi un outil objectif pour challenger toute nouvelle modification des designers ou managers. Pas pour stagner, mais pour assurer au projet de ne pas partir dans tous les sens, ce qui est essentiel à cette échelle.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ym2sI8Jlu6A?start=25385"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  8. URL ; reprenons les bases ⭐⭐
&lt;/h2&gt;

&lt;p&gt;Là, il n'y a plus personne dans ma boîte crânienne, ou plutôt il y a trop de choses, mais cette dernière conférence va fournir son lot d'informations passionnantes.&lt;/p&gt;

&lt;p&gt;Même si vous connaissez les 5 parties d'une URL, les subtitilités d'écriture de chacune d'entre elles réservent des surprises.&lt;/p&gt;

&lt;p&gt;Quels sont les pièges tendus aux utilisateurs grâce aux homoglyphes ? Pourquoi Chrome devrait gentiment s'abstenir de modifier les URLs affichées ? Qu'est ce que le test du bouton du milieu de la souris ?&lt;/p&gt;

&lt;p&gt;On réfléchit rarement aux URLs, qu'on prend pour acquises, mais elles constituent la base du web et on a tendance à minimiser leurs capacités.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/gq_y9PDQgLw?start=28739"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  8 bonnes raisons de venir à Paris Web 2023
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Les conférences (une trentaine !) sont de top qualité, j'ai appris beaucoup ;&lt;/li&gt;
&lt;li&gt;Le choix des conférences par les équipes est savamment équilibré entre design, accessibilité et technique pour vous tenir en haleine ;&lt;/li&gt;
&lt;li&gt;Les orateurs et oratrices viennent de tout horizon, vous n'entendrez pas 10 patrons de start-ups à la suite ;&lt;/li&gt;
&lt;li&gt;Une accessibilité remarquable, en cohérence avec le contenu : traduction LSF, vélotypie, traduction de l'anglais vers le français... Et cela a effectivement permis à de nombreuses personnes en situation de handicap d'être présentes ;&lt;/li&gt;
&lt;li&gt;Le prix est plutôt accessible pour un événement de ce type (surtout si vous demandez à votre boîte de participer) ;&lt;/li&gt;
&lt;li&gt;Pardonnez-moi d'être terre à terre, mais l'on y mange très bien, même en tant que végétarien, et ce n'est pas négligeable pour mobiliser toute cette concentration ;&lt;/li&gt;
&lt;li&gt;Vous serez en immersion parmis tout un tas de gens qui veulent bien faire comme vous, et ça fait du bien ;&lt;/li&gt;
&lt;li&gt;On pourra se dire bonjour :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;À l'année prochaine !&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>design</category>
      <category>html</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Paris Web 2022 — Jour 1, le récap !</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Wed, 12 Oct 2022 16:48:09 +0000</pubDate>
      <link>https://dev.to/bcalou/paris-web-2022-jour-1-le-recap--5c82</link>
      <guid>https://dev.to/bcalou/paris-web-2022-jour-1-le-recap--5c82</guid>
      <description>&lt;p&gt;Il y a pile une semaine, c'était mon premier Paris Web, et quelle journée ! 8 conférences (&lt;a href="https://www.paris-web.fr/2022/06.php"&gt;parmi les 16 proposées&lt;/a&gt;) passionnantes et variées.&lt;/p&gt;

&lt;p&gt;En voici un récap à chaud, partiel et partial, qui j'espère vous donnera envie pour l'année prochaine !&lt;/p&gt;

&lt;p&gt;J'ai mis des petites étoiles pour faire ressortir mes conférences préférées, mais c'est tout à fait biaisé par mes propres intérêts : je suis impressionné par la qualité de l'ensemble.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. On se lève et on se casse : tour d’horizon d’un travail sans capital ⭐⭐
&lt;/h2&gt;

&lt;p&gt;Ça commence fort dès le matin avec &lt;em&gt;la&lt;/em&gt; présentation politique de la journée.&lt;/p&gt;

&lt;blockquote&gt;Je ne sais pas qui fait 35h par semaine dans la salle, mais moi cela m'est tout à fait insupportable.&lt;/blockquote&gt;

&lt;p&gt;Au-delà des phrases (et du titre) chocs, Maïtané et Thomas ont créé toute une série de visualisations astucieuses pour créer le débat et comparer différentes formes d'activités : salariat, portage salarial, micro-entreprise, coopérative d'activité et d'emploi...&lt;/p&gt;

&lt;p&gt;Dans quelle structure peut-on parler d'argent sans tabou ? Dans laquelle choisit-on ses clients, ou ses collaborateurs ? Quelle structure participe le mieux au bien commun ? Et, pour répondre à cette notion de "sans capital", dans quelles structures les bénéfices nous reviennent-ils le plus directement possible ?&lt;/p&gt;

&lt;p&gt;Pour ma part, une confirmation que le salariat, ce n'est pas trop pour moi, mais aussi un rappel qu'il n'y a pas que le freelance en face !&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/rI35dYvljZo?start=2705"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Concevoir des services éco-responsables en alliant Design de Services et Éco-conception Numérique ⭐
&lt;/h2&gt;

&lt;blockquote&gt;Cela fait 12 ans que je conçois des services, et 12 ans que je les conçois sans me poser la question de l'impact sur la planète.&lt;/blockquote&gt;

&lt;p&gt;La conception centrée sur les utilisateurs est devenue une telle religion qu'il est difficile de le faire entendre : tout ce qui est bon pour les clients et le chiffre d'affaire ne l'est pas forcément pour notre éco-système.&lt;/p&gt;

&lt;p&gt;Une évidence ? Dans certains secteurs, oui, mais pas nécessairement dans le numérique et son illusion de dématérialisation.&lt;/p&gt;

&lt;p&gt;Le design centré sur l'utilisateur est centré sur l'utilisateur... au dépend du reste. Il est temps de prendre un sacré recul pour inclure la conception des services dans une démarche beaucoup plus globale.&lt;/p&gt;

&lt;p&gt;Et pour convaincre les entreprises qui n'y verraient que des contraintes, un seul axe : soit vous prenez le train, soit vous restez passifs face à une évolution inexorable.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/pJuHsOi0q4Y?start=4926"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Animating the Impossible ⭐⭐
&lt;/h2&gt;

&lt;p&gt;C'était une forte promesse, et c'est un succès !&lt;/p&gt;

&lt;p&gt;Je ne connaissais pas la méthode FLIP, qui permet de réaliser des transitions visuelles complexes entre deux états, avec un état final difficile à prévoir (notamment la position exacte de l'élément relativement au point de départ, l'élément pouvant atterir dans un autre endroit du &lt;code&gt;DOM&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;L'idée géniale est donc la suivante, en 4 étapes (F.L.I.P) :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First : stocker la position et les dimensions de l'élément actuel&lt;/li&gt;
&lt;li&gt;Last : placer instantanément l'élément dans sa position finale dans le DOM pour en trouver les dimensions et la position finale (ceci se passe dans la phase de &lt;em&gt;layout&lt;/em&gt;, on ne sollicite pas la phase de &lt;em&gt;paint&lt;/em&gt; et donc c'est invisible !)&lt;/li&gt;
&lt;li&gt;Flip : Inverser l'animation prévue à la base en calculant la différence entre les états &lt;em&gt;First&lt;/em&gt; et &lt;em&gt;Last&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Play : jouer l'animation finale.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Je ne sais pas si j'explique bien, mais c'est à ça que sert la vidéo, non ?&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/pJuHsOi0q4Y?start=8131"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  4. L'industrialisation des designers du web ⭐⭐
&lt;/h2&gt;

&lt;p&gt;Salle comble, c'est manifestement un sujet qui parle à beaucoup.&lt;/p&gt;

&lt;p&gt;25 ans après la phase d'effervescence joyeuse du web, le constat n'est pas réjouissant : les écoles n'enseignent plus les bases des arts plastiques et appliqués. La SNCF mobilise 200 designers pour réaliser une application médiocre. L'esthétique, le sensible et la narration sont mis de côté face à l'assemblage de blocs.&lt;/p&gt;

&lt;p&gt;Et c'est Figma qui va en prendre pour son grade. L'outil révolutionnaire pour les designers est aussi un outil de contrôle idéal pour les managers, assimilable à une ligne de montage surveillée.&lt;/p&gt;

&lt;p&gt;Les designers sont presques dépossédés de leur métier : c'est désormais tout le monde qui peut "chuchoter au curseur du designer" de déplacer ceci, d'agrandir cela.&lt;/p&gt;

&lt;p&gt;"Laissez-nous commiter !", demande Cécile, dans un excellent parallèle avec le processus de développement et ses phases de réflexion solitaires. Figma, c'est parfois un peu comme si les collègues de votre agence vous indiquaient que vous n'aviez pas fermé la parenthèse de votre fonction alors que vous êtes encore en train de coder...&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/rI35dYvljZo?start=11467"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Illectronisme et numérisation des services publics ⭐
&lt;/h2&gt;

&lt;p&gt;L'administration française donne-t-elle les moyens aux citoyens d'accéder à leurs droits et de réaliser leurs démarches obligatoires ?&lt;/p&gt;

&lt;p&gt;Avec 9% de français n'ayant aucun équipement pour accéder à Internet et 7% d'illetrisme en France, il est clair qu'une administration totalement numérique (et même si les services en ligne continuent à s'améliorer) ne répondra pas seule au problème.&lt;/p&gt;

&lt;p&gt;Selon Raphaël, il faut se méfier du tout-numérique, qui cache le fantasme d'un citoyen modèle, qui se fond dans le moule et remplit gentiment son formulaire en ligne. Vision laissant sur le carreau tous les cas particuliers (et ils sont nombreux) et pouvant être source d'une perte d'autonomie et d'humiliation.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/TGnbXfyIbq8?start=324"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Lost in translation ⭐⭐⭐
&lt;/h2&gt;

&lt;p&gt;Manuel me prend par les sentiments avec un sujet cher à mon cœur : HTML, et plus précisément le mystère de l'incompétence globale pour utiliser correctement ce langage.&lt;/p&gt;

&lt;p&gt;Quelle que soit la stack, React ou intégration native, la plupart des erreurs d'accessibilité viennent du HTML. 20 ans à répéter les bases, et pourtant !&lt;/p&gt;

&lt;p&gt;C'est précisément parce que la syntaxe de HTML est simple que ce langage est mal maîtrisé. Car la complexité ne vient pas de la syntaxe : elle vient de la compréhension des structures, de la sémantique, de tout ce qui est invisible dans un design. Et cela, c'est bien plus complexe.&lt;/p&gt;

&lt;blockquote&gt;
Some people just don't care.
&lt;/blockquote&gt;

&lt;p&gt;Certaines personnes s'en fichent-elles tout simplement ? J'ai bien peur qu'il ait raison, mais Manuel ne se veut pas fataliste pour autant. Une conférence très drôle sur &lt;em&gt;le&lt;/em&gt; langage du web.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/TGnbXfyIbq8?start=2828"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Transferts de données : est-ce que je peux encore utiliser des fournisseurs américains ? ⭐⭐
&lt;/h2&gt;

&lt;p&gt;Non.&lt;/p&gt;

&lt;p&gt;Autant le contenu de la conférence est technique pour le profane, autant la conclusion est sans appel. Même si les entreprises naviguent dans un flou règlementaire, soupesant les bénéfices et les risques d'une petite entrave à la règle, la fête est finie.&lt;/p&gt;

&lt;p&gt;L'administration Bush a signé un mandat simple : il permet de faire usage aux USA comme bon leur semble de toute donnée présente (ou transmise) sur leur territoire, même celles récoltées par "hasard" (oui, c'est le mot utilisé).&lt;/p&gt;

&lt;p&gt;Alors, votre prestataire des USA (ou travaillant lui-même avec les USA) pourra vous fournir toutes les précautions contractuelles du monde, cela ne change pas grand chose : face aux contrats, c'est la loi qui gagne.&lt;/p&gt;

&lt;p&gt;Et si une société hors USA a des liens quelconques avec le pays, ce dernier se réserve aussi l'exploitation des données qu'ils pourra récupérer. Les ramifications sont vertigineuses.&lt;/p&gt;

&lt;p&gt;Bref, exit Google Analytics, Mailchimp et les autres. Un petit séisme, en somme.&lt;/p&gt;

&lt;p&gt;Comme dit le diction :&lt;/p&gt;

&lt;blockquote&gt;Il ne faut pas se demander si on va se faire hacker. Il faut se demander &lt;em&gt;quand&lt;/em&gt; on va se faire hacker.&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/TGnbXfyIbq8?start=7667"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Objectifs 2025 de l’accessibilité : quels défis nous attendent ? ⭐
&lt;/h2&gt;

&lt;p&gt;Fin de journée morose, pas à cause des intervenants mais du constat dressé : accessibilité, on n'y est pas, et loin de là.&lt;/p&gt;

&lt;blockquote&gt;
Ne faites pas accessible, vous ne serez jamais inquiété.
&lt;/blockquote&gt;

&lt;p&gt;Avec une obligation récente (2021 pour le secteur public et très grosses entreprises privées) ou même future (2025 pour le reste du secteur privé) et peu ou pas d'amendes conséquentes pour le moment, le chemin pour un web accessible ne fait que commencer.&lt;/p&gt;

&lt;blockquote&gt;
Seuls 20% des 250 démarches les plus utilisées par les français sont accessibles alors que c'est imposé depuis 2012.
&lt;/blockquote&gt;

&lt;p&gt;Le sujet est profond et culturel : est-on prêt, en tant que société, à investir là-dessus ? Les actes ne le prouvent pas actuellement.&lt;/p&gt;

&lt;p&gt;Une remarque est révélatrice : l'un des intervenants estime qu'une personne avec des compétences en la matière n'a pas spécialement plus de chances d'être recrutée qu'une autre. Un bonus sympathique, tout au plus.&lt;/p&gt;

&lt;p&gt;Oui, le sujet est de plus en plus abordé. Mais c'est encore beaucoup trop anecdotique.&lt;/p&gt;

&lt;blockquote&gt;
Toutes les grosses boîtes ont un budget sécurité énorme, et le budget accessibilité ?
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/TGnbXfyIbq8?start=11402"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>a11y</category>
      <category>design</category>
    </item>
    <item>
      <title>Une musique de jeu évolutive grâce à JavaScript</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Thu, 07 Apr 2022 15:15:26 +0000</pubDate>
      <link>https://dev.to/bcalou/une-musique-de-jeu-evolutive-grace-a-javascript-4568</link>
      <guid>https://dev.to/bcalou/une-musique-de-jeu-evolutive-grace-a-javascript-4568</guid>
      <description>&lt;p&gt;Le week-end dernier, j'ai eu le plaisir de composer la musique de &lt;cite&gt;Blobby Zombie&lt;/cite&gt;, un jeu créé en 48h seulement par mon ami Simon et son camarade Pierre-Yves, lors d'une Game Jam organisée par &lt;a href="http://www.hitboxmakers.fr/"&gt;Hitbox Makers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Concevoir et coder un jeu en 48h n'étant visiblement pas assez difficile, ils ont créé un jeu multijoueur en ligne fonctionnel. Bravo à eux !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://glop.legeay.dev/"&gt;Pour jouer, c'est par ici !&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il faut être plusieurs, chacun sur un ordinateur, et tout le monde partage la même partie. Les règles et commandes sont disponibles &lt;a href="https://github.com/GJLOP/gjlop_front/blob/master/README.md#comment-jouer"&gt;ici&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;De mon côté, ces deux jours se sont divisés ainsi :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;7h le premier jour pour la composition de la bande-son&lt;/li&gt;
&lt;li&gt;7h le deuxième jour pour la "programmation musicale"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  La musique
&lt;/h2&gt;

&lt;p&gt;Le jeu repose sur un mécanisme de dernier survivant. Il va donc falloir monter en pression progressivement pour que ruissellent les gouttes de sueur des joueuses et joueurs.&lt;/p&gt;

&lt;p&gt;Avec un brief aussi complet que les trois mots "arcade", "horreur" et "fun", je me lance.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="100%" height="166" src="https://w.soundcloud.com/player/?url=https://soundcloud.com/b-calou/blobby-zombie&amp;amp;auto_play=false&amp;amp;color=%23000000&amp;amp;hide_related=false&amp;amp;show_comments=true&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;show_teaser=true"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Anticipant sur la programmation à venir, j'utilise une structure la plus simple possible : une boucle de 4 accords. À chaque nouveau cycle, un instrument se rajoute.&lt;/p&gt;

&lt;p&gt;Voici un schéma, c'est important pour la suite, et j'aime les schémas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oE2ZFUyd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6o2nm1xy9usa23wj9ri6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oE2ZFUyd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6o2nm1xy9usa23wj9ri6.png" alt="" width="880" height="356"&gt;&lt;/a&gt;&lt;/p&gt;
Les instruments s'empilent de cycle en cycle pour faire monter la pression.






&lt;p&gt;Mais comment accommoder cette montée en pression de plusieurs minutes à une partie qui pourrait se dérouler beaucoup plus vite ?&lt;/p&gt;

&lt;h2&gt;
  
  
  La programmation
&lt;/h2&gt;

&lt;p&gt;Commençons par une adaptation simple : j'avais choisi &lt;strong&gt;130 BPM&lt;/strong&gt; pour la bande son. Passer à &lt;strong&gt;128 BPM&lt;/strong&gt; est un changement quasi-inaudible qui me permet en revanche d'obtenir des cycles de 15 secondes exactement, ce qui sera bien plus sympathique pour coder et déboguer. C'est toujours ça de pris.&lt;/p&gt;

&lt;p&gt;Bon, il nous faut un moyen de sauter de cycle en cycle, par exemple lorsqu'un nouveau joueur se transforme en zombie.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Se_8eQO---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0w2qxarjv6eubq1jsno2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Se_8eQO---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0w2qxarjv6eubq1jsno2.png" alt="" width="844" height="458"&gt;&lt;/a&gt;&lt;/p&gt;
Passer d'une section à l'autre permet d'adapter la situation à l'évolution du jeu.






&lt;p&gt;Puisque mes cycles font 15 secondes, c'est assez facile à calculer.&lt;/p&gt;

&lt;p&gt;Si je suis au cycle 2 et que je souhaite avancer au cycle 3, je peux calculer qu'il faut avancer à 30 secondes dans le morceau (le cycle 1 commençant à 0 seconde, et le cycle 2 à 15 secondes).&lt;/p&gt;

&lt;p&gt;C'est exactement ce que fait cette première démo. À chaque fois que vous cliquerez sur le bouton "Sauter", vous serez emmené au début de la section suivante :&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/XWVZJKR?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Fludifier les sauts de cycles
&lt;/h3&gt;

&lt;p&gt;Si vous jouez un peu avec, vous pouvez probablement entendre que le résultat n'est pas très satisfaisant.&lt;/p&gt;

&lt;p&gt;Il y a deux raison à cela :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sauter au début du cycle interrompt le rythme que vous pouvez entendre dès le début et tout au long du morceau (cette note unique et répétitive)&lt;/li&gt;
&lt;li&gt;sauter au début du cycle suivant interrompt la &lt;strong&gt;progression d'accords&lt;/strong&gt; et la fait recommencer au début, ce qui n'est pas du tout naturel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La progression d'accords, c'est simplement l'enchaînement des 4 accords qui donne sa structure au morceau. On entend cette progression à partir du deuxième cycle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NJpj1q2m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1k3jjknfc3weeq0xm3e3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NJpj1q2m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1k3jjknfc3weeq0xm3e3.png" alt="" width="880" height="206"&gt;&lt;/a&gt;&lt;/p&gt;
Voici un cycle au complet : 4 accords qui font peur s'enchaînent sur 8 mesures.





&lt;p&gt;On va simplifier un peu (beaucoup) le nom des accords et les appeler C, G, C et F (do, sol, do et fa).&lt;/p&gt;

&lt;p&gt;On peut ainsi mettre à jour notre schéma, pour représenter cette progression à partir du deuxième cycle :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XK3m_C5l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ys1lgg0gpl4v3cmt3yqk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XK3m_C5l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ys1lgg0gpl4v3cmt3yqk.png" alt="" width="880" height="365"&gt;&lt;/a&gt;&lt;/p&gt;
À l'exception de la note unique à la basse et de la batterie qui est uniquement rythmique, chaque nouveau cycle se base sur la même progression d'accords.






&lt;p&gt;Le problème, donc, c'est que si nous passons du milieu du cycle 3 au début du cycle 4, par exemple, nous risquons de faire ça :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xhISH9vK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzcgjco3yu1btjifar91.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xhISH9vK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzcgjco3yu1btjifar91.png" alt="" width="880" height="358"&gt;&lt;/a&gt;&lt;/p&gt;
On saute du deuxième accord de la section 3 vers le premier accord de la section 4.






&lt;p&gt;Patatra, la progression d'accords est cassée. Alors que nous nous préparions à entendre C puis F pour finir le cycle 3, nous reprenons la progression au départ : C, puis G à nouveau ! Et si on enchaîne vite les cycles, on entend quasiment que le premier accord en permanence.&lt;/p&gt;

&lt;p&gt;Or le cerveau est très doué pour s'habituer à une progression d'accords bien spécifique, et toute déviation est troublante pour l'auditeur (ce que certains compositeurs peuvent utiliser à leur avantage, mais c'est une autre histoire).&lt;/p&gt;

&lt;p&gt;Pour remédier à cette violation rythmique et harmonique intolérable à l'oreille, le remède est simple : il ne faut pas aller au début du cycle suivant, mais à l'instant du cycle suivant qui correspond à l'instant actuellement joué.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QBuguwpX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oiyn8e1h02s8oweugaaj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QBuguwpX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oiyn8e1h02s8oweugaaj.png" alt="Image description" width="754" height="308"&gt;&lt;/a&gt;&lt;/p&gt;
Cette fois, on part du deuxième accord du cycle pour arriver sur le deuxième accord du suivant.






&lt;p&gt;Techniquement, c'est presque plus simple que la première version : au lieu de calculer le début de la section suivante, nous allons ajouter 15 secondes — la durée d'un cycle — à la position de lecture.&lt;/p&gt;

&lt;p&gt;Par exemple, si la musique a commencé depuis 5 secondes, nous pouvons sauter jusqu'à 5 + 15 = 20 secondes (alors que le début du cycle 2 est à 15 secondes).&lt;/p&gt;

&lt;p&gt;Essayez et comparez. Le résultat vous semble-t-il moins abrupt ?&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/JjMpGzm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Alors, attention, j'ai dit que les transitions étaient moins abruptes, pas parfaites ! Selon le moment où vous avancez, l'arrivée de tel ou tel instrument peut tout de même sauter aux oreilles. Mais la structure rythmique et harmonique est sauve, et c'est déjà beaucoup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Masquer la transition
&lt;/h3&gt;

&lt;p&gt;Pour améliorer encore l'effet, voici la botte secrète : un bon gros son bien énergique, qui va venir déguiser notre saut dans le morceau, en plus d'annoncer à tous les joueurs qu'il vient d'y avoir du grabuge.&lt;/p&gt;

&lt;p&gt;Ce son, c'est ce que j'appelle le &lt;em&gt;hit&lt;/em&gt;. En jouant le &lt;em&gt;hit&lt;/em&gt; au bon moment, ce dernier occupe tout l'espace sonore et va permettre aux sauts de s'effectuer "discrètement". Tous les coups sont permis...&lt;/p&gt;

&lt;p&gt;Voici le résultat.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/JjMpKjd?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Ce n'est pas encore parfait, mais compte tenu du timing serré, c'est déjà pas mal !&lt;/p&gt;

&lt;h3&gt;
  
  
  Harmoniser le &lt;em&gt;hit&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Finissons avec une petite touche cosmétique.&lt;/p&gt;

&lt;p&gt;Actuellement, le &lt;em&gt;hit&lt;/em&gt; est toujours le même son. Ce ne sont pas n'importe quelles notes qui sont jouées : elles correspondent précisément à celle du premier accord de la progression.&lt;/p&gt;

&lt;p&gt;Autrement dit, elles sonnent très bien sur le premier accord.&lt;/p&gt;

&lt;p&gt;Sur les autres accords, le rendu n'est pas choquant, car le &lt;em&gt;hit&lt;/em&gt; est un élément bien séparé du reste de la musique. Mais qu'est ce que ça donnerait si le &lt;em&gt;hit&lt;/em&gt; était harmonisé avec l'accord actuellement joué ?&lt;/p&gt;

&lt;p&gt;Pour cela, j'ai exporté 4 &lt;em&gt;hits&lt;/em&gt; différents. Ensuite, il suffit de faire correspondre le &lt;em&gt;hit&lt;/em&gt; avec l'accord courant. Si on est dans le dernier quart d'un cycle, c'est qu'il faut jouer le &lt;em&gt;hit&lt;/em&gt; qui correspond au dernier accord.&lt;/p&gt;

&lt;p&gt;C'est parti !&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/gOovMez?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Cette amélioration passe sans doute inaperçue, c'est d'ailleurs son but, mais je pense qu'elle rajoute une petite couche de satisfaction auditive à l'ensemble.&lt;/p&gt;

&lt;h2&gt;
  
  
  Musique + code = &amp;lt;3
&lt;/h2&gt;

&lt;p&gt;Voici un court extrait du jeu (le dernier saut est assez brusque, mais c'est comme ça !) :&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/HlYkDBsUe14"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;C'est la première fois que je combine ma passion pour la musique et mes connaissances en programmation, et en seulement 48h j'ai pu voir à quel point les possibilités étaient grandes.&lt;/p&gt;

&lt;p&gt;C'est l'occasion de recommander une excellente chaîne YouTube : &lt;a href="https://www.youtube.com/channel/UCeZLO2VgbZHeDcongKzzfOw"&gt;8-bit Music Theory&lt;/a&gt;. Je ne comprends pas la moitié de ce qu'il raconte, mais ses analyses de bande-sons vidéoludiques me fascinent et m'ont fortement influencé pour cette petite expérience.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="//glop.legeay.dev/"&gt;Blobby Zombie&lt;/a&gt;, le jeu&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/GJLOP/gjlop_front"&gt;Le code source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://soundcloud.com/bastien-calou/blobby-zombie"&gt;La bande-son&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>music</category>
    </item>
    <item>
      <title>The era of no-hacks CSS</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Mon, 28 Mar 2022 06:57:12 +0000</pubDate>
      <link>https://dev.to/bcalou/the-era-of-no-hacks-css-287l</link>
      <guid>https://dev.to/bcalou/the-era-of-no-hacks-css-287l</guid>
      <description>&lt;p&gt;If you learned CSS anytime before 2020, chances are that you collected a lot of little hacks along the way. You know, things like centering, styling form elements, sizing images, wrapping text... Black magic things. Incredibly specific behaviors that you look up in google, hoping that someone wrote a blog post about it, and that will ruin your day otherwise.&lt;/p&gt;

&lt;p&gt;A lot of my colleagues look at CSS with utter suspicion, because they had to learn it 10 years ago, before moving to back-end programming, project management, design or even "JS-only front-end".&lt;/p&gt;

&lt;p&gt;Lot of people even look at developers using CSS like strange creatures, the ones who tamed the beast, the ones who could see through an impenetrable jungle of CSS hacks and make sense of it, at the expense of their own sanity.&lt;/p&gt;

&lt;p&gt;But the truth is this:&lt;/p&gt;

&lt;h2&gt;
  
  
  We don't like CSS hacks
&lt;/h2&gt;

&lt;p&gt;Personally, I hate them. They might be fun to show to a student or colleagues struggling with a bit of strange layout behavior (tadaaaa !), but I despite them, because they're just workarounds, or ugly non-standards way of using properties that never were made for this. They are anything but good code. They are enigmatic code, maintenance nightmare, and probably the worse, they create a mistrust towards CSS that in the end hurts the whole ecosystem.&lt;/p&gt;

&lt;p&gt;And that's how you get Peter Griffin struggling with CSS, vertical alignment jokes... Heck, I even have the ironic "CSS is awesome" mug as my twitter cover image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcs6ypfjkv8kok606kcfe.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcs6ypfjkv8kok606kcfe.jpeg" alt="A mug with "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These jokes helped us cope with the harsh reality of CSS for years, but the truth is that they are now out of date. If anything, using them is like publicly announcing:&lt;/p&gt;

&lt;blockquote&gt;I learned CSS 10 years ago, hated it and never tried again! (insert miracle CSS-in-JS library presentation here)&lt;/blockquote&gt;

&lt;p&gt;Yep, that Twitter banner definitely has to go...&lt;/p&gt;

&lt;h2&gt;
  
  
  Will 2022 start the era of no-hacks CSS?
&lt;/h2&gt;

&lt;p&gt;A lot is happening to CSS these days, and I feel 2022 could be the year we get rid of CSS hacks, or at the least the year we stop considering them "everyday CSS".&lt;/p&gt;

&lt;p&gt;Just take a look at &lt;a href="https://twitter.com/bramus/status/1475583226165055501" rel="noopener noreferrer"&gt;this thread&lt;/a&gt;, for exemple.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1475583226165055501-259" src="https://platform.twitter.com/embed/Tweet.html?id=1475583226165055501"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1475583226165055501-259');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1475583226165055501&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Things are moving fast and CSS is becoming a mature language. Even the browsers community is organizing itself to make CSS level-up in the best possible way. See the &lt;a href="https://wpt.fyi/interop-2022" rel="noopener noreferrer"&gt;Interop&lt;/a&gt; initiative, for example.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;accent-color&lt;/code&gt; example
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/accent-color" rel="noopener noreferrer"&gt;accent-color&lt;/a&gt; property is quite simple and one of my favorite new things.&lt;/p&gt;

&lt;p&gt;Its unique purpose is to allow you changing the color of the native form inputs: checkboxes, radio buttons, range selectors... Check it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;crimson&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/XWVpOxB?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;That's one line of CSS and zero hacks.&lt;/p&gt;

&lt;p&gt;For years (dare I say decades?), CSS developers achieved that by actually hiding the native input and creating a fake input with the desired appearance. Both were linked with the good old &lt;code&gt;:checked&lt;/code&gt; pseudo-class. This was never normal code. It was a dirty and error-prone hack, waiting patiently to be replaced by a clean solution. &lt;/p&gt;

&lt;h2&gt;
  
  
  Leaving hacks behind is also your responsibility
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;accent-color&lt;/code&gt; property is a good example of that. Yes, it's new and &lt;a href="https://caniuse.com/?search=accent-color" rel="noopener noreferrer"&gt;not supported by every browser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Well, I could not care less about this.&lt;/p&gt;

&lt;p&gt;Because CSS is awesome, it will simply ignore &lt;code&gt;accent-color&lt;/code&gt; in older browsers and use the default system colors. Which is very fine (just test the contrasts if your background is not white).&lt;/p&gt;

&lt;p&gt;Even better, as time goes by, more and more people will have a browser supporting this and will see the intended final design. That's progressive enhancement magic: your website is getting better while you're not even working.&lt;/p&gt;

&lt;p&gt;Me not caring about this doesn't mean that everyone won't or even should. Maybe a designer or a manager will decide that it would be nice to have the brand color for inputs, even on older browsers, and I respect that. But that is not only a design question, they are costs and benefits.&lt;/p&gt;

&lt;p&gt;So I will defend the position that hacking the CSS (a hack which can break) for a fraction of the audience (a fraction that will have a great fallback anyway and will diminish with time) is not worth it is most cases.&lt;/p&gt;

&lt;p&gt;I also love flexbox's &lt;code&gt;gap&lt;/code&gt; property, which makes space management SO easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/abEpMOx?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;A decreasing fraction of browser don't support that and will show no gaps between items. Whether you're willing to setup a &lt;a href="https://dev.to/bcalou/flexbox-when-negative-margins-save-the-day-h4i"&gt;negative-margin CSS hack&lt;/a&gt; to handle these cases is another debate to have.&lt;/p&gt;

&lt;p&gt;I started to make peace with the fact that a tiny (and one again, decreasing) fraction of users won't have the spaces. As long as the content is perfectly legible, this doesn't bother me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goodbye hacks
&lt;/h2&gt;

&lt;p&gt;Of course I'm still using hacks, from time to time. But I stopped considering them common CSS.&lt;/p&gt;

&lt;p&gt;CSS is catching up with our clever hacks and is eradicating them by providing standard, robust features. If you use (and advocate for) progressive enhancement techniques where you know that your content is still accessible without every line of intended CSS, you can use these new features at will. You'll feel free, live longer and, I believe, make better websites.&lt;/p&gt;

&lt;p&gt;Share this to a colleague who hates CSS ;) I can't blame you. But this is 2022 and CSS has changed.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Calculs CSS infernaux à partir de données physiques</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Fri, 18 Jun 2021 06:46:26 +0000</pubDate>
      <link>https://dev.to/bcalou/calculs-css-infernaux-a-partir-de-donnees-physiques-4ah9</link>
      <guid>https://dev.to/bcalou/calculs-css-infernaux-a-partir-de-donnees-physiques-4ah9</guid>
      <description>&lt;p&gt;Côté CSS, je suis assez satisfait de l'effet &lt;strong&gt;renversant&lt;/strong&gt; (j'exagère un peu) de survol que j'ai mis en place (voir sur &lt;a href="https://top-livres-2020.netlify.app/" rel="noopener noreferrer"&gt;le site&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faas4r18ot2058ihgvppz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faas4r18ot2058ihgvppz.gif" alt="Les livres pivotent au survol"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il s'agit en fait d'une adaptation d'un projet open source, &lt;a href="//3dbook.xyz"&gt;3dbook.xyz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;L'intérêt de cette adaptation réside dans le fait que j'ai utilisé les variables CSS pour faire le lien entre des données concrètes, comme le nombre de pages, et le rendu CSS final.&lt;/p&gt;

&lt;p&gt;Car tout ça est subtil. L'épaisseur du livre, par exemple, va dépendre bien sûr du nombre de pages, mais aussi de la taille du livre. Un livre de poche de 200 pages vu de près pourra paraître aussi épais qu'un gros livre de 400 pages vu d'un peu plus loin...&lt;/p&gt;

&lt;p&gt;Cela nécessite donc quelques calculs !&lt;/p&gt;

&lt;h2&gt;
  
  
  Les données
&lt;/h2&gt;

&lt;p&gt;Voici les données concrètes qui nous intéressent, par exemple pour le livre &lt;em&gt;Clyde Fans&lt;/em&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt;
&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;23.5&lt;/span&gt;
&lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;488&lt;/span&gt;
&lt;span class="na"&gt;offset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Respectivement :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La largeur et la hauteur du livre en centimètres&lt;/li&gt;
&lt;li&gt;Le nombre de pages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;offset: true&lt;/code&gt; pour préciser que les pages sont plus petites que la couverture elle-même, ce qui est parfois le cas pour les gros livres (voir le gif ci-dessus)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Passer les données à l'élément
&lt;/h2&gt;

&lt;p&gt;Grâce au langage de templating &lt;code&gt;liquid&lt;/code&gt;, je pourrais alors générer des styles inline à partir de ces variables :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width: {{ item.data.width * 10 }}px"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans cet exemple, un livre faisant &lt;code&gt;20cm&lt;/code&gt; de large dans le monde physique fera &lt;code&gt;200px&lt;/code&gt; sur mon site.&lt;/p&gt;

&lt;p&gt;On peut faire en réalité bien plus propre et flexible, en passant ces paramètres aux composant sous forme de variables CSS.&lt;/p&gt;

&lt;p&gt;Voici ce que ça donne :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"book {% if item.data.offset %}book--offset{% endif %}"&lt;/span&gt;
    &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"
      --width: {{ item.data.width }};
      --height: {{ item.data.height }};
      --pages: {{ item.data.pages }};
    "&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La variable &lt;code&gt;offset&lt;/code&gt;, si elle est présente, permet d'ajouter une classe supplémentaire à l'élément &lt;code&gt;.book&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Les 3 autres variables sont passées grâce à l'attribut &lt;code&gt;style&lt;/code&gt;, et sont maintenant disponibles pour chaque élément &lt;code&gt;.book&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note : les variables CSS sont scopées. Chaque élément &lt;code&gt;.book&lt;/code&gt; possède désormais ces 3 variables qui ne sont accessibles qu'à lui-même et ses enfants.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3c6ujt9tot1cx0pz89u0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3c6ujt9tot1cx0pz89u0.png" alt="L'élément du DOM et ses styles CSS"&gt;&lt;/a&gt;&lt;/p&gt;
Les variables sont désormais disponibles dans le scope CSS de l'élément.






&lt;h2&gt;
  
  
  CSS : let the fun begin
&lt;/h2&gt;

&lt;p&gt;Maintenant, nous pouvons utiliser ces variables pour mettre en forme notre livre. Ici, ça se complique et il ne faut pas lésiner sur les commentaires.&lt;/p&gt;

&lt;p&gt;Je vais expliquer seulement quelques lignes du code. On commence avec quelques définitions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* The books will be contained inside a square of this dimension */&lt;/span&gt;
  &lt;span class="na"&gt;--base-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;--base-size-rem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;base-size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.0625rem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;@include&lt;/span&gt; &lt;span class="nd"&gt;medium&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;--base-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;350&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Je souhaite que les livres soient contenus dans un carré de &lt;code&gt;250&lt;/code&gt; pixels de côté (&lt;code&gt;--base-size&lt;/code&gt;). Je décline ensuite cette valeur en &lt;code&gt;rem&lt;/code&gt; (mieux que les pixels), grâce à une petite multiplication.&lt;/p&gt;

&lt;p&gt;La mixin &lt;code&gt;@medium&lt;/code&gt; est une media query qui me permet d'agrandir la taille de base sur des écrans plus larges.&lt;/p&gt;

&lt;p&gt;Notez comme je ne redéclare pas &lt;code&gt;--base-size-rem&lt;/code&gt; dans la mixin &lt;code&gt;@medium&lt;/code&gt;. En effet, &lt;code&gt;--base-size-rem&lt;/code&gt; est dynamiquement calculée à partir de &lt;code&gt;--base-size&lt;/code&gt;. Quand l'une change, l'autre aussi, y compris à l'intérieur d'une media query.&lt;/p&gt;

&lt;p&gt;On continue :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;--is-portrait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;999&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cette syntaxe du démon permet de savoir si le livre est en format paysage ou portrait, et de stocker cette info dans la variable &lt;code&gt;--is-portrait&lt;/code&gt;. (ça fait ça de moins à saisir dans la "base de données").&lt;/p&gt;

&lt;p&gt;Pas très clair ? On décompose.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clamp&lt;/code&gt; est une fonction CSS qui va me donner une valeur entre deux bornes (le premier et le troisième paramètre).&lt;/p&gt;

&lt;p&gt;Par exemple :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;clamp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="nc"&gt;.2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 0.2, car c'est entre les bornes */&lt;/span&gt;
&lt;span class="nt"&gt;clamp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;-15&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 0, car le chiffre du milieu est trop petit */&lt;/span&gt;
&lt;span class="nt"&gt;clamp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* 1, car le chiffre du milieu est trop grand */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notre valeur du milieu à nous, en simplifiant la syntaxe, ressemble à ça : &lt;code&gt;(height - width) * 999&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si le livre est au format portrait, la hauteur est plus grande que la largeur, et donc &lt;code&gt;(height - width)&lt;/code&gt; est positif. La multiplication par &lt;code&gt;999&lt;/code&gt; va nous faire obtenir un nombre très grand, transformé en 1 par les bornes du &lt;code&gt;clamp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;À l'inverse, on obtiendra un nombre négatif si le livre est au format paysage, qui sera ramené à 0 par les bornes du &lt;code&gt;clamp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Et voici comment on obtient un booléen en CSS 🙃 À manier avec précaution, nous sommes d'accord...&lt;/p&gt;

&lt;p&gt;Je peux ensuite utiliser ce booléen pour obtenir d'autres valeurs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxdl4d5juyn8ch76a5mz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxdl4d5juyn8ch76a5mz.png" alt="Les livres en paysage sont trop gros"&gt;&lt;/a&gt;&lt;/p&gt;
Si tous les livres font la même hauteur, ceux qui sont en paysage comme *Panthère* deviennent beaucoup trop gros. D'où l'intérêt du booléen "is-portrait" pour la suite.






&lt;p&gt;Quelle devrait être la hauteur d'un livre s'il est en portrait ? La hauteur du conteneur, soit &lt;code&gt;--base-size-rem&lt;/code&gt;. S'il est en paysage, au contraire, cela devrait être dépendant de largeur, qui elle sera &lt;code&gt;--base-size-rem&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note : l'usage de &lt;code&gt;object-fit: contain&lt;/code&gt; pour contenir l'image n'est pas suffisante ici, car d'autres éléments et pseudo-éléments constitutifs de l'effet final ont besoin de connaître les dimensions exactes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Et c'est ainsi que l'on parvient à des atrocités de ce genre :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* Height is base size if portrait, based on size ratio otherwise */&lt;/span&gt;
  &lt;span class="na"&gt;--height-rem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;is-portrait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;base-size-rem&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;base-size-rem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;base-size-rem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxaoyrw2pf24sctwhaaj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxaoyrw2pf24sctwhaaj.gif" alt="Expression de dégoût"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Allez, on s'accroche une dernière fois, promis. &lt;code&gt;clamp&lt;/code&gt;, on connaît déjà, alors regardons nos bornes. Que remarque t-on si le livre est en mode portrait ? La première borne :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--is-portrait&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--base-size-rem&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;devient simplement &lt;code&gt;--base-size-rem&lt;/code&gt;, puisque &lt;code&gt;is-portrait&lt;/code&gt; vaut 1. Et c'est aussi la valeur de la seconde borne. Si les bornes sont identiques, peut importe la valeur du milieu, le résultat sera &lt;code&gt;--base-size-rem&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Et c'est que l'on souhaite. Pour les livres portrait, la hauteur est la taille du conteneur, tout bêtement.&lt;/p&gt;

&lt;p&gt;Au contraire, pour un livre paysage, la borne du bas deviendra &lt;code&gt;0&lt;/code&gt; grâce à notre booléen. Et donc la valeur du milieu pourra entrer en action. La voici :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--base-size-rem&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--width&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nt"&gt;var&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;--height&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On prend la valeur de base (qui sera donc la largeur), on divise par le ratio entre largeur et hauteur, et hop, on obtient notre hauteur.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fucjyjchvk8436mdejp0d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fucjyjchvk8436mdejp0d.png" alt="Les livres en paysage font désormais une taille raisonnable, car leur dimension "&gt;&lt;/a&gt;&lt;/p&gt;
Les livres en paysage font désormais une taille raisonnable, car leur dimension "principale" devient leur largeur.






&lt;h2&gt;
  
  
  Support navigateur
&lt;/h2&gt;

&lt;p&gt;Quelques navigateurs dignes d'être considérés (Edge 18, Safari 13...), ne prennent pas en charge l'opération CSS &lt;code&gt;clamp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;La mixin suivante permet de détecter ce support, pour mettre en place une solution de fallback avec des calculs un peu moins fins.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@mixin&lt;/span&gt; &lt;span class="nf"&gt;supports-clamp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@supports&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;width&lt;/span&gt;&lt;span class="nd"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;clamp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;0px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;1px&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;2px&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;@content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pour reprendre notre calcul du dessus, on l'utilise ainsi :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.book&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;--height-rem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;base-size-rem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;@include&lt;/span&gt; &lt;span class="nd"&gt;supports-clamp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* Height is base size if portrait, based on size ratio otherwise */&lt;/span&gt;
    &lt;span class="na"&gt;--height-rem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;is-portrait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;base-size-rem&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="nf"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;base-size-rem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;ratio-width-height&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;base-size-rem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si &lt;code&gt;clamp&lt;/code&gt; n'est pas supporté, le navigateur utilisera la première ligne et ignorera tout le reste. Pour quelques utilisateurs, le rendu sera un peu moins subtil, mais le contenu reste lisible et c'est l'essentiel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vers un CSS plus adapté aux calculs visuels ?
&lt;/h2&gt;

&lt;p&gt;Le &lt;a href="https://github.com/bcalou/top-books-2020/blob/master/src/styles/blocs/_book.scss" rel="noopener noreferrer"&gt;code CSS complet du composant&lt;/a&gt; est disponible.&lt;/p&gt;

&lt;p&gt;Tout cela est bien stimulant, mais guère lisible, y compris pour moi-même quelques mois après l'avoir écrit.&lt;/p&gt;

&lt;p&gt;Pour un projet perso, c'est bien sympathique, mais la scalabilité n'est pas au rendez-vous.&lt;/p&gt;

&lt;p&gt;Cela reste pourtant la solution qui me paraît la plus élégante, car elle se repose sur des informations physiques concrètes et ne nécessite pas de manipulations JavaScript qui seraient par nature moins performantes. On peut donc espérer que la syntaxe CSS continue d'évoluer pour permettre ce genre d'opérations avec plus de fluidité.&lt;/p&gt;

&lt;p&gt;Peut-être grâce à &lt;a href="https://houdini.how/about/" rel="noopener noreferrer"&gt;Houdini&lt;/a&gt; ? &lt;/p&gt;

&lt;p&gt;En attendant, il faudra faire fonctionner nos petites cellules grises... Et commenter, beaucoup commenter !&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Optimisation agressive des performances d'un site statique</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Wed, 16 Jun 2021 06:57:00 +0000</pubDate>
      <link>https://dev.to/bcalou/optimisation-agressive-des-performances-d-un-site-statique-3jc9</link>
      <guid>https://dev.to/bcalou/optimisation-agressive-des-performances-d-un-site-statique-3jc9</guid>
      <description>&lt;p&gt;Grâce au &lt;em&gt;pre-rendering&lt;/em&gt; d'Eleventy, &lt;em&gt;Lighthouse&lt;/em&gt; donne déjà à &lt;a href="https://top-livres.netlify.app/" rel="noopener noreferrer"&gt;notre site&lt;/a&gt; le vénérable score de 100 points en performance 💪. Mais si nous essayions d'aller plus loin ? Le simple calcul d'un outil n'est pas une excuse pour ne pas mieux faire !&lt;/p&gt;

&lt;p&gt;Voici les techniques, certaines banales, d'autres plus exotiques, que j'ai l'habitude d'utiliser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy loading des images
&lt;/h2&gt;

&lt;p&gt;C'est désormais d'une simplicité absolue en HTML :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ainsi, les images sont chargées au fil du scroll. HTML mon amour.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft4x7q4sdmt89mvfszc9n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft4x7q4sdmt89mvfszc9n.gif" alt="Les images sont chargées au fil du scroll"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Un autre attribut a récemment fait son apparition, que je m'empresse d'ajouter :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;decoding=&lt;/span&gt;&lt;span class="s"&gt;"async"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;L'attribut &lt;code&gt;decoding="async"&lt;/code&gt; autorise le navigateur à traiter en parallèle le rendu de la page et celui de l'image, ce dernier devenant donc non bloquant.&lt;/p&gt;

&lt;p&gt;L'impact sera faible sur mes images de taille moyenne, mais ça ne mange pas de pain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Picture, source &amp;amp; srcset
&lt;/h2&gt;

&lt;p&gt;Pour les couvertures, trois formats d'image cohabitent : &lt;code&gt;avif&lt;/code&gt;, actuellement supporté par &lt;a href="https://caniuse.com/avif" rel="noopener noreferrer"&gt;Chrome &amp;amp; Opera&lt;/a&gt;, &lt;code&gt;webp&lt;/code&gt;, désormais &lt;a href="https://caniuse.com/webp" rel="noopener noreferrer"&gt;très bien supporté&lt;/a&gt;, et &lt;code&gt;jpeg&lt;/code&gt;, pour les navigateurs un peu à la traîne.&lt;/p&gt;

&lt;p&gt;Le navigateur peut choisir son format préféré grâce au tag &lt;code&gt;picture&lt;/code&gt;, qui contient un tag &lt;code&gt;source&lt;/code&gt; pour chacun des trois formats d'image. Il contient également un tag &lt;code&gt;img&lt;/code&gt; qui sera le seul interprété si le navigateur ne comprend pas &lt;code&gt;picture&lt;/code&gt;. On tire ici parti de la solidité du HTML, qui va simplement ignorer ce qui n'a pas de sens pour lui.&lt;/p&gt;

&lt;p&gt;Notez que les attributs &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;decoding&lt;/code&gt; et &lt;code&gt;alt&lt;/code&gt; se trouvent sur la balise de &lt;em&gt;fallback&lt;/em&gt;, mais qu'ils seront bien pris en compte.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"book__cover"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"dist/smile_350.avif 350w, dist/smile_700.avif 700w"&lt;/span&gt;
    &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 32em) 21.875rem, 15.625rem"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"dist/smile_350.webp 350w, dist/smile_700.webp 700w"&lt;/span&gt;
    &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 32em) 21.875rem, 15.625rem"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/jpeg"&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"dist/smile_350.jpg 350w, dist/smile_700.jpg 700w"&lt;/span&gt;
    &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 32em) 21.875rem, 15.625rem"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"dist/smile_350.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Couverture de Smile"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chaque couverture est donc proposée en &lt;code&gt;avif&lt;/code&gt;, &lt;code&gt;webp&lt;/code&gt; et en &lt;code&gt;jpeg&lt;/code&gt;, mais également avec deux largeurs différentes : &lt;code&gt;350px&lt;/code&gt; et &lt;code&gt;700px&lt;/code&gt;. C'est ce qui est proposé au navigateur grâce à l'attribut &lt;code&gt;srcset&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Enfin, l'attribut &lt;code&gt;sizes&lt;/code&gt; permet au navigateur de connaître la taille d'affichage des images (il faut lui dire, car il ne peut pas le deviner à partir du CSS, pour des raisons d'implémentation). Le contenu de l'attribut s'interprète ainsi :&lt;/p&gt;

&lt;blockquote&gt;
Au dessus de 32em de large pour le viewport, l'image fera 21.875rem de large. Sinon, elle fera seulement 15.625rem de large.
&lt;/blockquote&gt;

&lt;p&gt;Le navigateur connaît la taille du viewport et en déduit la taille de l'image affichée.&lt;/p&gt;

&lt;p&gt;Grâce à toutes les informations à sa disposition, le navigateur peut finalement choisir quelle image utiliser, en fonction des formats supportés, de la taille du viewport, du &lt;em&gt;pixel ratio&lt;/em&gt; de l'écran, du cache, de la qualité de connexion...&lt;/p&gt;

&lt;p&gt;Voici le poids des dix images en fonction du format et de la dimension :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;avif&lt;/th&gt;
&lt;th&gt;webp&lt;/th&gt;
&lt;th&gt;jpeg&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;350px&lt;/td&gt;
&lt;td&gt;🌟147k&lt;/td&gt;
&lt;td&gt;252k&lt;/td&gt;
&lt;td&gt;321k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;700px&lt;/td&gt;
&lt;td&gt;249k&lt;/td&gt;
&lt;td&gt;459k&lt;/td&gt;
&lt;td&gt;624k&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On varie donc du simple au quadruple ! Avec des images plus grandes, la différence sera encore plus importante.&lt;/p&gt;

&lt;h3&gt;
  
  
  Générer les images avec Eleventy
&lt;/h3&gt;

&lt;p&gt;Plutôt être forcé à regarder la saison 29 de Plus belle la vie que de produire à la main toutes les images nécessaires à cette optimisation.&lt;/p&gt;

&lt;p&gt;Pour rappel, on parle de 10 livres * 3 formats * 2 tailles, doit 60 images !&lt;/p&gt;

&lt;p&gt;Non, je souhaite prendre l'image de la meilleure qualité possible, et laisser la machine faire le reste. Et là, merveille : Eleventy propose exactement ce qu'il me faut.&lt;/p&gt;

&lt;p&gt;Nous allons créer un helper &lt;code&gt;bookImage&lt;/code&gt;, que nous appellerons pour chaque item :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight liquid"&gt;&lt;code&gt;&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bookImage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un helper est une fonction qui retourne un template. Elle se déclare ainsi, encore une fois dans le fichier &lt;code&gt;.eleventy.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLiquidShortcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bookImage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bookImage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bookImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;p&amp;gt;Hello world !&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rappel important : Eleventy étant un &lt;strong&gt;générateur de site statique&lt;/strong&gt;, ce JavaScript est exécuté une fois pour toutes lorsque le site est généré, et non pas au runtime côté client. Le but est toujours d'avoir un HTML statique au final.&lt;/p&gt;

&lt;p&gt;Dans notre helper, nous allons utiliser le plugin officiel &lt;a href="https://www.11ty.dev/docs/plugins/image/" rel="noopener noreferrer"&gt;Image&lt;/a&gt;. Ça se passe comme ça :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nc"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`src/img/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fileSlug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jpg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;widths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;350&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;formats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;avif&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jpeg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_site/img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si nous passons un objet &lt;code&gt;book&lt;/code&gt; et que nous avons bien un fichier image correspondant dans &lt;code&gt;src/img/&lt;/code&gt;, cette fonction va générer les 6 images nécessaires.&lt;/p&gt;

&lt;p&gt;Seule bizarrerie à mentionner, le &lt;code&gt;null&lt;/code&gt; dans la liste des largeurs, nécessaire au cas où l'image source fait moins de &lt;code&gt;700px&lt;/code&gt; (la grande taille sera alors la taille originale de l'image, par exemple &lt;code&gt;579px&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Ensuite, et je vous passe les détails d'implémentation, nous allons retourner le template correspondant. Vous savez, le gros bout de code décrit plus haut avec toutes les &lt;code&gt;sources&lt;/code&gt;, &lt;code&gt;srcset&lt;/code&gt;...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;picture class="book__cover"&amp;gt;
  &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
  &amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" alt="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" loading="lazy" decoding="async" /&amp;gt;
&amp;lt;/picture&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Peut-être l'avez vous remarqué, ce helper a de formidable qu'il fait deux choses très importantes à la fois :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;il génère les images nécessaires&lt;/li&gt;
&lt;li&gt;il renvoie le markup associé&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La séparation de ces deux processus est fréquente. Qu'ils soient ici si intriqués facilitera certainement la maintenance.&lt;/p&gt;

&lt;p&gt;Une autre façon de le dire, c'est que le template génère à la volée les images dont il a besoin !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qod4aa6hr9rhbvamrw7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qod4aa6hr9rhbvamrw7.gif" alt="Génération des images"&gt;&lt;/a&gt;&lt;/p&gt;
Le processus peut être désactivé en développement pour gagner du temps.







&lt;h2&gt;
  
  
  CSS critique inline
&lt;/h2&gt;

&lt;p&gt;Actuellement, la cascade du site ressemble à ça :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkkfok90wbb6w9pea0gdc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkkfok90wbb6w9pea0gdc.png" alt="Cascade du site avant optimisation"&gt;&lt;/a&gt;&lt;/p&gt;
J'ai utilisé une simulation "slow 3G" pour forcer le trait






&lt;p&gt;On voit nettement les deux ressources &lt;strong&gt;bloquantes&lt;/strong&gt; que sont le CSS et le JavaScript.&lt;/p&gt;

&lt;p&gt;Contrairement aux images, le CSS et le JavaScript bloquent l'affichage de la page tant qu'ils ne sont pas chargés, parsés et exécutés.&lt;/p&gt;

&lt;p&gt;Le client récupère le HTML, puis effectue deux nouvelles requêtes pour récupérer le CSS et le JavaScript. Il ne se passera rien d'autre pendant ce temps. La page restera blanche et les images ne commenceront pas à se charger. Quel gâchis !&lt;/p&gt;

&lt;p&gt;Une bonne solution serait d'utiliser un &lt;em&gt;server push&lt;/em&gt;, pour envoyer ces ressources avant même que le navigateur ne les ait demandé. Mais il faut pour cela avoir accès au serveur.&lt;/p&gt;

&lt;p&gt;Alors me vient une pensée impure :&lt;/p&gt;

&lt;blockquote&gt;Mon CSS ne fait que 4ko, qu'est ce qui m'empêche de le mettre directement dans le HTML lors du build ?&lt;/blockquote&gt;

&lt;p&gt;Il s'agit en réalité d'une technique très efficace appelée &lt;em&gt;Critical CSS Inline&lt;/em&gt;, qui consiste à placer le CSS nécessaire au rendu de ce que l'on voit en premier directement dans le HTML. On charge ensuite le reste du CSS en asynchrone, sans bloquer la page.&lt;/p&gt;

&lt;p&gt;Dans mon cas, le CSS critique représente la quasi totalité de ma petite page, mais la technique n'en est pas moins intéressante.&lt;/p&gt;

&lt;p&gt;Je vais ici faire appel au plugin &lt;a href="https://github.com/gregives/eleventy-critical-css" rel="noopener noreferrer"&gt;eleventy-critical-css&lt;/a&gt;, qui cette fois n'est pas officiel mais créé par la communauté.&lt;/p&gt;

&lt;p&gt;Je n'ai pas grand chose à dire sur l'utilisation tant elle est directe :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;criticalCss&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;assetPaths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_site/index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;minify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C'est tout !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6z9tcwz3x1u71uq1lvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6z9tcwz3x1u71uq1lvz.png" alt="CSS Critique dans le code source"&gt;&lt;/a&gt;&lt;/p&gt;
Le CSS critique est extrait puis directement inclus dans l'index.html.






&lt;p&gt;En plus d'inclure le CSS critique, le plugin ajoute la ligne suivante :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./css/styles.css"&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
  &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"print"&lt;/span&gt;
  &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"this.media='all'"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cette technique permet de charger le reste du CSS en asynchrone. En effet, le navigateur charge les CSS associées au media &lt;code&gt;print&lt;/code&gt; en asynchrone par défaut. Une fois ceci fait, la destination de la feuille de style est mise à jour de &lt;code&gt;print&lt;/code&gt; vers &lt;code&gt;all&lt;/code&gt; grâce à &lt;code&gt;onload="this.media='all'&lt;/code&gt;. Habile.&lt;/p&gt;

&lt;h3&gt;
  
  
  Et le JavaScript ?
&lt;/h3&gt;

&lt;p&gt;Quand au JavaScript, qui sert uniquement à gérer l'ouverture fluide des éléments &lt;code&gt;details&lt;/code&gt; sur mobile, l'attribut &lt;code&gt;async&lt;/code&gt; sera idéal :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./dist/script.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si l'utilisateur venait à cliquer sur un élément &lt;code&gt;details&lt;/code&gt; avant que le script ne soit chargé, il s'ouvrirait alors sans transition, soit son comportement par défaut. Quand le JavaScript arrive, on utilise donc l'approche d'amélioration progressive sur ces éléments pour améliorer l'expérience.&lt;/p&gt;

&lt;p&gt;Résultat, nous n'avons plus aucune ressource bloquante !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n5m7usnpzv5rlkei0ad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6n5m7usnpzv5rlkei0ad.png" alt="La cascade après optimisation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nous avons ainsi drastiquement amélioré le &lt;em&gt;chemin critique&lt;/em&gt;, soit cet instant crucial entre la requête et l'affichage de la page.&lt;/p&gt;

&lt;p&gt;En une seule requête, notre utilisateur verra un contenu.&lt;/p&gt;

&lt;p&gt;Mon petit projet effectue désormais un chargement initial de &lt;strong&gt;128k&lt;/strong&gt; et s'affiche en moins d'une seconde.&lt;/p&gt;

&lt;h2&gt;
  
  
  Un site performant, c'est forcément moche ?
&lt;/h2&gt;

&lt;p&gt;Il n'y a rien de plus faux ! Il n'y a &lt;strong&gt;aucune&lt;/strong&gt; corrélation entre la beauté d'un site et sa performance. Si vous avez les bons designers et les bons développeurs, les deux sont parfaitement compatibles.&lt;/p&gt;

&lt;p&gt;Ne me croyez pas sur parole : voici une &lt;a href="https://www.11ty.dev/speedlify/" rel="noopener noreferrer"&gt;liste d'autres sites générés avec Eleventy&lt;/a&gt;, qui atteignent les 100 points sur tous les critères, tout en étant bien plus riches que le mien.&lt;/p&gt;

&lt;p&gt;Ces 100 points ne sont d'ailleurs qu'un point de départ : mon petit projet les atteignait avant même les optimisations décrites dans cet article. Ils ne doivent donc pas nous empêcher d'aller plus loin !&lt;/p&gt;

</description>
      <category>performance</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>Eleventy — Pour un web simple, performant et accessible</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Mon, 14 Jun 2021 06:53:34 +0000</pubDate>
      <link>https://dev.to/bcalou/eleventy-pour-un-web-simple-performant-et-accessible-4m0p</link>
      <guid>https://dev.to/bcalou/eleventy-pour-un-web-simple-performant-et-accessible-4m0p</guid>
      <description>&lt;p&gt;Et si nous gardions Vue, React et ses compagnons pour les web app &lt;em&gt;vraiment&lt;/em&gt; complexes ? Et s'ils devenaient &lt;strong&gt;l'exception à la règle&lt;/strong&gt;, plutôt que d'être notre modèle mental par défaut ?&lt;/p&gt;

&lt;p&gt;Tant de sites ne sont pas si complexes que ça ! Portfolios, sites vitrines, documentation en ligne, blogs... Ce web là mérite bien mieux que la complexité et les coûts qu'engendrent l'utilisation de nos frameworks JS favoris.&lt;/p&gt;

&lt;p&gt;Une des ces nombreuses alternatives s'appelle &lt;a href="https://www.11ty.dev/" rel="noopener noreferrer"&gt;Eleventy&lt;/a&gt;. Il s'agit un générateur de site statique, dont je suis totalement tombé sous le charme pour sa simplicité et son efficacité.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ça sert à quoi ?
&lt;/h2&gt;

&lt;p&gt;Pour découvrir la bête, j'ai réalisé un site tout simple présentant &lt;a href="https://top-livres.netlify.app/" rel="noopener noreferrer"&gt;mes 10 livres préférés de l'année&lt;/a&gt; (entends-je une remarque sur mon sens inestimable du design ?)  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92ouhf1scf6uyupako4m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92ouhf1scf6uyupako4m.png" alt="Une image du site"&gt;&lt;/a&gt;&lt;/p&gt;
C'est pas moche, c'est sobre






&lt;p&gt;Le site est totalement statique : à cette adresse se trouve un fichier HTML, accompagné d'un peu de CSS et de JS. Pour la performance, on ne fait pas mieux.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu433j7cbhp9b2og3bnjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu433j7cbhp9b2og3bnjg.png" alt="Un score de 100 sur Lighthouse"&gt;&lt;/a&gt;&lt;/p&gt;
Les scores des divers outils en ligne ne se substituent pas à l'analyse humaine, mais permettent de vérifier que l'essentiel est là.






&lt;p&gt;Certes, le site est basique, mais j'aurais tout aussi bien pu le générer grâce à un appel GraphQL, une boucle React et autres joyeusetés. Sauf qu'on ne bat pas la simplicité. &lt;em&gt;Boring code is good code&lt;/em&gt;, qu'ils disent.&lt;/p&gt;

&lt;p&gt;Pour autant, je ne me suis pas amusé à écrire à la main les 770 lignes de ce fichier, très redondantes (10 répétitions du composant permettant d'afficher un livre et sa description).&lt;/p&gt;

&lt;p&gt;C'est ici qu'&lt;strong&gt;Eleventy&lt;/strong&gt; entre en scène.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comment ça marche ?
&lt;/h2&gt;

&lt;p&gt;Si on voulait résumer grossièrement, on pourrait présenter Eleventy ainsi :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;données + templates = ♡ HTML ♡
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Markdown, la "base de données"
&lt;/h3&gt;

&lt;p&gt;Chaque livre représenté dans le site est un fichier &lt;code&gt;markdown&lt;/code&gt; (d'autres formats, tels que &lt;code&gt;JSON&lt;/code&gt; sont possibles). Voici par exemple celui pour le livre &lt;em&gt;Dune&lt;/em&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;book&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dune"&lt;/span&gt;
&lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Frank Herbert&lt;/span&gt;
&lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1965&lt;/span&gt;
&lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt;
&lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;896&lt;/span&gt;
&lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#cf5441'&lt;/span&gt;
&lt;span class="na"&gt;publisher&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pocket&lt;/span&gt;
&lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://www.lisez.com/livre-de-poche/dune/9782266320481&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ce&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pavé&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;la&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;réputation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;d'être&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;un&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;peu&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;chiant,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;et&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;oui,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bon,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;peut-être,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;faut&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;rentrer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dedans&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;comme&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;dit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;..."&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Les trois tirets au début et à la fin permettent de définir une table. Le reste est assez direct.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note : il serait formidable de pouvoir typer les objets, avec chaque type de champ et des champs optionnels...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Voici donc ma belle liste de livres :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4k75ypoh4i0xae8abmip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4k75ypoh4i0xae8abmip.png" alt="La liste des 10 fichiers markdown"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Si nous sommes très, très loin d'une base de données telle qu'on l'entend habituellement, cette simplicité vient avec ses avantages : il est ultra simple de mettre à jour le contenu.&lt;/p&gt;

&lt;p&gt;Je n'ai qu'à modifier le fichier (potentiellement directement sur Github), et le process automatique de build que je décris plus loin se mettra en action. Corollaire : les données sont versionnées et il devient difficile d'en perdre.&lt;/p&gt;

&lt;p&gt;On ne pourra certes pas faire du relationnel bien avancé, mais pour notre exemple, c'est parfait !&lt;/p&gt;

&lt;h3&gt;
  
  
  Rendre disponible les données
&lt;/h3&gt;

&lt;p&gt;Par défault, il est déjà possible de boucler sur cette collection de livres, qui sera ordonnée par date de création des fichiers markdown.&lt;/p&gt;

&lt;p&gt;C'est bien pratique pour les posts d'un blog, mais dans mon cas je souhaite avoir une collection ordonnée par ordre alphabétique. Il faut alors la déclarer dans un fichier dédié, &lt;code&gt;.eleventy.js&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;itemsAscending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFilteredByGlob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/items/*.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un peu de travail manuel, certes, mais en contrepartie, une grande liberté.&lt;/p&gt;

&lt;p&gt;Je pourrais trier par année, par auteur, ou même créer une sous-collection contenant uniquement les livres de moins de 100 pages, pour les moins motivés. Après tout, ce n'est que du JavaScript : on fait exactement ce qu'on veut.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Important : ce JavaScript n'est pas exécuté côté client, mais bien lors de la génération du HTML statique, que je détaille ensuite&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Templating
&lt;/h3&gt;

&lt;p&gt;De nombreux langages de templating sont compatibles. J'ai choisi &lt;code&gt;liquid&lt;/code&gt; pour une raison qui a totalement disparu de mon esprit (probablement parce qu'il n'y avait aucune raison).&lt;/p&gt;

&lt;p&gt;Voici donc la boucle du fichier &lt;code&gt;index.liquid&lt;/code&gt; qui va générer les livres :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"items"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  {%- for item in collections.itemsAscending -%}
    {% include src/partials/item %}
  {%- endfor -%}
&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dans le fichier &lt;code&gt;item.liquid&lt;/code&gt; dont voici un extrait, la syntaxe parle d'elle-même :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item__title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  {{ item.data.title }}
&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
{% if item.data.subtitle %}
  &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item__subtitle"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ item.data.subtitle }}&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
{% endif %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C'est simple, c'est bien 👌&lt;/p&gt;

&lt;h3&gt;
  
  
  Vous prendrez bien un peu de CSS / JS ?
&lt;/h3&gt;

&lt;p&gt;Oui, mais à condition de pouvoir utiliser &lt;code&gt;SASS&lt;/code&gt; et du JavaScript moderne !&lt;/p&gt;

&lt;p&gt;Pour satisfaire ces besoins, Eleventy utilise un système de &lt;a href="https://www.11ty.dev/docs/plugins/" rel="noopener noreferrer"&gt;plugins&lt;/a&gt; très simples à utiliser.&lt;/p&gt;

&lt;p&gt;Encore une fois, ça se passe dans le fichier de configuration &lt;code&gt;.eleventy.js&lt;/code&gt;. Pour le CSS, d'abord :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ELEVENTY_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/styles/**/*.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_site/css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cleanCSS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;sourcemaps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;prod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le booléen &lt;code&gt;prod&lt;/code&gt; nous permettra de minifier le CSS uniquement en production, et de générer des &lt;em&gt;sourcemaps&lt;/em&gt; uniquement en développement.&lt;/p&gt;

&lt;p&gt;Même système pour le JavaScript :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;babel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/js/script.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_site/js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;uglify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Il n'y a pas grand chose à ajouter. Si je peux éviter de tout câbler à la main à chaque projet, tant mieux (je t'aime toujours, Gulp).&lt;/p&gt;

&lt;h3&gt;
  
  
  Action !
&lt;/h3&gt;

&lt;p&gt;Tout est en place. Voici la commande que j'utilise pour lancer le serveur de développement :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eleventy --input=src --serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Les données markdown sont injectées dans les templates, eux-même transformés en bon vieux HTML.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--input=src&lt;/code&gt; désigne le dossier dans lequel j'ai placé tout mon code source (&lt;code&gt;liquid&lt;/code&gt;, &lt;code&gt;markdown&lt;/code&gt;, &lt;code&gt;css&lt;/code&gt;...).&lt;/p&gt;

&lt;p&gt;Le flag &lt;code&gt;--serve&lt;/code&gt; vous créera un petit &lt;em&gt;live server&lt;/em&gt; à rechargement automatique. À chaque fois que vous changez un fichier, le HTML final est régénéré, en un dixième de seconde de mon côté.&lt;/p&gt;

&lt;p&gt;Et voici la commande de build :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ELEVENTY_ENV=prod eleventy --input=src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En utilisant un service tel que &lt;a href="https://app.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; (pour qui travaille le créateur d'Eleventy, tout est lié), il ne vous reste plus qu'à renseigner la commande à lancer et le dossier généré à servir (&lt;code&gt;_site&lt;/code&gt; pour Eleventy).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fci1varwxh93i6raw2hv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fci1varwxh93i6raw2hv4.png" alt="La configuration Netlify"&gt;&lt;/a&gt;&lt;/p&gt;
La commande build contient l'appel à eleventy






&lt;p&gt;Le projet Netlify étant lié au projet Github, chaque push ou modification du code sur Github mettra à jour le site en une poignée de secondes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Un meilleur web ?
&lt;/h2&gt;

&lt;p&gt;À nouveau, il est évident qu'un outil tel qu'Eleventy n'est pas adapté à des applications à forte complexité métier, et ce n'est pas le terrain sur lequel il joue.&lt;/p&gt;

&lt;p&gt;En revanche, nous avons désormais un site :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Léger&lt;/strong&gt;, car rien ne peut battre du HTML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performant&lt;/strong&gt;, le CPU n'étant pas sollicité par une montagne de JavaScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessible&lt;/strong&gt;, pour peu que le HTML soit écrit correctement bien sûr&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explorable&lt;/strong&gt; par les moteurs de recherche&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prédictif&lt;/strong&gt;, dans le sens où la complexité se situe côté serveur&lt;/li&gt;
&lt;li&gt;Aisément &lt;strong&gt;modifiable&lt;/strong&gt; et rapidement &lt;strong&gt;déployable&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bref, des objectifs parfois mis à mal lorsqu'on utilise des outils inadaptés, mais des objectifs essentiels...&lt;/p&gt;

&lt;p&gt;Voici un web qui me plaît !&lt;/p&gt;

&lt;p&gt;Retrouvez le code complet de ce projet sur &lt;a href="https://github.com/bcalou/top-books-2020" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  La Jamstack
&lt;/h2&gt;

&lt;p&gt;Eleventy fait partie de l'approche &lt;a href="https://jamstack.org/" rel="noopener noreferrer"&gt;Jamstack&lt;/a&gt;, qui se définit par des termes souvent obscurs, mais dont le point le plus important est sans doute la génération en avance des sites côté back : le &lt;em&gt;pre-rendering&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgix1ivzvc1ejqsswv48h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgix1ivzvc1ejqsswv48h.png" alt="Jamstack"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://jamstack.org/generators/" rel="noopener noreferrer"&gt;Beaucoup de générateurs&lt;/a&gt; sont d'ailleurs disponibles. Eleventy a la réputation de faire partie des plus simples, ce que j'ai largement pu vérifier par moi-même.&lt;/p&gt;

&lt;p&gt;J'aime particulièrement le fait qu'il ne soit pas lié à un langage ou un framework en particulier. Bref, Je le conserve précieusement dans ma boîte à outils.&lt;/p&gt;

&lt;p&gt;La prochaine fois, ne vous demandez pas :&lt;/p&gt;

&lt;blockquote&gt;Quel framework JS vais-je choisir ?&lt;/blockquote&gt;

&lt;p&gt;Mais bien :&lt;/p&gt;

&lt;blockquote&gt;Suis-je dans l'absolue nécessité dans utiliser un ?&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>html</category>
    </item>
    <item>
      <title>What happens when you write an invalid CSS selector? (bad things)</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Mon, 07 Dec 2020 08:19:09 +0000</pubDate>
      <link>https://dev.to/bcalou/what-happens-when-you-write-an-invalid-css-selector-bad-things-4734</link>
      <guid>https://dev.to/bcalou/what-happens-when-you-write-an-invalid-css-selector-bad-things-4734</guid>
      <description>&lt;p&gt;I'd like to talk about a very specific CSS behavior that might cause some headaches if you don't know (or forget!) about it.&lt;/p&gt;

&lt;p&gt;Let's create a button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Click me&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I want this button to change its colors when it is pressed. With the &lt;code&gt;:active&lt;/code&gt; pseudo-class, that's easy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nd"&gt;:active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/OJXYNag?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So far so good.&lt;/p&gt;

&lt;p&gt;To improve accessibility, I want to apply the same effect when the button is focused with the keyboard or an assistive technology (and do nothing special if the focus comes from the mouse).&lt;/p&gt;

&lt;p&gt;This is possible thanks to the new &lt;code&gt;:focus-visible&lt;/code&gt; pseudo-class. At the time of writing, it is supported without prefix by &lt;a href="https://caniuse.com/?search=focus-visible" rel="noopener noreferrer"&gt;Chrome and Edge&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nd"&gt;:active&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nd"&gt;:focus-visible&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/bGeyyPo?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you are on Chrome or Edge, you can try to focus the button with the tab key and you should see the &lt;code&gt;:focus-visible&lt;/code&gt; styles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhce2hf2erpl0nkcglwws.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhce2hf2erpl0nkcglwws.gif" alt="Focus within styles"&gt;&lt;/a&gt;&lt;/p&gt;
This is a great visual help if you don't use a mouse



&lt;h1&gt;
  
  
  Here's the catch
&lt;/h1&gt;

&lt;p&gt;Can you guess what will happen on other browsers? Obviously the &lt;code&gt;:focus-visible&lt;/code&gt; styles won't show, but any side effect, maybe?&lt;/p&gt;

&lt;p&gt;We also lost the &lt;code&gt;:active&lt;/code&gt; styles!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxxz2fpdqa6v01brkjcca.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxxz2fpdqa6v01brkjcca.gif" alt="There are no styles on Firefox"&gt;&lt;/a&gt;&lt;/p&gt;
The :active styles don't show on Firefox, despite the browser perfect understanding of the :active selector. So sad.



&lt;p&gt;The problem might seem obvious if you already know why this happens, but when I had to debug this in a much more complex CSS file, it boggled me for a good few minutes. And I don't think it is a well-known fact among beginners.&lt;/p&gt;

&lt;p&gt;So how to put it?&lt;/p&gt;

&lt;h1&gt;
  
  
  If any part of a selector fails, the whole selector fails
&lt;/h1&gt;

&lt;p&gt;In other words, if a browser doesn't know about the &lt;code&gt;:focus-within&lt;/code&gt; selector, it will throw out your entire CSS rule, including the &lt;code&gt;:active&lt;/code&gt; part.&lt;/p&gt;

&lt;p&gt;You could say that CSS is a bit susceptible. If it doesn't like the type of olive you put on the pizza, it won't even consider eating it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdzaxbvr99oj5mc2is4sx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdzaxbvr99oj5mc2is4sx.gif" alt="Garbage truck"&gt;&lt;/a&gt;&lt;/p&gt;
CSS has no time to waste with your crazy selectors



&lt;p&gt;Here's the W3C &lt;a href="https://www.w3.org/TR/css-syntax-3/#error-handling" rel="noopener noreferrer"&gt;specification&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt; When interpreting a list of declarations, unknown syntax at any point causes the parser to throw away whatever declaration it’s currently building, and seek forward until it finds a semicolon (or the end of the block). It then starts fresh, trying to parse a declaration again.&lt;/blockquote&gt;

&lt;p&gt;And so here's the fix you'll need to use: separate the "safe styles" and the crazy ones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nd"&gt;:active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nd"&gt;:focus-visible&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/oNzbByo?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Now, &lt;code&gt;:focus-visible&lt;/code&gt; might fail, but it won't bother the &lt;code&gt;:active&lt;/code&gt; selector.&lt;/p&gt;

&lt;h1&gt;
  
  
  But why this behavior?
&lt;/h1&gt;

&lt;blockquote&gt;Not really resilient for a language that should adapt itself to many environments, is it?&lt;/blockquote&gt;

&lt;blockquote&gt;CSS is broken! JavaScript is our only savior!&lt;/blockquote&gt;

&lt;p&gt;Well, there is actually a good reason for this, which is explained in an old document, the &lt;a&gt;CSS 2.1 specification&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
CSS 2.1 gives a special meaning to the comma (,) in selectors. However, since it is not known if the comma may acquire other meanings in future updates of CSS, the whole statement should be ignored if there is an error anywhere in the selector, even though the rest of the selector may look reasonable in CSS 2.1.&lt;/blockquote&gt;

&lt;p&gt;CSS designers displayed a great level of anticipation here. Indeed, here are some CSS selector that we'll be able to use sooner or later (in some cases, we already are):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.title&lt;/span&gt;&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c"&gt;/* h1.title, h2.title, h3.title */&lt;/span&gt;
&lt;span class="nc"&gt;.title&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c"&gt;/* multiple exclusions */&lt;/span&gt;
&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c"&gt;/* parent selector */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These selector contain commas, but these commas don't separate the first-level selectors.&lt;/p&gt;

&lt;p&gt;If a browser doesn't understand &lt;code&gt;:is&lt;/code&gt; and tries to separate our first example, it could result in something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.title&lt;/span&gt;&lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="c"&gt;/* What is this? Ignore */&lt;/span&gt;
&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="c"&gt;/* Style all the h2, even without the .title class! */&lt;/span&gt;
&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c"&gt;/* Wut?*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft2yxcsm15eqcy1wr1j9u.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft2yxcsm15eqcy1wr1j9u.gif" alt="A man with a chainsaw"&gt;&lt;/a&gt;&lt;/p&gt;
The CSS chainsaw massacre



&lt;p&gt;Instead, the browser is cautious. This has been discussed again in 2013, and kept the same way &lt;a href="https://lists.w3.org/Archives/Public/www-style/2013Apr/0246.html" rel="noopener noreferrer"&gt;"due to Web-compat concerns"&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hacks
&lt;/h1&gt;

&lt;p&gt;Some developers even used this as a hack to discriminate a specific browser.&lt;/p&gt;

&lt;p&gt;Wanna apply a specific style to all browsers except IE? Just add a modern selector for the sole purpose of making IE ignore the rule.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.covfefe&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tadaa, the &lt;code&gt;h1&lt;/code&gt; will be red only if the browser also understands &lt;code&gt;:not&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With the correct combination of selectors, you could target or exclude any specific browser version. Which is of course very, very dirty, and hopefully not needed anymore 🙏&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Flexbox: when negative margins save the day</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Mon, 02 Nov 2020 08:43:04 +0000</pubDate>
      <link>https://dev.to/bcalou/flexbox-when-negative-margins-save-the-day-h4i</link>
      <guid>https://dev.to/bcalou/flexbox-when-negative-margins-save-the-day-h4i</guid>
      <description>&lt;p&gt;Gap management with flexbox is not as easy as it seems. Here is a  simple trick I've been using a lot lately.&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;This is our HTML for this demo:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;HTML&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;CSS&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;JavaScript&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Front-end dev&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Web&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Lorem ipsum...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It's an article with a list of tags. With some basic CSS, here's what it looks like.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/twhite96/embed/dyXdqOL?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;p&gt;We want the list of tags to be a flex container, with the possibility to wrap. Here we go!&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;As you can see, I also set some space after each &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element, &lt;code&gt;2em&lt;/code&gt; being equal to &lt;code&gt;32px&lt;/code&gt; for common text (with the advantage of being responsive to the user preferences and the font-size of the item itself).&lt;/p&gt;

&lt;p&gt;And here's the result:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/twhite96/embed/WNxMgpp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;p&gt;It may seem good enough, but the devil is in the details.&lt;/p&gt;

&lt;p&gt;Look at the bottom right corner of the card: I made it resizable so you can simulate a browser resize.&lt;/p&gt;

&lt;p&gt;There are two main issues. Can you spot them?&lt;/p&gt;
&lt;h1&gt;
  
  
  The horizontal issue
&lt;/h1&gt;

&lt;p&gt;The first problem is that because of its right margin, the last items goes to the second line too soon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fv31tzfgwyxah04yzerm3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fv31tzfgwyxah04yzerm3.gif" alt="The line wraps too soon"&gt;&lt;/a&gt;&lt;/p&gt;
Do you notice how there is more space for the last item to go more to the right before the wrapping? Compare that to the space to the left of the first tag.



&lt;p&gt;You could fix that by excluding the last item from the rule:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/twhite96/embed/mdEXGvE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;p&gt;But the problem is the same: every other item causes the line to wrap too soon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flkqjq2ipkwwg75sxls7x.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flkqjq2ipkwwg75sxls7x.gif" alt="The line still wraps too soon"&gt;&lt;/a&gt;&lt;/p&gt;
Now the last tag can go farther to the right, but the other ones still cause the line to wrap too soon.



&lt;p&gt;Well, if &lt;code&gt;margin-right&lt;/code&gt; is not good enough, what about &lt;code&gt;margin-left&lt;/code&gt; ? Let's try this on every item — except the first one, which should not be preceded by any space.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/BazrZQv?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Is it better this time? Take a moment and try to guess what issue it might cause.&lt;/p&gt;

&lt;p&gt;Because there is no &lt;code&gt;margin-right&lt;/code&gt; anymore, the line wraps exactly when it should. But now our problem is elsewhere:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg38dtrm09tmloftslbhu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg38dtrm09tmloftslbhu.gif" alt="The new line reveals the  raw `margin-left` endraw  of the item"&gt;&lt;/a&gt;&lt;/p&gt;
The new line reveals the `margin-left` of the item



&lt;p&gt;We can't complain. We told CSS that each item except the first one should have a left margin, and that's what happens.&lt;/p&gt;

&lt;p&gt;How nice would it be to exclude every item that is the first one of its row! But there is no magic selector like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:first-flex-row-item&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c"&gt;/* Does not exist */&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Such hypothetical selectors could cause a &lt;em&gt;CSS circular dependency&lt;/em&gt;. For example, I could say that the first item of a row has a smaller font-size. That could cause the item to go back to the previous line (because of it smaller size), and then it wouldn't be targeted by the selector anymore, and regain its original size, and go back to the second line and... 🤯&lt;/p&gt;

&lt;p&gt;Circular dependencies one of the main reasons we don't have &lt;a href="https://css-tricks.com/lets-not-forget-about-container-queries/" rel="noopener noreferrer"&gt;container queries&lt;/a&gt; yet. But that's another topic.&lt;/p&gt;

&lt;h1&gt;
  
  
  The negative margin trick
&lt;/h1&gt;

&lt;p&gt;So here's how you do it: first off, every item will get a &lt;code&gt;margin-left&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/yLJKPXy?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We now have to get rid of the space to the left of the first item, and we can do that with negative margins.&lt;/p&gt;

&lt;p&gt;Negative margins are not considered a good practice, and I think that you should avoid them whenever possible, because they can make your code's logic harder to understand.&lt;/p&gt;

&lt;p&gt;That being said, they are allowed by the &lt;a href="https://www.w3.org/TR/CSS2/box.html#margin-properties" rel="noopener noreferrer"&gt;w3c&lt;/a&gt; and offer a really good browser support.&lt;/p&gt;

&lt;p&gt;And in our case, they save the day:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;margin-left&lt;/span&gt; &lt;span class="err"&gt;-2em;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/MWeVomw?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqkdy7mvnvcp8xi5nvopj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqkdy7mvnvcp8xi5nvopj.png" alt="Blue borders applied on the list element reveal the trick"&gt;&lt;/a&gt;&lt;/p&gt;
Blue borders applied on the `ul` element reveal the trick



&lt;h1&gt;
  
  
  What about the vertical axis?
&lt;/h1&gt;

&lt;p&gt;Well guess what, it's the same thing!&lt;/p&gt;

&lt;p&gt;You can't target every item except the ones that are on the first line.&lt;/p&gt;

&lt;p&gt;So you have to give everyone a margin-top.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/zYBWzdo?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This causes the whole list to appear lower that what we want.&lt;/p&gt;

&lt;p&gt;We could remove the &lt;code&gt;margin-bottom: 1em&lt;/code&gt; from the title tag to compensate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpuu6i895b2orm8dafrx9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpuu6i895b2orm8dafrx9.png" alt="The removal of the title margin (yellow area) would compensate for the new area inside the list"&gt;&lt;/a&gt;&lt;/p&gt;
The removal of the title margin (yellow area) would compensate for the new area inside the `ul` (blue borders)



&lt;p&gt;But I always try to &lt;strong&gt;keep my elements independent of the context&lt;/strong&gt;. The list could appear below another element at some point. Or a title could be followed by something that is not a list.&lt;/p&gt;

&lt;p&gt;You know, component driven development, design system and all that jazz.&lt;/p&gt;

&lt;p&gt;So we just have to use the same trick and apply a negative margin to our list:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;margin-left&lt;/span&gt; &lt;span class="err"&gt;-2em;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/XWKEgEp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;And here's our final version. It works on every browser correctly supporting this flexbox configuration, including IE11.&lt;/p&gt;

&lt;h1&gt;
  
  
  What about the &lt;code&gt;gap&lt;/code&gt; property?
&lt;/h1&gt;

&lt;p&gt;Posts like this one will become irrelevant once the CSS &lt;code&gt;gap&lt;/code&gt; property is widely supported.&lt;/p&gt;

&lt;p&gt;But that's not the case yet. At the time of writing, its &lt;a href="https://caniuse.com/flexbox-gap" rel="noopener noreferrer"&gt;browser support is only 70%&lt;/a&gt;. Not that great, compared to the 99% support of flexbox itself — has Safari really become the new IE?&lt;/p&gt;

&lt;p&gt;Other modern browsers should show you the same result with the following code, without tricks!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* row-gap + column-gap */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* No more styles on the items */&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/zYBWRaO?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The sad part is that you can't even detect the support of this property. Consider the following code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="k"&gt;@supports&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Cancel the tricks and do the right thing */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;@supports&lt;/code&gt; queries allow you to apply rules only if the browser understands what's inside the parenthesis.&lt;/p&gt;

&lt;p&gt;The problem here is that &lt;code&gt;gap&lt;/code&gt; is also a property used on grids, with a much better support of 92%. But that does not mean that the property will work for flexbox.&lt;/p&gt;

&lt;p&gt;Here's &lt;a href="https://github.com/w3c/csswg-drafts/issues/3559" rel="noopener noreferrer"&gt;the issue being discussed by the CSS Working Group&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the meantime, it's negative margins all the way.&lt;/p&gt;

&lt;h1&gt;
  
  
  Now with variables ✨
&lt;/h1&gt;

&lt;p&gt;We can improve our code and make it more generic if we need. I like to separate my BEM/semantic CSS from my utility classes, so I will create a class called &lt;code&gt;u-flex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm not a big fan of having style-oriented classes in my &lt;code&gt;HTML&lt;/code&gt;, so I would probably use a SASS mixin instead, but you get the idea.&lt;/p&gt;

&lt;p&gt;Let's use CSS variables, which have a very decent support (95%). In CSS, you can get the opposite of a value by multiplying it by &lt;code&gt;-1&lt;/code&gt;. Here is an example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--size&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="err"&gt;/*&lt;/span&gt; &lt;span class="err"&gt;-2em&lt;/span&gt; &lt;span class="err"&gt;/*&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So here's our utility class:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.u-flex&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--row-gap&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-1&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--column-gap&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.u-flex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--row-gap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--column-gap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I like to use the "direct child of any type" selector (&lt;code&gt;&amp;gt; *&lt;/code&gt;) with flexbox and grid. It relates very well to the parent/child relationship of these features and will work every time.&lt;/p&gt;

&lt;p&gt;And here's how you would use it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"u-flex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;HTML&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;CSS&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;JavaScript&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Front-end dev&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Web&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--row-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--column-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/oNLqEQz?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The power of CSS variables allows us to define different gaps for each targeted element. We could even define default values for the whole document:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--row-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--column-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This way, we only have to change the variables locally when we need to have a different gap value.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bad practices
&lt;/h1&gt;

&lt;p&gt;We all know many bad practices: &lt;code&gt;!important&lt;/code&gt; is another one that comes to my mind. But like negative margins, it also has some relevant use cases.&lt;/p&gt;

&lt;p&gt;This negative margins trick is a reminder to me: things you learned to avoid might come in handy some day. It all depends of the context.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>HTML is not an imperative programming language and that's the best thing about it</title>
      <dc:creator>Bastien Calou</dc:creator>
      <pubDate>Wed, 21 Oct 2020 07:18:53 +0000</pubDate>
      <link>https://dev.to/bcalou/html-is-not-a-programming-language-and-that-s-the-best-thing-about-it-4202</link>
      <guid>https://dev.to/bcalou/html-is-not-a-programming-language-and-that-s-the-best-thing-about-it-4202</guid>
      <description>&lt;p&gt;I love HTML. The more I learn about it, the more I think it is genius work. Above all, I love that it is not a programming language. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Programming languages suck&lt;/strong&gt;. They fail all the time (I swear, I always write my JavaScript perfectly on the first try, and yet it persists in failing 🤷).&lt;/p&gt;

&lt;p&gt;Worse, when they fail, most of the time the whole program fails! I'd just rather stack toothpicks on a windy bridge.&lt;/p&gt;

&lt;p&gt;But compare that to the beauty that is HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"products.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Products&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"about.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is beautiful, semantic HTML5. It helps accessibility. It helps legibility. It helps styling. It helps crawlers.&lt;/p&gt;

&lt;p&gt;And it doesn't fail.&lt;/p&gt;

&lt;p&gt;If an old browser doesn't know about HTML5, it will just treat the &lt;code&gt;nav&lt;/code&gt; element as good old &lt;code&gt;div&lt;/code&gt;, &lt;strong&gt;and it will work&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If a developer or a user with a code editor (e.g. the WordPress back-end) writes &lt;code&gt;nax&lt;/code&gt; instead of &lt;code&gt;nav&lt;/code&gt;, &lt;strong&gt;it will still work&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's see another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;details&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;HTML&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
  HTML is an acronym for HyperText Markup Language. It was created by Tim Berners-Lee in 1989.
&lt;span class="nt"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not everyone knows about the &lt;code&gt;details&lt;/code&gt; element, so here's what it will produce in modern browsers:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bcalou/embed/oNbRWJZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I didn't &lt;em&gt;program&lt;/em&gt; this behavior (browser's developers did). I &lt;em&gt;described&lt;/em&gt; the content of the document and trusted the browser to render it the best it could. And I think that's very, very cool.&lt;/p&gt;

&lt;p&gt;And it will work with old browsers too: there won't be any interactivity, but the content will be displayed and that's the most important thing.&lt;/p&gt;

&lt;h1&gt;
  
  
  Keep calm and stop programming
&lt;/h1&gt;

&lt;p&gt;I don't want to program. I often have to, when &lt;code&gt;HTML&lt;/code&gt; is not enough to describe what my website should do. And like many of us, my typical day revolves around front-end JavaScript frameworks, some of which I really like.&lt;/p&gt;

&lt;p&gt;But when I think about the user, I know that the worst thing I can do to them is to program.&lt;/p&gt;

&lt;p&gt;Everytime I program something myself, I feel like signing a strange document in my head:&lt;/p&gt;

&lt;blockquote&gt;
I hereby acknowledge that I'm introducing a non-standard behavior into this website, discharging the browser of its responsibility to ensure a reliable experience for every user. I do this fully aware of my partial knowledge of web technologies, of the existence of limits in my implementations, temporal and technical, which cannot be estimated. I realize that what I'm doing will probably break at some point or in some situations. But I have no choice and I promise not to fuck it up.
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3unrqe2j6n23w4mjgrk1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3unrqe2j6n23w4mjgrk1.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, when I use HTML and web standards, I rely on the shared knowledge of skilled browser's developers and decades of debates aiming to make the web a great platform.&lt;/p&gt;

&lt;p&gt;And that's why a deep knowledge of HTML is infinitely valuable: it simply brings quality to the user, which at the end of the day is the only thing of importance.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resilience
&lt;/h1&gt;

&lt;p&gt;In one of my best reads of the year, &lt;a href="https://resilientwebdesign.com/" rel="noopener noreferrer"&gt;Resilient Web Design&lt;/a&gt;, Jeremy Keith tells us how we almost lost one of the most powerful aspects of HTML because of XHTML 2.0:&lt;/p&gt;

&lt;blockquote&gt;
[XHTML 2.0] would also implement XML’s draconian error‐handling model. If there is a single error in an XML document — one unquoted attribute or missing closing slash — then the parser should stop immediately and refuse to render anything.
&lt;/blockquote&gt;

&lt;p&gt;Thank god we didn't have that.&lt;/p&gt;

&lt;blockquote&gt;
XHTML 2.0 died on the vine. Its theoretical purity was roundly rejected by the people who actually made websites for a living.
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8mjzd29e5kxgnct70tum.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8mjzd29e5kxgnct70tum.jpg" alt="HTML5 won against XHTML 2.0"&gt;&lt;/a&gt;&lt;/p&gt;
Source : https://speakerdeck.com/elkraneo/html5



&lt;p&gt;I told you: sane people don't want to program nor anything close to it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Is HTML hard?
&lt;/h1&gt;

&lt;p&gt;Of course, for HTML to be such a great language, you have to know it. I mean really &lt;em&gt;know&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;Semantics, accessibility, SEO, browser compatibility and default styling, new tags, deprecated tags, specific attributes related to language and time, forms, performance optimization, metadata, media resources...&lt;/p&gt;

&lt;p&gt;Even without considering framework-generated "tag soups", there is a huge gap between a good HTML markup and a great one.&lt;/p&gt;

&lt;p&gt;It would be a mistake to consider HTML (and CSS) to be the easy part of web development. The problem is that you need to know these languages well to realize that.&lt;/p&gt;

&lt;p&gt;JavaScript is hard. Why does everyone know that? Because before you get anything to work, you will deal with countless red errors blocking your entire project. Only after a painful debugging your code will run correctly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8zqw5nc6s3faw11xqkoa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8zqw5nc6s3faw11xqkoa.jpg" alt="console log all the ways"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can't fail with HTML. You can write tag soup, bad forms and follow none of the good practices, but it won't fail, because of its fundamental resilience.&lt;/p&gt;

&lt;p&gt;The first time you write JavaScript, it's a mess. The first time you write HTML, you feel like a web genius.&lt;/p&gt;

&lt;p&gt;It's only with time and knowledge that you realize you were not the genius: HTML designers were the geniuses, and they gave you a great tool which will require a lot of practice and patience to get &lt;em&gt;really&lt;/em&gt; right.&lt;/p&gt;

&lt;p&gt;The permissiveness of HTML gave the opportunity to contribute to the web to a lot of people and probably has to do with how far the vision of Tim Berners-Lee has come. But for professional developers, it comes with the responsibility to not rest on this apparent simplicity, and really master this powerful language.&lt;/p&gt;

&lt;h1&gt;
  
  
  The identity crisis of web languages
&lt;/h1&gt;

&lt;p&gt;It is important how we call things. It's very frustrating to see the HTML/CSS part of a project devalued so often when you know its critical aspect. It's excruciating hearing front-end developers "not caring about CSS", while &lt;strong&gt;displaying pixels on a screen&lt;/strong&gt; is almost the definition of the job.&lt;/p&gt;

&lt;p&gt;Maybe calling HTML a programming language makes it more worthy of attention to some people? It would be naive not to realize the biases in salaries and even the sexism related to this matter. You know, because HTML/CSS is the presentation part, and that's... feminine?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmysg4uuhjco2sl235p5g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmysg4uuhjco2sl235p5g.gif" alt="Face Palm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, I understand that reading that HTML is a programming language can bother some people, including myself. Not because I think programming languages are better. Because &lt;strong&gt;I don't want HTML to be a programming language&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  We are just building things
&lt;/h1&gt;

&lt;p&gt;During my courses I often use the term &lt;em&gt;development language&lt;/em&gt;. I don't see it used often in english. In french we say "langage de développement" and I think that's beautiful.&lt;/p&gt;

&lt;p&gt;With that term, you can reunite HTML, CSS and JS without everybody freaking out. From the &lt;a href="https://dictionary.cambridge.org/fr/dictionnaire/anglais/develop" rel="noopener noreferrer"&gt;Cambridge Dictionnary&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
Develop: to invent something or bring something into existence
&lt;/blockquote&gt;

&lt;p&gt;While it seems the debate about HTML/CSS being programming languages will last until the end of datetimes, the fact that they are used, sometimes alongside JS, to "bring something to existence", does not seem controversial at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frcrbr674dy3zs85dovfs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frcrbr674dy3zs85dovfs.gif" alt="developers developers developers"&gt;&lt;/a&gt;&lt;/p&gt;
We are all developers.



&lt;p&gt;Who cares if you're programming or not? The only thing that matters is the quality of what you're building.&lt;/p&gt;

&lt;p&gt;I guess we just have to make non-programming cool again.&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
