<?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>Forem: Francesco Vetere</title>
    <description>The latest articles on Forem by Francesco Vetere (@francescovetere).</description>
    <link>https://forem.com/francescovetere</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%2F1200255%2F7c8f299d-4607-4f5d-bcd0-c3075a619d29.png</url>
      <title>Forem: Francesco Vetere</title>
      <link>https://forem.com/francescovetere</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/francescovetere"/>
    <language>en</language>
    <item>
      <title>↔️ Sideway selection in CSS with :has()</title>
      <dc:creator>Francesco Vetere</dc:creator>
      <pubDate>Wed, 31 Jan 2024 11:40:14 +0000</pubDate>
      <link>https://forem.com/francescovetere/-sideway-selection-in-css-with-has-28im</link>
      <guid>https://forem.com/francescovetere/-sideway-selection-in-css-with-has-28im</guid>
      <description>&lt;p&gt;Hi folks! 👋 Today I would like to share with you this &lt;strong&gt;codepen&lt;/strong&gt; I created in order to showcase a simple but really &lt;strong&gt;cool use&lt;/strong&gt; for the recently introduced &lt;code&gt;:has()&lt;/code&gt; &lt;strong&gt;selector&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;If you hover with your mouse over any of the emojis, you'll notice that not only the &lt;strong&gt;hovered emoji&lt;/strong&gt; smoothly pops up, but its &lt;strong&gt;previous and next siblings&lt;/strong&gt; also get affected a little bit, creating a very pleasant effect.&lt;/p&gt;

&lt;p&gt;This cool effect is only possible thanks to the &lt;code&gt;:has()&lt;/code&gt; &lt;strong&gt;selector&lt;/strong&gt;, recently introduced in the CSS world and &lt;a href="https://caniuse.com/css-has"&gt;now available for all the major browsers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;➡️ &lt;code&gt;:has()&lt;/code&gt; is a &lt;strong&gt;functional pseudo-class&lt;/strong&gt; that allows us to style an element based on its descendants or any succeeding elements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Basically, &lt;code&gt;:has()&lt;/code&gt; allows to style the &lt;strong&gt;element it is attached to&lt;/strong&gt; — otherwise known as the &lt;strong&gt;target&lt;/strong&gt; element. This is &lt;strong&gt;similar to other pseudo-classes&lt;/strong&gt; like &lt;code&gt;:hover&lt;/code&gt;, where &lt;code&gt;a:hover&lt;/code&gt; is intended to style the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; element in an hovered state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However, &lt;code&gt;:has()&lt;/code&gt; is also similar to &lt;code&gt;:is()&lt;/code&gt;, &lt;code&gt;:where()&lt;/code&gt;, and &lt;code&gt;:not()&lt;/code&gt;, in that it accepts a a &lt;strong&gt;list of relative selectors&lt;/strong&gt; within its parentheses. This allows &lt;code&gt;:has()&lt;/code&gt; to create &lt;strong&gt;complex criteria to test against&lt;/strong&gt;, making it a very powerful selector.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if I wanted to select all the &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; elements that contain an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; as child, &lt;code&gt;:has()&lt;/code&gt; would make this quite a simple task:&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;article&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&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 use of &lt;code&gt;:has()&lt;/code&gt; is certainly one of the most common: it basically acts as a &lt;strong&gt;parent selector&lt;/strong&gt;, something that &lt;strong&gt;really was missing&lt;/strong&gt; in the web platform and was highly demanded for years by developers.&lt;/p&gt;

&lt;p&gt;❗ &lt;strong&gt;BUT&lt;/strong&gt;, because &lt;code&gt;:has()&lt;/code&gt; actually accepts a relative selector list as its argument, you can select &lt;strong&gt;so much more&lt;/strong&gt; than just the parent element! Using various CSS combinators, it is now possible to &lt;strong&gt;not only go up&lt;/strong&gt; ⬆️ the DOM tree, but &lt;strong&gt;also&lt;/strong&gt; do &lt;strong&gt;sideway selections!&lt;/strong&gt; ↔️&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;article:has(+ article)&lt;/code&gt; will select any &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; element that has another &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; as a direct sibling. This apparently simple selection would just not be possible without &lt;code&gt;:has()&lt;/code&gt;, and it would have required some extra JavaScript.&lt;/p&gt;

&lt;p&gt;💡 The codepen I realized takes advantage of this very idea. I basically want to &lt;strong&gt;apply some styling&lt;/strong&gt; (a scaling and a translation) for the &lt;strong&gt;currently hovered emoji&lt;/strong&gt;, but &lt;strong&gt;also&lt;/strong&gt; for its &lt;strong&gt;previous and next sibling.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;➡️ &lt;code&gt;:has()&lt;/code&gt; makes this really 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="nc"&gt;.dock&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* scale and translate the hovered emoji */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.dock&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* scale and translate the next emoji */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.dock&lt;/span&gt; &lt;span class="nt"&gt;li&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;li&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* scale and translate the previous emoji */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course the full code is a little bit more complex than that (you can check out the &lt;a href="https://codepen.io/francescovetere/pen/abMJgMz"&gt;codepen&lt;/a&gt; if you're curious), but the &lt;strong&gt;main idea&lt;/strong&gt; really is based on this simple snippet. Having a way to select not only an element and its next sibling, but also its previous one, opens up a whole new world of possibilities.&lt;/p&gt;




&lt;p&gt;And that's it! Feel free to leave a comment and let me know what other cool stuff you built using &lt;code&gt;:has()&lt;/code&gt; 😉&lt;/p&gt;

&lt;p&gt;Till next time! 👋&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>css</category>
    </item>
    <item>
      <title>🧙‍♂️ CSS trick: transition from height 0 to auto!</title>
      <dc:creator>Francesco Vetere</dc:creator>
      <pubDate>Sat, 25 Nov 2023 09:20:53 +0000</pubDate>
      <link>https://forem.com/francescovetere/css-trick-transition-from-height-0-to-auto-21de</link>
      <guid>https://forem.com/francescovetere/css-trick-transition-from-height-0-to-auto-21de</guid>
      <description>&lt;p&gt;If you messed around with CSS for long enough, chances are you've tried at least once to make a &lt;strong&gt;transition&lt;/strong&gt; from &lt;code&gt;height: 0&lt;/code&gt; to &lt;code&gt;auto&lt;/code&gt;... only to find out that it &lt;strong&gt;doesn't work!&lt;/strong&gt; 😢 &lt;/p&gt;

&lt;p&gt;➡️ Luckily, today there is actually a &lt;strong&gt;solution&lt;/strong&gt; to this problem: it uses &lt;strong&gt;CSS Grid&lt;/strong&gt; under the hood, and it is just &lt;strong&gt;so easy&lt;/strong&gt; and it &lt;strong&gt;works flawlessly!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's start with a practical example. I have built this simple &lt;strong&gt;accordion&lt;/strong&gt;:&lt;/p&gt;

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

&lt;p&gt;The &lt;strong&gt;HTML&lt;/strong&gt; for it is pretty straightforward:&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;"accordion"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&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;"accordion-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hover me!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&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;"accordion-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&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;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;If you &lt;strong&gt;hover&lt;/strong&gt; with your mouse over the accordion, you'll notice that a &lt;strong&gt;dropdown appears&lt;/strong&gt;. That's cool, but what if we wanted to make it appear with a nice &lt;strong&gt;smooth transition?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I actually tried&lt;/strong&gt; to do so in the previous codepen by adding a little transition on the &lt;code&gt;height&lt;/code&gt; property:&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;.accordion-body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500ms&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.accordion&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="nc"&gt;.accordion-body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&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;❌ Unfortunately, &lt;strong&gt;this doesn't work&lt;/strong&gt;: transitioning from &lt;code&gt;height: 0&lt;/code&gt; to &lt;code&gt;height: auto&lt;/code&gt;, as I was saying earlier, is something &lt;strong&gt;not possible with CSS.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🤔 How to solve this? &lt;/p&gt;

&lt;p&gt;Well, a &lt;strong&gt;first solution&lt;/strong&gt; could be setting the &lt;code&gt;height&lt;/code&gt; property to a &lt;strong&gt;fixed number&lt;/strong&gt;, instead of &lt;code&gt;auto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This would work, but it's &lt;strong&gt;not such a great approach&lt;/strong&gt;: in order to compute this fixed number we would have to resort to &lt;strong&gt;JavaScript&lt;/strong&gt;, in order to calculate how much our &lt;code&gt;.accordion-body&lt;/code&gt; is actually tall... &lt;strong&gt;not really what we aimed for!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;😕 Can we still achieve this effect, but with a &lt;strong&gt;CSS-only&lt;/strong&gt; solution?&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Actually, yes!&lt;/strong&gt; Why don't we just use &lt;code&gt;max-height&lt;/code&gt; instead?&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;.accordion-body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500ms&lt;/span&gt; &lt;span class="n"&gt;max-height&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.accordion&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="nc"&gt;.accordion-body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&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 would be the result:&lt;/p&gt;

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

&lt;p&gt;Since we are defining a &lt;strong&gt;fixed value&lt;/strong&gt; for &lt;code&gt;max-height&lt;/code&gt;, the browser is now able to &lt;strong&gt;perform the transition correctly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;😕 The &lt;strong&gt;only problem&lt;/strong&gt; is that, since we are defining a fixed value for &lt;code&gt;max-height&lt;/code&gt;, now the content could &lt;strong&gt;potentially overflow&lt;/strong&gt;:&lt;/p&gt;

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

&lt;p&gt;If you're sure that your content will always be such that it never reaches a certain height... then it's &lt;strong&gt;perfectly fine to use this method!&lt;/strong&gt; Just use an appropriate value for &lt;code&gt;max-height&lt;/code&gt;, and you're good to go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be aware though&lt;/strong&gt;, the &lt;strong&gt;higher the value&lt;/strong&gt; for &lt;code&gt;max-height&lt;/code&gt;, the &lt;strong&gt;weirder the transition gets&lt;/strong&gt; (try putting a &lt;code&gt;max-height: 1000px&lt;/code&gt; in the previous codepen, and see how things change!).&lt;/p&gt;

&lt;p&gt;🤔 &lt;strong&gt;Can we do better?&lt;/strong&gt; Can we avoid having any fixed &lt;code&gt;height&lt;/code&gt;/&lt;code&gt;max-height&lt;/code&gt; in the first place?&lt;/p&gt;

&lt;p&gt;🎉 &lt;strong&gt;CSS Grid comes to the rescue!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ We can actually use a &lt;strong&gt;neat trick&lt;/strong&gt; which basically consists in making a &lt;strong&gt;CSS grid&lt;/strong&gt; with a &lt;strong&gt;single grid item&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;All we really have to do then, is taking our &lt;code&gt;grid-template-rows&lt;/code&gt; and make it &lt;strong&gt;transition from &lt;code&gt;0fr&lt;/code&gt; to &lt;code&gt;1fr&lt;/code&gt;&lt;/strong&gt;: this way, our grid item will transition from 0 to its "natural" height. It's &lt;strong&gt;THAT&lt;/strong&gt; simple:&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;.accordion-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;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="py"&gt;grid-template-rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250ms&lt;/span&gt; &lt;span class="n"&gt;grid-template-rows&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.accordion&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="nc"&gt;.accordion-body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.accordion-body&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&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 feels a &lt;strong&gt;lot cleaner.&lt;/strong&gt; No fixed heights, no fancy stuff, just our accordion working as expected. &lt;strong&gt;Wonderful!&lt;/strong&gt; 😄&lt;/p&gt;

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

&lt;p&gt;The &lt;strong&gt;one caveat&lt;/strong&gt; to this solution is that you actually need to set an &lt;code&gt;overflow: hidden&lt;/code&gt; to the &lt;code&gt;.accordion-body&lt;/code&gt;'s internal &lt;code&gt;div&lt;/code&gt; in order to make this work. In my opinion, this little extra CSS is totally worth it, but let me know in the comments what you think about it!&lt;/p&gt;

&lt;p&gt;🎁 &lt;strong&gt;Bonus tip&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This trick only works because of the &lt;strong&gt;animability&lt;/strong&gt; of &lt;code&gt;grid-template-rows&lt;/code&gt; (and, more generally speaking, of &lt;strong&gt;grid tracks&lt;/strong&gt;). &lt;/p&gt;

&lt;p&gt;This is quite a &lt;strong&gt;recent feature&lt;/strong&gt; for some browsers: if you visit &lt;a href="https://caniuse.com/mdn-css_properties_grid-template-rows_animation" rel="noopener noreferrer"&gt;this page&lt;/a&gt; you'll notice that &lt;strong&gt;grid tracks animability&lt;/strong&gt; is something that, for example, only landed in &lt;strong&gt;Chrome&lt;/strong&gt; starting from &lt;strong&gt;version 107.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;At the time I'm writing this article all major browsers supports this feature, but always &lt;strong&gt;check for compatibility&lt;/strong&gt; first if you want to use this feature in production code!&lt;/p&gt;




&lt;p&gt;And that's all! Feel free to leave a comment and let me know if you already knew about this awesome CSS feature! 😉&lt;/p&gt;

&lt;p&gt;Till next time! 👋&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francescovetere" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--6Oibfu3K--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_800%2Fhttps%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>css</category>
    </item>
    <item>
      <title>The CSS property you didn't know you needed 👈</title>
      <dc:creator>Francesco Vetere</dc:creator>
      <pubDate>Sat, 18 Nov 2023 07:29:04 +0000</pubDate>
      <link>https://forem.com/francescovetere/the-css-property-you-didnt-know-you-needed-3fk0</link>
      <guid>https://forem.com/francescovetere/the-css-property-you-didnt-know-you-needed-3fk0</guid>
      <description>&lt;p&gt;Hi folks! 👋 Today I wanna talk about a CSS feature that, in my opinion, doesn't get too much attention... but it should! I'm talking about the &lt;code&gt;isolation&lt;/code&gt; property! 🪄 &lt;/p&gt;

&lt;p&gt;➡️ It basically provides more control over how elements interact with the rest of the document, and it is often an elegant solution for &lt;strong&gt;z-index issues&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's start with a practical example. I've built this simple &lt;strong&gt;card&lt;/strong&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%2Fijhrlacuaeoinn9sfo2n.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%2Fijhrlacuaeoinn9sfo2n.png" alt="Card without quotation mark"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;HTML&lt;/strong&gt; for it is pretty straightforward, and it looks something like this:&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;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__header"&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;class=&lt;/span&gt;&lt;span class="s"&gt;"card__avatar"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Daniel Clifford&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__role"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Verified Graduate&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__summary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;I received ...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card__description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;I was an EMT ...&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;Some &lt;strong&gt;styles&lt;/strong&gt; have been applied too, in order to set up colors, typography and layout. However, we can completely &lt;strong&gt;ignore them&lt;/strong&gt; as they will not play any role in what we are going to do now.&lt;/p&gt;

&lt;p&gt;Now, let's say that we want to add a &lt;strong&gt;quotation mark image&lt;/strong&gt; to the top-right corner of the card, as a little &lt;strong&gt;decorative element&lt;/strong&gt;. Something like this:&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%2F0kzren6hagk8gqjj4nsa.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%2F0kzren6hagk8gqjj4nsa.png" alt="Card with quotation mark"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🤔 How can we achieve that?&lt;/p&gt;

&lt;p&gt;💡 We could treat the quotation mark image as a &lt;strong&gt;pseudo-element&lt;/strong&gt;, and use &lt;code&gt;position: absolute&lt;/code&gt; to place it over the card! Let's give it a try 💪&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;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* We want the .card element to be the containing block for its children .card::before */&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* This is a pseudo-element, so we need to give it a content by definition */&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* We position our image over the card, with a little offset from the right */&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;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="c"&gt;/* We define a size for our image */&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;aspect-ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* This makes sure that the image is a square */&lt;/span&gt;

  &lt;span class="c"&gt;/* We bring in our image through a background-image */&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(https://raw.githubusercontent.com/francescovetere/testimonial-grid-section/main/images/bg-pattern-quotation.svg)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-repeat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;no-repeat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* This makes sure that the background actually fills all the available space (150px x 150px) */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the result we get:&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%2F1ma9pwsiszvm6zxcs7kd.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%2F1ma9pwsiszvm6zxcs7kd.png" alt="Card with quotation mark"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks good, except for one little issue: we want to push this image &lt;strong&gt;behind the text&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Here's where our &lt;code&gt;z-index&lt;/code&gt; comes into play. A little &lt;code&gt;z-index: -1&lt;/code&gt; should do the trick, right? Well... not exactly 😕&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%2Fwp4wi8bp5na4xim0yh1t.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%2Fwp4wi8bp5na4xim0yh1t.png" alt="Card with quotation mark"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;😱 It... disappeared?!&lt;/p&gt;

&lt;p&gt;Well, if you think about it, that makes perfect sense: &lt;strong&gt;every&lt;/strong&gt; element, by default, gets a &lt;code&gt;z-index: 0&lt;/code&gt;. So, it's like saying that each element on the page lives on the very &lt;strong&gt;same layer&lt;/strong&gt;, by default.&lt;/p&gt;

&lt;p&gt;When we declare a &lt;code&gt;z-index: -1&lt;/code&gt; on our pseudo-element, we are actually pushing it &lt;strong&gt;under the defaut layer&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;🤔 How can we solve this?&lt;/p&gt;

&lt;p&gt;Ideally, we would like to have a &lt;strong&gt;local&lt;/strong&gt;, &lt;strong&gt;scoped&lt;/strong&gt; &lt;code&gt;z-index&lt;/code&gt;: when I say that I want my pseudo-element to have a &lt;code&gt;z-index: -1&lt;/code&gt;, what I really mean is: "go behind everything, but &lt;strong&gt;NOT&lt;/strong&gt; behind the card itself!"&lt;/p&gt;

&lt;p&gt;✅ This concept is actually built-in into CSS, and it's called &lt;strong&gt;stacking context!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;stacking context&lt;/strong&gt; basically is defined by an element, that acts as the &lt;strong&gt;root&lt;/strong&gt; for its children's &lt;code&gt;z-index&lt;/code&gt; declarations. In particular, the children can never escape behind their stacking context, no matter how low their &lt;code&gt;z-index&lt;/code&gt; are.&lt;/p&gt;

&lt;p&gt;By default, a plain &lt;strong&gt;HTML document&lt;/strong&gt; will have a &lt;strong&gt;single stacking context&lt;/strong&gt;, and every element refers to it. That's why, when we assigned &lt;code&gt;z-index: -1&lt;/code&gt; to our pseudo-element, it was pushed all the way back: there was only one, global stacking context!&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;BUT&lt;/strong&gt;, of course, we can also &lt;strong&gt;create new stacking contexts&lt;/strong&gt; on arbitrary elements!&lt;/p&gt;

&lt;p&gt;There are a &lt;strong&gt;number of ways&lt;/strong&gt; we can create a new stacking context on an element. Some of them are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assigning a &lt;code&gt;transform&lt;/code&gt; to it;&lt;/li&gt;
&lt;li&gt;Assigning a &lt;code&gt;filter&lt;/code&gt; to it;&lt;/li&gt;
&lt;li&gt;Assigning an &lt;code&gt;opacity&lt;/code&gt; to it;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the full list of properties &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context#description" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All these methods have &lt;strong&gt;one, big issue&lt;/strong&gt;: they also come with &lt;strong&gt;side-effects!&lt;/strong&gt; 😢&lt;/p&gt;

&lt;p&gt;Yes, they create a stacking context, which is what we want, but they also do &lt;strong&gt;something else&lt;/strong&gt;, which &lt;strong&gt;maybe we don't necessarily want&lt;/strong&gt;!&lt;br&gt;
I mean, why should I be forced to apply an opacity to an element in order to create a stacking context, even if I didn't want to apply any opacity at all in the first place?&lt;/p&gt;

&lt;p&gt;🪄 Luckily, there's an &lt;strong&gt;easy solution&lt;/strong&gt;, and it's called &lt;strong&gt;isolation&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;isolation&lt;/code&gt; is a special property whose &lt;strong&gt;sole and unique purpose&lt;/strong&gt; is to &lt;strong&gt;create a new stacking context&lt;/strong&gt; on the element it is applied to, with &lt;strong&gt;no other side-effects&lt;/strong&gt;. 😄&lt;/p&gt;

&lt;p&gt;It accepts two values, &lt;code&gt;auto&lt;/code&gt; and &lt;code&gt;isolate&lt;/code&gt;. Of course, &lt;code&gt;isolate&lt;/code&gt; is what we want.&lt;/p&gt;

&lt;p&gt;✅ So, that's it! The final solution to this problem reveals to be extremely simple:&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;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;isolation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;isolate&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;Here's the result with all the code, if you want to mess around with it! ☺️&lt;/p&gt;

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




&lt;p&gt;And that's all! Feel free to leave a comment and let me know if you already knew about this awesome property! 😉&lt;/p&gt;

&lt;p&gt;Till next time! 👋&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francescovetere" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--6Oibfu3K--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_800%2Fhttps%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>css</category>
    </item>
    <item>
      <title>How I organize my CSS declarations 🗂️</title>
      <dc:creator>Francesco Vetere</dc:creator>
      <pubDate>Sun, 12 Nov 2023 02:35:08 +0000</pubDate>
      <link>https://forem.com/francescovetere/how-i-organize-my-css-declarations-2d52</link>
      <guid>https://forem.com/francescovetere/how-i-organize-my-css-declarations-2d52</guid>
      <description>&lt;p&gt;Hi folks! 👋 A while ago, I started adopting this little style &lt;strong&gt;convention&lt;/strong&gt; in my CSS code, and I wanted to share it with you in this article. &lt;/p&gt;

&lt;p&gt;➡️ It is about defining an &lt;strong&gt;order&lt;/strong&gt; over the various declarations that may appear into a selector. Let me be more specific.&lt;/p&gt;

&lt;p&gt;Instead of just throwing all of my declarations one after another, without any particular order, I try to divide them &lt;strong&gt;semantically&lt;/strong&gt;, grouping them under a common area.&lt;/p&gt;

&lt;p&gt;Approximately, this is the &lt;strong&gt;skeleton&lt;/strong&gt; that I try to follow:&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;.my-selector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* display stuff */&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;

  &lt;span class="c"&gt;/* positioning stuff */&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;

  &lt;span class="c"&gt;/* box-model stuff */&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;

  &lt;span class="c"&gt;/* typography stuff */&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;...;&lt;/span&gt;

  &lt;span class="c"&gt;/* manipulation stuff */&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;  

  &lt;span class="c"&gt;/* misc stuff */&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&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;Of course this is just an approximate blueprint, and I &lt;strong&gt;do not follow it strictly&lt;/strong&gt; each and every time. If an exception should be made, so be it! &lt;/p&gt;

&lt;p&gt;But the thing is, in the general picture, keeping this kind of style helps my code in at least 3 ways:&lt;/p&gt;

&lt;p&gt;✅ It's more &lt;strong&gt;consistent&lt;/strong&gt;&lt;br&gt;
✅ It's &lt;strong&gt;less error-prone&lt;/strong&gt;&lt;br&gt;
✅ Overall it's more readable, and thus more &lt;strong&gt;maintainable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just to give you a quick &lt;strong&gt;comparison example&lt;/strong&gt;, this is what a simple button could look like without using any ordering for its various declarations:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;text-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&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;inline-flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5em&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&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="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250ms&lt;/span&gt; &lt;span class="n"&gt;ease-out&lt;/span&gt; &lt;span class="n"&gt;opacity&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="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;700&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="m"&gt;#252b2e&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="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&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;😐 Pretty overwhelming, isn't it?&lt;br&gt;
The very same button, with some tidy-up, could look a little bit nicer:&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="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;inline-flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&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="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5em&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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="m"&gt;#252b2e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;font-size&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="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;700&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="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250ms&lt;/span&gt; &lt;span class="n"&gt;ease-out&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&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;😁 Much better!&lt;br&gt;
Now, at a glance, I can see more clearly &lt;strong&gt;where everything is placed&lt;/strong&gt; in the code, and if I just need to modify the &lt;code&gt;background-color&lt;/code&gt; for this button, I know where to look.&lt;/p&gt;

&lt;p&gt;At this point, one could also enforce an ordering for the declarations &lt;strong&gt;inside&lt;/strong&gt; each group: it could be alphabetical, it could be something else.&lt;/p&gt;

&lt;p&gt;I really just focus on the &lt;strong&gt;big picture&lt;/strong&gt; here: to me, it doesn't really matter much if a &lt;code&gt;font-size&lt;/code&gt; comes before or after a &lt;code&gt;font-weight&lt;/code&gt;.&lt;br&gt;
What matters, is that typography-related declarations are well distinguishable and separated from, for example, display-related ones.&lt;/p&gt;

&lt;p&gt;And that's all! Feel free to leave a comment and let me know what you think about this! 😉 &lt;/p&gt;

&lt;p&gt;Till next time! 👋&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francescovetere" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>css</category>
    </item>
    <item>
      <title>I made a CSS Frankenstein 👻</title>
      <dc:creator>Francesco Vetere</dc:creator>
      <pubDate>Tue, 07 Nov 2023 17:14:18 +0000</pubDate>
      <link>https://forem.com/francescovetere/i-made-a-css-frankenstein-ahk</link>
      <guid>https://forem.com/francescovetere/i-made-a-css-frankenstein-ahk</guid>
      <description>&lt;p&gt;Hi folks 👋 Today, I wanted to share with you this cool &lt;strong&gt;CSS art&lt;/strong&gt; I made as part of a spooky &lt;a href="https://cssbattle.dev/play/177" rel="noopener noreferrer"&gt;CSS Battle&lt;/a&gt; 👻:&lt;/p&gt;

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

&lt;p&gt;This was not only a lot of fun, but really educational too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I found out that the &lt;strong&gt;head&lt;/strong&gt; shape could be easily accomplished with a fancy &lt;code&gt;border-radius&lt;/code&gt;, which I generated with this &lt;a href="https://9elements.github.io/fancy-border-radius/" rel="noopener noreferrer"&gt;cool website&lt;/a&gt;. Basically, that shape is obtained with a:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;border-radius: 15% 15% 100% 100% / 15% 15% 100% 100%;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Also, the &lt;strong&gt;hair fringe&lt;/strong&gt; was perfectly suitable for a &lt;code&gt;clip-path&lt;/code&gt;. I used this other &lt;a href="https://bennettfeely.com/clippy/" rel="noopener noreferrer"&gt;cool website&lt;/a&gt; in order to better visualize what I was clipping. I basically want a triangle, so I can obtain it with:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;clip-path: polygon(100% 0, 0 0, 50% 100%);&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;mouth&lt;/strong&gt; was also perfectly suitable for a &lt;code&gt;clip-path&lt;/code&gt;, since it is essentially a semicircle:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0% 100%);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;📽️ If you enjoy these kind of things, here's a video of me speedrunning through the whole process 😉&lt;/p&gt;

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

&lt;p&gt;Of course, as often happens in CSS, there are a &lt;strong&gt;lot of different ways&lt;/strong&gt; we could accomplish the same results. &lt;strong&gt;Let me know&lt;/strong&gt; if you would have done something differently in any way, I'm really curious! 😊&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francescovetere" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>frontend</category>
    </item>
    <item>
      <title>CSS-only direction-aware hover effects</title>
      <dc:creator>Francesco Vetere</dc:creator>
      <pubDate>Fri, 03 Nov 2023 21:03:26 +0000</pubDate>
      <link>https://forem.com/francescovetere/css-only-direction-aware-hover-effects-2hmo</link>
      <guid>https://forem.com/francescovetere/css-only-direction-aware-hover-effects-2hmo</guid>
      <description>&lt;p&gt;Hi everyone! 👋 I just discovered a really great way to build a simple &lt;strong&gt;direction-aware hover mechanism&lt;/strong&gt; using nothing but &lt;strong&gt;CSS&lt;/strong&gt; (big thanks to Kevin Powell 😁), and I wanted to share it with you with this simple codepen I created.&lt;/p&gt;

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

&lt;p&gt;If you hover over any of these links with your mouse coming from the top or the bottom, you'll notice a simple decoration coming under the link itself: nothing too fancy, plain old CSS here.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;real magic&lt;/strong&gt; comes if you do hover on a link coming from its left or its right: in these cases, you'll notice that this decoration doesn't just "appear" under the link, it &lt;strong&gt;slides&lt;/strong&gt; into it!&lt;/p&gt;

&lt;p&gt;This cool effect is only possible thanks to the &lt;code&gt;:has()&lt;/code&gt; selector: in this particular example, it basically allows us to target an &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element such that its next sibling is currently hovered.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;:has()&lt;/code&gt; selector is &lt;strong&gt;kinda new&lt;/strong&gt; in the CSS world, so it is possible that your browser currently doesn't support it (you can check that &lt;a href="https://caniuse.com/css-has" rel="noopener noreferrer"&gt;here&lt;/a&gt;). &lt;br&gt;
If that's the case, you just won't see this nice sliding effect, but the overall layout won't break. So, I consider this a really good progressive enhancement.&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;:has()&lt;/code&gt;, this operation would have required some JavaScript in order to manually target the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; that meets the desired condition. Now instead, this is possible using &lt;strong&gt;nothing but CSS&lt;/strong&gt;: kinda amazing in my opinion! 😁&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/francescovetere" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>css</category>
    </item>
  </channel>
</rss>
