<?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: Andy Bell</title>
    <description>The latest articles on DEV Community by Andy Bell (@hankchizljaw).</description>
    <link>https://dev.to/hankchizljaw</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%2F64381%2F1471244f-82a3-4fea-a160-dcb4cb5bb6ef.JPG</url>
      <title>DEV Community: Andy Bell</title>
      <link>https://dev.to/hankchizljaw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hankchizljaw"/>
    <language>en</language>
    <item>
      <title>A Modern CSS Reset</title>
      <dc:creator>Andy Bell</dc:creator>
      <pubDate>Tue, 01 Oct 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/hankchizljaw/a-modern-css-reset-6p3</link>
      <guid>https://dev.to/hankchizljaw/a-modern-css-reset-6p3</guid>
      <description>&lt;p&gt;I think about and enjoy very boring CSS stuff—probably much more than I should do, to be honest. One thing that I’ve probably spent too much time thinking about over the years, is CSS resets.&lt;/p&gt;

&lt;p&gt;In this modern era of web development, we don’t really need a heavy-handed reset, or even a reset at all, because CSS browser compatibility issues are much less likely than they were in the old IE 6 days. That era was when resets such as &lt;a href="https://github.com/necolas/normalize.css/"&gt;normalize.css&lt;/a&gt; came about and saved us all heaps of hell. Those days are gone now and we can trust our browsers to behave more, so I think resets like that are probably mostly redundant.&lt;/p&gt;

&lt;h2&gt;
  
  
  A reset of sensible defaults
&lt;/h2&gt;

&lt;p&gt;I still like to reset stuff, so I’ve been slowly and continually tinkering with a reset myself over the years in an obsessive &lt;a href="https://en.wikipedia.org/wiki/Code_golf"&gt;code golf&lt;/a&gt; manner. I’ll explain what’s in there and why, but before I do that, here it is in its entirety:&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="c"&gt;/* Box sizing rules */&lt;/span&gt;
&lt;span class="o"&gt;*,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Remove default padding */&lt;/span&gt;
&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&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="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Remove default margin */&lt;/span&gt;
&lt;span class="nt"&gt;body&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="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;li&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="nt"&gt;figcaption&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;blockquote&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;dl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;dd&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="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Set core body defaults */&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;smooth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-rendering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;optimizeSpeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Remove list styles on ul, ol elements with a class attribute */&lt;/span&gt;
&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;list-style&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="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* A elements that don't have a class get default styles */&lt;/span&gt;
&lt;span class="nt"&gt;a&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;class&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;text-decoration-skip-ink&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;span class="c"&gt;/* Make images easier to work with */&lt;/span&gt;
&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&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="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Natural flow and rhythm in articles by default */&lt;/span&gt;
&lt;span class="nt"&gt;article&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&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="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;span class="c"&gt;/* Inherit fonts for inputs and buttons */&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;textarea&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Remove all animations and transitions for people that prefer not to see them */&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&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="nl"&gt;animation-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.01ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.01ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="cp"&gt;!important&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;h3&gt;
  
  
  Breaking it down
&lt;/h3&gt;

&lt;p&gt;We start with box-sizing. I just flat out reset all elements and pseudo-elements to use &lt;code&gt;box-sizing: border-box&lt;/code&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="o"&gt;*,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&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;Some people think that pseudo-elements should &lt;code&gt;inherit&lt;/code&gt; box sizing, but I think that’s silly. If you want to use a &lt;a href="https://css-tricks.com/almanac/properties/b/box-sizing/"&gt;different box-sizing value&lt;/a&gt;, set it explicitly—at least that’s what I do, anyway. I wrote about box-sizing more over on &lt;a href="https://cssfromscratch.com/posts/bite-sized-basics-box-sizing/"&gt;CSS From Scratch&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="c"&gt;/* Remove default padding */&lt;/span&gt;
&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&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="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Remove default margin */&lt;/span&gt;
&lt;span class="nt"&gt;body&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="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;li&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="nt"&gt;figcaption&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;blockquote&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;dl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;dd&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="m"&gt;0&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;After box-sizing, I do a blanket reset of &lt;code&gt;margin&lt;/code&gt; and &lt;code&gt;padding&lt;/code&gt;, where it gets set by the browser styles. This is all pretty self-explanatory, so I won’t get into it too much.&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;will&lt;/em&gt; mention the situation with lists, though. I select only lists that &lt;strong&gt;do&lt;/strong&gt; have a &lt;code&gt;class&lt;/code&gt; attribute because if a plain ol’ &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; gets used, I want it to look like a list. A lot of resets, including my previous ones, aggressively remove that.&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;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;smooth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-rendering&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;optimizeSpeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5&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;Next up: body styles. I keep this really simple. It’s useful for the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; to fill the viewport, even when empty, so I do that by setting the &lt;code&gt;min-height&lt;/code&gt; to &lt;code&gt;100vh&lt;/code&gt;. I also like smooth anchor scrolling, so I set &lt;code&gt;scroll-behavior: smooth&lt;/code&gt;, too.&lt;/p&gt;

&lt;p&gt;I only set two text styles. I set the &lt;code&gt;line-height&lt;/code&gt; to be &lt;code&gt;1.5&lt;/code&gt; because the default &lt;code&gt;1.2&lt;/code&gt; just isn’t big enough to have accessible, readable text. I also set &lt;code&gt;text-rendering&lt;/code&gt; to &lt;code&gt;optimizeSpeed&lt;/code&gt;. Using &lt;code&gt;optimizeLegibility&lt;/code&gt; makes your text look nicer, but can have serious performance issues such as &lt;a href="https://marco.org/2012/11/15/text-rendering-optimize-legibility"&gt;30 second loading delays&lt;/a&gt;, so I try to avoid that now. I do sometimes add it to sections of microcopy though.&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;ul&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt;
&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;list-style&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like the margin and padding rules, I only reset &lt;code&gt;list-style&lt;/code&gt; where a list element has a &lt;code&gt;class&lt;/code&gt; attribute.&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;a&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;class&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;text-decoration-skip-ink&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;For links without a class attribute, I set &lt;code&gt;text-decoration-skip-ink: auto&lt;/code&gt; so that the underline renders in a much more readable fashion. This could be set on links globally, but it’s caused one or two conflicts in the past for me, so I keep it 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="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&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="nb"&gt;block&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;Good ol’ fluid image styles come next. I set images to be a block element because frankly, life is too short for that weird gap you get at the bottom, and realistically, images—especially with work I do—tend to behave like blocks.&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="o"&gt;&amp;gt;&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="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;I &lt;em&gt;really&lt;/em&gt; like this CSS trick and I’ve finally been brave enough to add it to the reset. &lt;a href="https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/"&gt;The lobotomised owl selector&lt;/a&gt; targets direct descendants of an article and adds &lt;code&gt;1em&lt;/code&gt; of top margin to them. This gives a solid rhythm to flow content. I actually use a &lt;code&gt;.flow&lt;/code&gt; utility in every project now. You can &lt;a href="https://24ways.org/2018/managing-flow-and-rhythm-with-css-custom-properties/"&gt;read more about it on 24 Ways&lt;/a&gt;. In fact, I reckon it’s my most used CSS these days.&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;input&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;textarea&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&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;Another thing I’ve finally been brave enough to set as default is &lt;code&gt;font: inherit&lt;/code&gt; on input elements, which as a shorthand, &lt;a href="https://css-tricks.com/almanac/properties/f/font/"&gt;does exactly what it says on the tin&lt;/a&gt;. No more tiny (mono, in some cases) text!&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="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-reduced-motion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;)&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="nl"&gt;animation-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.01ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.01ms&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;scroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="cp"&gt;!important&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;Last, and by no means least, is a single &lt;code&gt;@media&lt;/code&gt; query that resets animations, transitions and scroll behaviour if the &lt;a href="https://css-tricks.com/introduction-reduced-motion-media-query/"&gt;user prefers reduced motion&lt;/a&gt;. I like this in the reset, with &lt;a href="https://hankchizljaw.com/wrote/css-specificity-and-the-cascade/"&gt;specificity trumping&lt;/a&gt; &lt;code&gt;!important&lt;/code&gt; selectors, because most likely now, if a user doesn’t want motion, they won’t get it, regardless of the CSS that follows this reset.&lt;/p&gt;

&lt;p&gt;ℹ️ &lt;strong&gt;Update&lt;/strong&gt;: &lt;em&gt;Thanks to &lt;a href="https://github.com/atomiks"&gt;@atomiks&lt;/a&gt;, this has &lt;a href="https://github.com/hankchizljaw/modern-css-reset/pull/6"&gt;been updated&lt;/a&gt; so it doesn’t break JavaScript events watching for &lt;code&gt;animationend&lt;/code&gt; and &lt;code&gt;transitionend&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;That’s it, a very tiny reset that makes my life a lot easier. If you like it, you can use it yourself, too! You can find it on &lt;a href="https://github.com/hankchizljaw/modern-css-reset"&gt;GitHub&lt;/a&gt; or &lt;a href="https://www.npmjs.com/package/modern-css-reset"&gt;NPM&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>What do you find the most difficult with CSS?</title>
      <dc:creator>Andy Bell</dc:creator>
      <pubDate>Sat, 28 Sep 2019 12:22:06 +0000</pubDate>
      <link>https://dev.to/hankchizljaw/what-do-you-find-the-most-difficult-with-css-1geg</link>
      <guid>https://dev.to/hankchizljaw/what-do-you-find-the-most-difficult-with-css-1geg</guid>
      <description>&lt;p&gt;I’m writing a &lt;a href="https://cssfromscratch.com"&gt;new book&lt;/a&gt; that teaches you how to write CSS from scratch, so I’m curious about what people find the most difficult with CSS. &lt;/p&gt;

&lt;p&gt;Also, what do you wish you were taught about CSS, early on in your career?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>css</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Create a semantic “breakout” button to make an entire element clickable</title>
      <dc:creator>Andy Bell</dc:creator>
      <pubDate>Fri, 27 Sep 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/hankchizljaw/create-a-semantic-breakout-button-to-make-an-entire-element-clickable-2ng</link>
      <guid>https://dev.to/hankchizljaw/create-a-semantic-breakout-button-to-make-an-entire-element-clickable-2ng</guid>
      <description>&lt;p&gt;A common design pattern is to have something like a “card” element that has to be fully clickable. This is usually because it links to another page or triggers a JavaScript action.&lt;/p&gt;

&lt;p&gt;The problem though, is that often, you end up with stuff that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;onClick=&lt;/span&gt;&lt;span class="s"&gt;"alert('Nope')"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Please don’t ever do this.&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;You should absolutely never attach a click event to a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element, though, even if you sprinkle it with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques"&gt;aria roles&lt;/a&gt; to “fake” a real button. &lt;a href="https://dev.to/wrote/context-and-caveats/"&gt;Although this is technically possible&lt;/a&gt;, if assistive technology doesn’t support the aria roles in question, the user will just get &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s and nothing else. &lt;strong&gt;Not cool&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we’re going to remedy this common crime by instead using the magic of CSS to give us the desired fully clickable element effect, while also using proper semantic elements and JavaScript and as an enhancement.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we’re making
&lt;/h2&gt;

&lt;p&gt;We’re going to use the context of an &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; that when a button is clicked, a JavaScript alert fires. Here’s a CodePen demo:&lt;/p&gt;

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

&lt;p&gt;To code along, you’re going to need a HTML file, a CSS file and a JavaScript file. I recommend that you use a service like &lt;a href="https://codepen.io/"&gt;CodePen&lt;/a&gt; that does all of this for you.&lt;/p&gt;

&lt;p&gt;For the rest of this section, we’re going to be laying the foundations. If you’re in a rush, you can skip this section and use this &lt;a href="https://codepen.io/andybelldesign/pen/43dd6339a10e9830264524bbdef3fcfc"&gt;starter CodePen&lt;/a&gt; instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started with markup
&lt;/h3&gt;

&lt;p&gt;We need some HTML to work with, so add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;"box"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;A semantic, breakout button&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This whole box is clickable, but still uses a button element, correctly.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"breakout-button"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Say Hi 👋&lt;span class="nt"&gt;&amp;lt;/button&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;We’ve got an article, a heading, a paragraph and a button. Job done for HTML for now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Base CSS styles
&lt;/h3&gt;

&lt;p&gt;Before we get into the proper CSS stuff, let’s set some base styles. Add this CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#efefef&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;3rem&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.4&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="n"&gt;-apple-system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlinkMacSystemFont&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;'Segoe UI'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Roboto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;'Apple Color Emoji'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;'Segoe UI Emoji'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;'Segoe UI Symbol'&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;1.2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&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;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.1&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;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.box&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="m"&gt;#fff&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;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#252525&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="nl"&gt;box-shadow&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;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;300ms&lt;/span&gt; &lt;span class="n"&gt;ease-in-out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;box-shadow&lt;/span&gt; &lt;span class="m"&gt;400ms&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="m"&gt;100ms&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;.box&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.box&lt;/span&gt;&lt;span class="nd"&gt;:focus-within&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="n"&gt;rgba&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="m"&gt;0&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="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-0.5rem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&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="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;Looking pretty decent, right? That’s it for our base styles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the breakout button component
&lt;/h2&gt;

&lt;p&gt;We’ve got base styles, so let’s focus all of our attention on the &lt;code&gt;.breakout-button&lt;/code&gt; component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core component styles
&lt;/h3&gt;

&lt;p&gt;In your CSS, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.breakout-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inherit&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;600&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.6rem&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&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="n"&gt;currentColor&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="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&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="n"&gt;background&lt;/span&gt; &lt;span class="m"&gt;100ms&lt;/span&gt; &lt;span class="n"&gt;ease&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;static&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, we have some simple styles for our button which make it looks nicer. A handy takeaway trick here is that because we are using &lt;code&gt;font: inherit&lt;/code&gt; and &lt;code&gt;color: currentColor&lt;/code&gt;, we get all of our text styles for free, using the cascade, which is by far my favourite aspect of CSS. Also notice that we are setting &lt;code&gt;.breakout-button&lt;/code&gt; to be &lt;code&gt;position: static&lt;/code&gt;. This is because we want our “breakout element” (coming up) to literally &lt;em&gt;break out&lt;/em&gt; of the button!&lt;/p&gt;

&lt;p&gt;Related to this is that the &lt;code&gt;.box&lt;/code&gt; element has &lt;code&gt;position: relative&lt;/code&gt;, which means that any child elements without a relative parent that have &lt;code&gt;position: absolute&lt;/code&gt; will be contained in this &lt;code&gt;.box&lt;/code&gt;. Because that’s what our breakout button will do as its sole purpose, you should always remember to make its containing parent behave like this. The &lt;code&gt;position: static&lt;/code&gt; on the &lt;code&gt;.breakout-button&lt;/code&gt; itself is a failsafe to make sure the “breakout element” isn’t ever contained to the &lt;code&gt;.breakout-button&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;Right, let’s add some more code. Under the &lt;code&gt;.breakout-button&lt;/code&gt; component style, add this CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.breakout-button&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.breakout-button&lt;/span&gt;&lt;span class="nd"&gt;::before&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;We’ve set both the button and its &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements"&gt;&lt;code&gt;::before&lt;/code&gt; pseudo-element&lt;/a&gt; to have a &lt;code&gt;pointer&lt;/code&gt; cursor. There’s some contention around wether a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; should have a &lt;code&gt;pointer&lt;/code&gt; cursor and I very much sit in the camp that by proxy of exposure, it is now an expected style and shouldn’t really have a negative user experience impact.&lt;/p&gt;

&lt;p&gt;Anyway, we digress… Add the following CSS to create the “breakout element”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.breakout-button&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;''&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="nb"&gt;block&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;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&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;left&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;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&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;100%&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;It’s pretty straightforward. We make this pseudo-element an absolutely positioned block element that will “break out” until it hits the bounds of a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/position"&gt;relative, absolute or fixed&lt;/a&gt; parent. In our context, this parent is the &lt;code&gt;.box&lt;/code&gt; element because it has &lt;code&gt;position: relative&lt;/code&gt; set.&lt;/p&gt;

&lt;p&gt;The “breakout element” is visually hidden, so to help you understand how it behaves, check out this demo where I’ve added some colour to it:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Interactive styles
&lt;/h3&gt;

&lt;p&gt;Now that we’ve got the core component setup, let’s style up the interactivity. Add this to your CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.breakout-button&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&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="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.breakout-button&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333333&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;The first thing we do is remove focus outline from the button. I can’t stress this enough, though: you &lt;strong&gt;must&lt;/strong&gt; have visible focus styles for interactive elements, so keyboard users can actually see where their focus currently is. If you remove the default &lt;code&gt;outline&lt;/code&gt; CSS rule, you &lt;strong&gt;must&lt;/strong&gt; replace it with something effective and obvious.&lt;/p&gt;

&lt;p&gt;This is exactly what we’re going to do now, by adding a solid outline to our “breakout element” when the parent button is focused. Add this CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.breakout-button&lt;/span&gt;&lt;span class="nd"&gt;:focus::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;outline-offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-0.8rem&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;Now that we’ve sorted our button out, let’s add some hover styles to our &lt;code&gt;.box&lt;/code&gt; element. Add this to your CSS, with all of the other &lt;code&gt;.box&lt;/code&gt; styles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.box&lt;/span&gt;&lt;span class="nd"&gt;:focus-within&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="n"&gt;rgba&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="m"&gt;0&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="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-0.5rem&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 makes our box shift up either on hover, or if there’s focus inside it, which means when our button element is focused, our box’s appearance will change.&lt;/p&gt;

&lt;p&gt;That’s it! Our “breakout button” finished and this is what it should look like:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Improving our breakout button with progressive enhancement
&lt;/h2&gt;

&lt;p&gt;As usual, I make you think that you’re done, but then slip in some progressive enhancement when you least expect it, because as it stands, our project is just &lt;em&gt;ok&lt;/em&gt;. Because we’re using a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, it’ll be about as useful as a chocolate teapot when JavaScript isn’t available. What we’re going to do to fix this is hide the button by default with a &lt;code&gt;hidden&lt;/code&gt; attribute, and when JavaScript is available, we’ll show it by removing the &lt;code&gt;hidden&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;We’re also going to add a bonus bit of attention to detail and only display the interactive states when JavaScript is available too, using a &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes"&gt;data attribute&lt;/a&gt; as a style hook.&lt;/p&gt;

&lt;p&gt;Open up your HTML and add a &lt;code&gt;hidden&lt;/code&gt; attribute to the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"breakout-button"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Say Hi 👋&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;Now we need to add some JavaScript to show the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; by removing that &lt;code&gt;hidden&lt;/code&gt; element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.breakout-button&lt;/span&gt;&lt;span class="dl"&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;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&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;Like I said above, though, we should also only show interactive styles such as &lt;code&gt;:hover&lt;/code&gt; and &lt;code&gt;:focus&lt;/code&gt; states when the button is available too. Let’s replace your existing JavaScript with this JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.breakout-button&lt;/span&gt;&lt;span class="dl"&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;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-interactive&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="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oh hi there 👋&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We’ve added an event handler for the button’s click event, but most importantly, we’ve added a &lt;code&gt;data-interactive&lt;/code&gt; attribute to the button’s parent, which means we can now use this as a style hook.&lt;/p&gt;

&lt;p&gt;Amend your CSS by deleting this block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nc"&gt;.box&lt;/span&gt;&lt;span class="nd"&gt;:focus-within&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="n"&gt;rgba&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="m"&gt;0&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="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-0.5rem&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;And now, replace it with this block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-interactive&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-interactive&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:focus-within&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="n"&gt;rgba&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="m"&gt;0&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="m"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-0.5rem&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;Now, the &lt;code&gt;.box&lt;/code&gt; will behave like a normal element when JavaScript isn’t available, like so:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;That’s it, we’re done. Yours should now look like this:&lt;/p&gt;

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

&lt;p&gt;Hopefully this article shows that when you think outside the box (or inside it in this context), CSS, semantic HTML and a sprinkle of JavaScript can give you solid, progressive components that work for everyone.&lt;/p&gt;

</description>
      <category>css</category>
      <category>a11y</category>
      <category>html</category>
    </item>
    <item>
      <title>Bite Sized Basics: Box Sizing</title>
      <dc:creator>Andy Bell</dc:creator>
      <pubDate>Mon, 23 Sep 2019 19:39:00 +0000</pubDate>
      <link>https://dev.to/hankchizljaw/bite-sized-basics-box-sizing-4al2</link>
      <guid>https://dev.to/hankchizljaw/bite-sized-basics-box-sizing-4al2</guid>
      <description>&lt;p&gt;&lt;em&gt;I originally posted this on &lt;a href="https://cssfromscratch.com" rel="noopener noreferrer"&gt;https://cssfromscratch.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;If there’s ever one really important thing to remember when writing CSS is that &lt;strong&gt;everything is a box&lt;/strong&gt;. Regardless of how it looks visually—it’s still a box. &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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7om8k69evky4olt9qmte.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7om8k69evky4olt9qmte.jpg" title="Even when an element has 100% border-radius, the browser treats it as a box." alt="A circle that has a box behind it to demonstrate how it works on the web"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take the above example: it’s visually a circle, by proxy of &lt;a href="https://css-tricks.com/almanac/properties/b/border-radius/" rel="noopener noreferrer"&gt;border-radius&lt;/a&gt;, but it’s still a box, as far as the browser is concerned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Padding and borders
&lt;/h2&gt;

&lt;p&gt;When we add padding and borders to an element, by default, their values will be added to the computed width and height. This can be confusing—especially when you are first starting 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="nc"&gt;.box&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="m"&gt;100px&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;10px&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="m"&gt;10px&lt;/span&gt; &lt;span class="nb"&gt;solid&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkiupigzfys0brvs6w922.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkiupigzfys0brvs6w922.jpg" title="The width, padding and border contributing to a 140px computed value." alt="A stack of three boxes to represent width, padding and border. Width is set to 100px, while padding and border are set to 10px. There is a measure at the bottom which shows this calculated as 140px"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What happens here is your &lt;code&gt;.box&lt;/code&gt;’s computed width is actually calculated as &lt;strong&gt;140px&lt;/strong&gt;. This is how the box model works, out of the box (pun intended), and is expected behaviour. Most of the time though, it’s preferable for this not to be the case, so we add this little snippet of CSS:&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;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&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 completely transforms the browser’s calculation because what it does is say “Take the dimensions that I specified and also account for the padding and border, too”. What you get as a result, is a box that instead of being 140px wide, is now 100px wide, just like you specified! &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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1l1l15vaz2wgbii9nuqf.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1l1l15vaz2wgbii9nuqf.jpg" title="The fixed box with a predictable width." alt="The same example as above, but the box is now measured as 100px. This is demonstrated with all of the properties inside one box with a ghost of the old box behind it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;box-sizing&lt;/code&gt; rule is usually added as a global selector to a reset, or default normalising styles, so to set a more complete example, this is how our box CSS now looks:&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="c"&gt;/* Reset rule */&lt;/span&gt;
&lt;span class="o"&gt;*,&lt;/span&gt; 
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&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 component */&lt;/span&gt;
&lt;span class="nc"&gt;.box&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="m"&gt;100px&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;10px&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="m"&gt;10px&lt;/span&gt; &lt;span class="nb"&gt;solid&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;What this now does is instead of just targeting the &lt;code&gt;.box&lt;/code&gt;, it targets every element on the page and any &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements" rel="noopener noreferrer"&gt;pseudo-elements&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;You can read more on box sizing over on MDN, where there is some &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing" rel="noopener noreferrer"&gt;very good documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Setting &lt;code&gt;box-sizing: border-box&lt;/code&gt; is such a life saver—especially for responsive design. This is so much the case that we even have &lt;a href="https://css-tricks.com/international-box-sizing-awareness-day/" rel="noopener noreferrer"&gt;“International box-sizing Awareness Day”&lt;/a&gt; on February 1st, every year.&lt;/p&gt;

&lt;p&gt;Anyway: &lt;a href="https://www.producthunt.com/upcoming/css-from-scratch" rel="noopener noreferrer"&gt;sign up for updates on Product Hunt&lt;/a&gt;, &lt;a href="https://cssfromscratch.com/feed.xml" rel="noopener noreferrer"&gt;subscribe to the RSS feed&lt;/a&gt; or &lt;a href="https://twitter.com/cssfromscratch" rel="noopener noreferrer"&gt;follow @cssfromscratch on Twitter&lt;/a&gt; to keep in the loop.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>css</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Keeping it simple with CSS that scales</title>
      <dc:creator>Andy Bell</dc:creator>
      <pubDate>Wed, 18 Sep 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/hankchizljaw/keeping-it-simple-with-css-that-scales-2phg</link>
      <guid>https://dev.to/hankchizljaw/keeping-it-simple-with-css-that-scales-2phg</guid>
      <description>&lt;p&gt;This is the written version of my new talk, “Keeping it simple with CSS that scales”, which I first delivered at &lt;a href="https://2019.stateofthebrowser.com/"&gt;State of the Browser 2019&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s a &lt;em&gt;very&lt;/em&gt; long read, so I recorded an audio version, too:&lt;/p&gt;




&lt;p&gt;CSS has a weird place on the web today. There’s a lot of polarisation, with the opinion being seemingly split on “CSS sucks” and “CSS rules, learn it better, fools”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zy4hVsKq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.002_v6fao7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zy4hVsKq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.002_v6fao7.png" alt="'CSS sucks' and 'CSS rules, learn it better fools' split diagonally, 50:50"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I empathise with the “CSS rules” camp and I’ll explain why: I have a theory as to why the “CSS sucks” camp have the attitude that they do. I think it’s a combination of them over-engineering their CSS, not fully understanding the power of CSS and finally, approaching it like it is a language like JavaScript and expecting it to work in the same way.&lt;/p&gt;

&lt;p&gt;What I’m going to do in this piece, is tackle the first bit and talk to you all about how we can simplify CSS to give us incredible power, while also being as low-tech as possible. The secret sauce is that most of the content isn’t actually about CSS, but that’ll all become clearer, later.&lt;/p&gt;

&lt;h1&gt;
  
  
  Let’s talk about scale
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OD05mfdC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.006_kuw6cr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OD05mfdC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.006_kuw6cr.png" alt="'Scale' is bollocks, most of the time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I absolutely &lt;em&gt;hate&lt;/em&gt; it when we use the term, “Scale”. I think we are stuck with it though, just like we are stuck with “JAMstack”, “Serverless” and “performant”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1rhzUqqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.007_nikh6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1rhzUqqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.007_nikh6a.png" alt="A list: Serverless, JAMstack, Performant, with a poop emoji as the list decoration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They’re all equally awful words, but one thing they do is create a common, recognisable construct for communication. As much as it pained me, it’s exactly why I named this talk “Keeping it simple with CSS that scales”. You probably knew before I even opened my gob that I’d be talking about working on massive codebases, which at some point in this talk, I’ll get to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xSVsAVGl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.008_plltsn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xSVsAVGl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.008_plltsn.png" alt="A list: Serverless, JAMstack, Performant, with a chat emoji as the list decoration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One thing that I do get pissed off about with “Scale”, though, is that gets slightly muddied when people use it as an excuse to over-engineer something.&lt;/p&gt;

&lt;p&gt;Let’s take this common example. It usually gets said by some Bay Area tech bro:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We use a CSS-in-JS library because our product needs to scale&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZoEJlts3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.011_swdahl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZoEJlts3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.011_swdahl.png" alt="A typical bearded hipster has a speech bubble, which reads: 'We use CSS-in-JS because we need to scale'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s be honest for a moment, folks: most of the tepid guff that these tech bros are making will only scale as far as the bin, so it’s not much of a valid excuse, is it?&lt;/p&gt;

&lt;p&gt;I’ll also be bold and straight-up say that I don’t think using scale as an excuse for over-engineering stuff—especially CSS—is acceptable, even for huge teams that work on huge products. Keep that in mind, because I hope, by the end of this session, you’re going to be in agreement with me.&lt;/p&gt;

&lt;h1&gt;
  
  
  Four key things
&lt;/h1&gt;

&lt;p&gt;I think we can focus on four key things today, and for the rest of this piece, I’m going to run us through them in detail with a little progress thing, so you know roughly how much longer you have to endure me for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iXddFSHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.013_wwombv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iXddFSHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.013_wwombv.png" alt="Don’t panic, Communicate, Consistency, Simplification"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I could package this up as &lt;em&gt;DCCS&lt;/em&gt; and really mop up the upvotes on that orange website, right?&lt;/p&gt;

&lt;p&gt;Anyway, let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t panic
&lt;/h2&gt;

&lt;p&gt;One of my favourite books is The Hitchhiker’s Guide to the Galaxy. It’s about the earth being blown up to make way for a hyperspace highway and our main character, Arthur Dent proceeds to hitchhike around space with his alien guide, Ford Prefect.&lt;/p&gt;

&lt;p&gt;I know, that’s a proper rubbish synopsis, but you all didn’t come here to read me chatting about this book.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;actual&lt;/em&gt; Hitchhiker’s Guide to the Galaxy is a sort of interactive encyclopaedia—well, interactive by 1979 standards...&lt;/p&gt;

&lt;p&gt;The thing that has always resonated with me about the encyclopaedia is on the cover it says: “Don’t Panic”. The phrase is used &lt;em&gt;so many times&lt;/em&gt; throughout the story, even when the context very much calls for panic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VAB2AqfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.016_v2d0lc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VAB2AqfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.016_v2d0lc.png" alt="Don’t panic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I find myself really resonating with Ford Prefect, guiding Arthur Dent—a bumbling brit through the understandably mind-boggling adventure in space. Ford always approaches challenges in a calm, pragmatic way, just like the guide tells him to: “Don’t Panic”, and I think that’s a takeaway for us too.&lt;/p&gt;

&lt;p&gt;In fact, when Arthur first gets the book handed to him, he says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I like the cover...‘Don’t Panic’. It’s the first helpful or intelligible thing any-body’s said to me all day.“&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Right, anyway, I digress…“don’t panic”. It’s such good advice because when we panic, we make silly mistakes. Think about it: how many horrendous CSS hacks have you made when you’re up against-it in a project and you just needed to get it done.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;lot&lt;/em&gt; of people do it and it’s because we’re panicking. The deadline is looming and there’s no time to work out why our CSS is borked, so we throw &lt;code&gt;!important&lt;/code&gt; at it until it’s fixed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C8l_QY5h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.019_ohpnnj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C8l_QY5h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.019_ohpnnj.png" alt="A Wonga advert with 3 old people puppets, sat next to each other"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is fine: we all do it, but what isn’t fine is technical debt. Often panic goes beyond a little hack here-and-there and escalates into something much more serious, like employing a CSS-in-JS framework, which is the equivalent of taking out a Wonga loan to pay of your house mortgage.&lt;/p&gt;

&lt;p&gt;Incredibly high interest technical debt, which frustratingly, the developers who took it out, only pay a bit off, because that developer has probably already gone and got a new job. It’s mainly the user who takes the biggest hit, in terms of performance, and this boggles my mind when you consider what we have available to us with modern CSS.&lt;/p&gt;

&lt;h3&gt;
  
  
  The current state of CSS
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bEi9xOsM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.022_rvyrqd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bEi9xOsM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.022_rvyrqd.png" alt="A bar chart shows 'display: block' has 100%, 'display: flex' has 98.8% and 'display: grid' has 93%"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Really, we’ve never had it better with CSS. We have CSS Grid with 93% support and Flexbox with 98.8% support. Approach using them with a safe progressive enhancement mindset and your layout is &lt;strong&gt;sorted&lt;/strong&gt;. Job done. No worries.&lt;/p&gt;

&lt;p&gt;We also get CSS Custom Properties which are native CSS variables. They’re incredibly handy for tokenising our CSS. Because they are also affected by the cascade, we can can override them, contextually. This makes them useful for theming, algorithms and display modes, such as dark mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:root { --primary: #8e8e8e;}.box { background: var(--primary);}.badge { color: var(--primary);}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;These are just a subset of powerful new features, but you can see how modern CSS is an incredibly powerful, effective styling tool. But it can come up a bit short, especially when you do have lots of CSS. So let's look at how we can deal with that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sass for the win!
&lt;/h3&gt;

&lt;p&gt;All of this native functionality is cool as heck, right? Let’s not forget native nesting too, but who does all of the work when we use that? Yep: &lt;strong&gt;the browser&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;In most cases, that’s fine, although the thought of native CSS terrifies me—especially when we are already kludging up the browser with heavy JavaScript frameworks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PVI79ZwY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.028_vvbjqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PVI79ZwY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.028_vvbjqp.png" alt="Some CSS code with nesting. A scream emoji is on the right of the screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basically, what I’m saying is we don’t have to abandon Sass because native language features are coming. It’s probably better to cautiously pre-compile your CSS and not force the browser to work as hard. It’s already working hard enough, re-rendering the DOM every time one piece of data changes (&lt;em&gt;cough&lt;/em&gt; reactive frameworks &lt;em&gt;cough&lt;/em&gt;), so why make it work harder just so you can have native nesting? It smells like developer experience over user experience to me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h_PGJJsp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.030_grv3om.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h_PGJJsp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.030_grv3om.png" alt="Some sheep, looking at the camera"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We rush to throw stuff in the bin without thinking about the wider implications. Yeh, we’ll get nesting soon, but how is a low-powered device going to handle 5 levels of nesting with chained selectors? How is a low-powered device going to handle calculating the colour of a Custom Property that has been overridden by the cascade 5 times? It doesn't matter how good the native tools are because if we keep throwing rubbish code at browsers, the users will suffer for it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e0GI74j9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.031_pnmdjf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e0GI74j9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.031_pnmdjf.png" alt="A Motorola Moto C Plus handset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The beauty of Sass is that you can have the best of both worlds. You get cool stuff like nesting, but if you do it right, you can get nice, flat selectors. You also get components and if you want, you can set your project up to get multiple bundles. You can also lint your CSS at build time, so you know when stuff is getting out of hand, right in your terminal or GUI.&lt;/p&gt;

&lt;p&gt;The most important thing is that with Sass—well, SCSS, you’re writing CSS still. SCSS is smart enough to just do what it needs to focus on and leave the rest of your CSS alone. To me, it feels like a pretty perfect setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xqpG1G_h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.032_bdd6zl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xqpG1G_h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.032_bdd6zl.png" alt="A word cloud containing: tree-shaking, linting, variables, componenents, portability, DX. The words are wrapped around the Sass logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Communicate
&lt;/h2&gt;

&lt;p&gt;We seem to be in an era where tools and methodologies are dreamed up to help avoid communicating with each other.&lt;/p&gt;

&lt;p&gt;Generated CSS class names is a classic example of this. It’s a very typical problem. Some might at this point start having an existential crisis, or dream of machine-generated classnames, but check this out: we’re going to try this novel thing called talking:&lt;/p&gt;

&lt;h3&gt;
  
  
  Dev #1 - Lucrecia
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;“This component I came up with already exists. Let me have a quick look in git and see who created it. Ah, it was Isabella”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Lucrecia to Dev #2, Isabella
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hey, Dev Isabella, is there a reason why this component is called 'block'?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Isabella to Lucrecia
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;“Ah yeh, this very important reason. How about you call that component 'box' instead?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now this important reason could be anything you dream up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A stakeholder decision&lt;/li&gt;
&lt;li&gt;A legacy codebase issue&lt;/li&gt;
&lt;li&gt;A Design decision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Importantly, Isabella, a professional, who knows how to communicate effectively, comes up with an alternative.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lucrecia
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;“That’s a great idea. Thanks!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How wholesome was that?? It’s amazing what happens when we &lt;strong&gt;actually talk to each other&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C_HTapM8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.041_gspzgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C_HTapM8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.041_gspzgv.png" alt="The phrase 'soft skills' is crossed out with 'core skills' under it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So-called “soft skills” which I prefer to call &lt;strong&gt;core skills&lt;/strong&gt; are shunned in favour of being able to build your own linked-list or do fizz buzz on a whiteboard. This winds me up because to be an effective member of a team, &lt;em&gt;you have to be able to communicate&lt;/em&gt;, whereas the only time you ever do fizz buzz in the real world is during that life-draining interview process…&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation is everything
&lt;/h3&gt;

&lt;p&gt;Another incredible way to communicate that’s not actual talking is writing. I &lt;em&gt;love&lt;/em&gt; writing and you probably noticed, I do a lot of it… In fact, I write almost everything down because I never know when I might need it. It also helps me to commit stuff to memory.&lt;/p&gt;

&lt;p&gt;There’s a real value in writing everything down—especially in a large team of front-end developers, writing CSS—or any code, really. You can document your thought-process and explain how and why you’ve done things. You can write documentation, so if another developer picks up your code, they know what’s going on.&lt;/p&gt;

&lt;p&gt;By documentation, I don’t mean that you have to write reams and reams of structured docs: I’m talking goddamn comments in your code.&lt;/p&gt;

&lt;p&gt;Take this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card { background-color: #ffffff !important;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If I landed on this I would be like “What the heck is going on here?”&lt;/p&gt;

&lt;p&gt;How about this, though?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card { /* When this card is used in the legacy app, there is a collision between existing styles, so unfortunately we had to go nuclear. It’s certainly a refactor target. */ background-color: #ffffff !important;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now if I landed on this, I would be more like: “Huh, fair enough. I’ve got a spare bit of time: maybe I should see if I can work out the specificity issue”.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good written communication can prevent unnecessary collisions between people, which can in turn, prevent expensive technical debt created by silly tools&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A win-win in my books!&lt;/p&gt;

&lt;p&gt;Right, enough of me yammering on about how to be functioning adults for a minute, because I’m this far into this piece and I’ve not talked about how to write CSS yet. Let’s do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consistency
&lt;/h2&gt;

&lt;p&gt;I think consistency is key to scaling CSS (sorry I said scale again). Really, this is what these over-abstractions are trying to give you, in my opinion, they just go way too far.&lt;/p&gt;

&lt;p&gt;I use a methodology that is sort of a devolution of BEM—a simplified version. I call it &lt;strong&gt;C-BEUT&lt;/strong&gt; , which stands for &lt;strong&gt;Cascade&lt;/strong&gt; , &lt;strong&gt;Block&lt;/strong&gt; , &lt;strong&gt;Element&lt;/strong&gt; , &lt;strong&gt;Utility&lt;/strong&gt; and &lt;strong&gt;Token&lt;/strong&gt;. It’s a proper rubbish name, I know, but it suits the rest of the awful stuff that we come up with for names, doesn’t it? I’ll explain how C-BEUT works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rUTnHtHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.049_uscvwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rUTnHtHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.049_uscvwg.png" alt="C-BEUT, as described above"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cascade
&lt;/h3&gt;

&lt;p&gt;The “C” in CSS stands for “Cascading”. Cascade is my favourite part of CSS because if you use it right, you can write very little CSS and get really good results in return. With this methodology, cascade is the first port of call. I set sensible defaults, higher level theming and typography as high up as I can. This gives us so much power.&lt;/p&gt;

&lt;p&gt;The components can then be much more skeletal and deal only with how they are different than the globals, rather than dealing with everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Block
&lt;/h3&gt;

&lt;p&gt;This is your component, your card or your button. It’s the building block of your user interface. And that's about it really—a construct and nothing else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--acdIzweA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.055_yykqm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--acdIzweA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.055_yykqm7.png" alt="A card component with a '.card' label"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Element
&lt;/h3&gt;

&lt;p&gt;This is something that is a dependent of your block—a child element. It always lives in its parent block. A good example of this is within your card, you might have a &lt;code&gt;card__image&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K_-tmZnZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.056_ialkry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K_-tmZnZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.056_ialkry.png" alt="A card component with two elements, '.card __image' and '.card__ body' labeled"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I try to keep the elemental classes as light as possible and use CSS algorithms to distribute content, rather than diving even deeper.&lt;/p&gt;

&lt;p&gt;Again, this keeps our component files light and skeletal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QzVd9hl7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.057_pmmipt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QzVd9hl7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.057_pmmipt.png" alt="A zoomed in view of the card shows that space is distributed equally using a lobotomised owl selector"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Utility
&lt;/h2&gt;

&lt;p&gt;This is a class that does one job and does it well—like a plumber or a tin opener. An example of a utility class is a one that centers text or applies some top margin. Simple, low-fidelity tools.&lt;/p&gt;

&lt;p&gt;Importantly, it means you can write common CSS and apply it where you need it, rather than repeating yourself over-and-over again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4L-8nqeR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.058_js2tem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4L-8nqeR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.058_js2tem.png" alt="The heading of the card component has an arrow, showing it has a '.weight-bold' utility"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Token
&lt;/h2&gt;

&lt;p&gt;This is actually a utility class, but a specific utility class that implements a design token and is often generated by a separate tool.&lt;/p&gt;

&lt;p&gt;What’s a design token? they scream: I’ll let my pal Jina explain them, because they invented them!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Design Tokens are the visual atoms of the design system – specifically, they are named entities that store visual design attributes. We use them in place of hard–coded values in order to maintain a scalable and consistent visual system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;— &lt;a href="https://twitter.com/jina"&gt;@jina&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These little classes are great for decoupling the scaffold of your UI from the design system. It enables the system to live away from the code context that you are in, which gives it great power.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BKkMg6hv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.059_eshwwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BKkMg6hv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.059_eshwwr.png" alt="The same heading of the card component has an arrow, showing it has '.font-brand' and '.text-600' tokens"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.text-600&lt;/code&gt; token is a reference to a size scale, just like &lt;a href="https://dev.to/styleguide"&gt;this one off my website&lt;/a&gt;. It uses a major-third scale which gives us that lovely curve between sizes.&lt;/p&gt;

&lt;p&gt;It’s used for everything, too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sizing text&lt;/li&gt;
&lt;li&gt;Spacing elements&lt;/li&gt;
&lt;li&gt;Adding inner padding&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;That’s it really and I won’t sit here, telling you that it’s the best way to write CSS, because it probably isn’t. What it is though is &lt;em&gt;consistent&lt;/em&gt;. Just like BEM is or ITCSS is. At the end of the day, find something that works for your team, stick to it and document the hell out of it. &lt;strong&gt;Enable people in your team to make consistent decisions without slowing them down&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One thing I will say about methodologies is that if you find yourself restricted by one: invest the time to experiment with something different. Things change, so accept and embrace that fact. It’s why I now use C-BEUT, rather than BEM. I think BEM is amazing, but I also ran into issues where my modifiers were getting out of hand, so I sat back, simplified what I was trying to achieve, and settled on using utilities and tokens instead.&lt;/p&gt;

&lt;p&gt;Always be open to change. We live in a dynamic world and work in an incredibly dynamic industry. &lt;strong&gt;If you stick to your guns too tightly, you’re probably going to end up causing more problems not just for yourself, but everyone else, in the future&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplification
&lt;/h2&gt;

&lt;p&gt;It’d be wild if I did a presentation, titled “Keeping it simple with CSS that scales” and didn’t talk about simplification, wouldn’t it?&lt;/p&gt;

&lt;p&gt;Let’s start by talking about frameworks. Do you really need one? I don’t think that you do anymore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AeAXVtSA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.068_fa06xf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AeAXVtSA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.068_fa06xf.png" alt="The Bootstrap logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://getbootstrap.com/"&gt;Bootstrap&lt;/a&gt; is an incredibly powerful framework. It came at a time when we were learning how to build responsive websites &lt;em&gt;and&lt;/em&gt; fighting relentless compatibility issues with browsers. It was a hellish time and Bootstrap, to its credit, made it all much easier. In fact, I’d go as far as saying that by accident, Bootstrap is one of the best design systems ever created.&lt;/p&gt;

&lt;p&gt;Using Bootstrap today—when we have actual native tools for layout, such as grid and flex—is like using a sledgehammer to crack an egg. It can also bring complications of its own, too. Because of the way it is built, it uses very global selectors to aggressively set styles. This results in stuff like this again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card { background-color: #ffffff !important;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The same goes for most CSS frameworks to be honest. An example that gives me a heart attack is &lt;a href="https://tailwindcss.com/"&gt;Tailwind CSS&lt;/a&gt; generates over &lt;strong&gt;40 thousand lines of CSS by default&lt;/strong&gt; (&lt;a href="https://unpkg.com/tailwindcss@1.1.2/dist/tailwind.css"&gt;source&lt;/a&gt;). Bonkers.&lt;/p&gt;

&lt;p&gt;If you have a solid methodology like BEM, ITSCSS, SMACSS or even C-BEUT, you could sprinkle a bit of a grid system with, y'know GRID, add some layout helpers with flex and you are golden.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mhrvK7wT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.074_siyprj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mhrvK7wT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.074_siyprj.png" alt="The Every Layout logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the approach that we took with &lt;a href="https://every-layout.dev"&gt;Every Layout&lt;/a&gt;—a book that I co-authored with my good pal, Heydon Pickering.&lt;/p&gt;

&lt;p&gt;For our layouts, we find the most robust solution by simplifying and distilling our problem. We then hint the browser, using axioms and rudiments, rather than micro-manage it to allow it to call the shots. This results in a very solid layout system that works upwards with progressive enhancement at the forefront.&lt;/p&gt;

&lt;p&gt;It’s been a really cool project and resonated with a lot of people, so go ahead and &lt;a href="https://every-layout.dev"&gt;check it out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the subject of progressive enhancement, gather around and take a knee for a moment, everyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t dismiss modern CSS because you have to support IE11&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It’s a ridiculous mindset and it pisses me off whenever someone shares a cool trick on Twitter and a Chad will pop into the comments with “WhAt aboUt IE 11 tHOuGh”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6UUid379--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.081_allu7h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6UUid379--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.081_allu7h.png" alt="Hipster, probably called Turd Buckman, says “WhAt aboUt IE 11 tHOuGh”"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stop trying to pixel push your designs and instead, use progressive enhancement to create a sensible default that automatically improves where support is available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vBKE3m_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.082_kxkt6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vBKE3m_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.082_kxkt6a.png" alt="A three column, two row grid of grey boxes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take this example: we’ve got a good ol’ three column grid. In times gone by, we’d employ some hacks not just to lay it out, but also make it look like this in every browser.&lt;/p&gt;

&lt;p&gt;What I propose is that we take a step back, &lt;strong&gt;simplify the problem&lt;/strong&gt; , and find a sensible baseline, and here it is: Good ol’ stacking with space. We can achieve 100% coverage with tiny amounts of CSS now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dxxjaIeb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.083_xbazps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dxxjaIeb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.083_xbazps.png" alt="A vertical stack of 4 grey boxes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a &lt;a href="https://dev.to/wrote/create-a-responsive-grid-layout-with-no-media-queries-using-css-grid/"&gt;handy little grid system&lt;/a&gt; that uses minmax to distribute columns. It means we get a responsive grid with &lt;strong&gt;no media queries&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.auto-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); grid-gap: 1rem;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But, grid still isn’t quite full supported, but thanks to CSS’s nature, it’ll ignore stuff it doesn’t understand and move on, so we can add this below our grid code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.auto-grid &amp;gt; * { max-width: 25rem; margin-left: auto; margin-right: auto;}.auto-grid &amp;gt; * + * { margin-top: 1rem;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, thanks to &lt;code&gt;@supports&lt;/code&gt;, we can reset some of that where there is support. If a browser supports grid, it supports &lt;code&gt;@supports&lt;/code&gt;, so &lt;strong&gt;job done&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's 22 lines of CSS, with no hacks and works all the way back to IE9 (and probably beyond).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yj1WHESg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.088_nw7okb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yj1WHESg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/andybelldesign/image/upload/c_scale%2Cf_auto%2Cw_1400/v1568725444/keeping-it-simple-with-css-that-scales/presentation.088_nw7okb.png" alt="A vertical stack of 4 grey boxes in IE9"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See the Pen &lt;a href="https://codepen.io/hankchizljaw/pen/xxKdvwy/"&gt;Progressively enhanced, media query-free grid&lt;/a&gt; by Andy Bell (&lt;a href="https://codepen.io/andybelldesign"&gt;@andybelldesign&lt;/a&gt;) on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slow down
&lt;/h3&gt;

&lt;p&gt;The last point on simplification and really, the last point of this presentation before I wrap up is “slow down”.&lt;/p&gt;

&lt;p&gt;Seriously, &lt;strong&gt;slow down&lt;/strong&gt;. I know it’s hard when you are working sprint-to-sprint or on a massive project, but trust me, when shit hits the fan, just slow down.&lt;/p&gt;

&lt;p&gt;I came a cropper to this earlier in the year. I was working on a massive system/pattern library and we were hit with some early complications. What I should have done was stop, stepped back and put some critical thinking in place. But what I did instead was plough on through each sprint, each retro and each planning session until it got to the point where not slowing down had massive negative implications. I was cashing tech debt like I was earning air miles on it.&lt;/p&gt;

&lt;p&gt;We had two or three grid systems, some fluid type and some utility driven type that conflicted &lt;strong&gt;and&lt;/strong&gt; a card component that was pretty much a website in itself. If I had slowed down and stepped back, I could have seen these problems, but I didn’t. So seriously, slow down and you will save so much time.&lt;/p&gt;

&lt;p&gt;I’ll leave you with this take-home advice: &lt;strong&gt;instead of moving fast and breaking things, move slowly and deliberately instead&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;You can watch me deliver this talk at &lt;a href="https://www.youtube.com/watch?v=byAaV3sy5qc&amp;amp;t"&gt;State of the Browser 2019, here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can see the &lt;a href="https://noti.st/hankchizljaw/D6LsJD/keeping-it-simple-with-css-that-scales"&gt;slide deck from that presentation, here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>Create a user controlled dark or light mode</title>
      <dc:creator>Andy Bell</dc:creator>
      <pubDate>Fri, 31 May 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/hankchizljaw/create-a-user-controlled-dark-or-light-mode-4p1m</link>
      <guid>https://dev.to/hankchizljaw/create-a-user-controlled-dark-or-light-mode-4p1m</guid>
      <description>&lt;p&gt;Ever since the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme"&gt;prefers-color-scheme media query landed&lt;/a&gt;, folks have been rolling out dark themes for their websites as often as they use the entire React library to power a hamburger menu on their static blog.&lt;/p&gt;

&lt;p&gt;A lot of the time, folks rightly add a dark/light switch to give the user a choice. Oftentimes, though, folks will do one of the most dangerous things in design: make a presumption and roll out a dark theme if the user’s operating system preference is dark mode, and just leave it at that.&lt;/p&gt;

&lt;p&gt;It’s important to not make presumptions in design if you can help it, so I’m going to show you a quick and easy way to honour the user’s operating system preference by default, but also give them a toggle button to change their preference, manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we are building
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/andybelldesign/video/upload/v1559290559/misc/dark-light-mode-demo_cbfd3f.mp4"&gt;Watch video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The video shows that because my operating system is in dark mode, the demo honours it by default. I then use the toggle to switch the theme. This is then maintained by local storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laying the foundations
&lt;/h3&gt;

&lt;p&gt;&lt;small&gt;&lt;em&gt;You can skip this section completely and &lt;a href="https://codepen.io/andybelldesign/pen/654b3b67255eb4a8d5860938685e4d1f"&gt;fork the base code on CodePen&lt;/a&gt;. If not, follow along to add the following base code.&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;You’re going to need a HTML file, a CSS file and a JavaScript file. I’ve built this in &lt;a href="https://codepen.io"&gt;Codepen&lt;/a&gt; to make things easier for us all.&lt;/p&gt;

&lt;p&gt;In your HTML file (or HTML panel in CodePen), add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;main&amp;gt; &amp;lt;article&amp;gt; &amp;lt;h1&amp;gt;Dark mode should be a user preference—not presumed&amp;lt;/h1&amp;gt; &amp;lt;p&amp;gt; Yes, by default, when a user has &amp;lt;code&amp;gt;@media (prefers-color-scheme: dark)&amp;lt;/code&amp;gt; set, we should set a dark theme, but we should also provide a switch for if the dark them isn’t working out for them. &amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;This also benefits users that don’t have &amp;lt;code&amp;gt;@media (prefers-color-scheme: dark)&amp;lt;/code&amp;gt; set because they get a toggle to choose, too.&amp;lt;/p&amp;gt; &amp;lt;/article&amp;gt; &amp;lt;div class="user-toggle"&amp;gt; &amp;lt;div role="status" class="[visually-hidden][js-mode-status]"&amp;gt;&amp;lt;/div&amp;gt; &amp;lt;button class="[toggle-button] [js-mode-toggle]"&amp;gt; &amp;lt;span class="[toggle-button__text] [js-mode-toggle-text]"&amp;gt;Enable dark mode&amp;lt;/span&amp;gt; &amp;lt;span class="toggle-button__icon" aria-hidden="true"&amp;gt;&amp;lt;/span&amp;gt; &amp;lt;/button&amp;gt; &amp;lt;/div&amp;gt;&amp;lt;/main&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That’s all of the HTML that we need and the &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; element only serves as a demo. Everything that lives in &lt;code&gt;.user-toggle&lt;/code&gt; is the important part.&lt;/p&gt;

&lt;p&gt;Next up, let’s add some CSS. We’ll add our core presentational styles first. Paste this into your CSS file (or CSS panel on CodePen):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Presentational demo styles */body { font-family: sans-serif; padding: 2rem 1rem; line-height: 1.4; display: grid; place-items: center;}article { max-width: 75ch; margin: 0 auto;}article &amp;gt; * + * { margin-top: 1em;}h1 { font-size: 2.5rem; line-height: 1.1;}p { font-size: 1.2rem; opacity: 0.9;}code { font-weight: 700; font-size: 1.3em; white-space: pre;}.visually-hidden { display: block; height: 1px; width: 1px; overflow: hidden; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px); clip-path: inset(1px); white-space: nowrap; position: absolute;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Cool—we’ve got our base HTML and CSS in place. You might also want to add this &lt;a href="https://codepen.io/andybelldesign/pen/Ygmwym.css"&gt;reset&lt;/a&gt; that I use for my demos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/--*"&gt;CSS Custom Properties&lt;/a&gt; are doing the heavy lifting for us, so next, let’s define some at the &lt;code&gt;:root&lt;/code&gt; level, which is on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:root { --color-mode: 'light'; --color-dark: #141414; --color-dark-alpha: rgba(0, 0, 0, 0.1); --color-light: #efefef; --color-light-alpha: rgba(255, 255, 255, 0.9); --icon-sun: url('data:image/svg+xml,\ &amp;lt;svg version="1.1" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24"&amp;gt;\ &amp;lt;path d="M18 12c0-0.811-0.161-1.587-0.455-2.295-0.304-0.735-0.75-1.395-1.303-1.948-0.552-0.552-1.213-0.998-1.948-1.303-0.707-0.293-1.483-0.454-2.294-0.454s-1.587 0.161-2.295 0.455c-0.735 0.304-1.395 0.75-1.948 1.302s-0.998 1.213-1.302 1.948c-0.294 0.708-0.455 1.484-0.455 2.295s0.161 1.587 0.455 2.295c0.304 0.735 0.75 1.395 1.303 1.948 0.552 0.552 1.213 0.998 1.948 1.303 0.707 0.293 1.483 0.454 2.294 0.454s1.587-0.161 2.295-0.455c0.735-0.304 1.395-0.75 1.948-1.303s0.998-1.213 1.303-1.948c0.293-0.707 0.454-1.483 0.454-2.294zM16 12c0 0.544-0.108 1.060-0.303 1.529-0.202 0.489-0.5 0.929-0.869 1.299s-0.81 0.667-1.299 0.869c-0.469 0.195-0.985 0.303-1.529 0.303s-1.060-0.108-1.529-0.303c-0.489-0.202-0.929-0.5-1.299-0.869s-0.667-0.81-0.869-1.299c-0.195-0.469-0.303-0.985-0.303-1.529s0.108-1.060 0.303-1.529c0.202-0.489 0.5-0.929 0.869-1.299s0.81-0.667 1.299-0.869c0.469-0.195 0.985-0.303 1.529-0.303s1.060 0.108 1.529 0.303c0.489 0.202 0.929 0.5 1.299 0.869s0.667 0.81 0.869 1.299c0.195 0.469 0.303 0.985 0.303 1.529zM11 1v2c0 0.552 0.448 1 1 1s1-0.448 1-1v-2c0-0.552-0.448-1-1-1s-1 0.448-1 1zM11 21v2c0 0.552 0.448 1 1 1s1-0.448 1-1v-2c0-0.552-0.448-1-1-1s-1 0.448-1 1zM3.513 4.927l1.42 1.42c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-1.42-1.42c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414zM17.653 19.067l1.42 1.42c0.391 0.391 1.024 0.391 1.414 0s0.391-1.024 0-1.414l-1.42-1.42c-0.391-0.391-1.024-0.391-1.414 0s-0.391 1.024 0 1.414zM1 13h2c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2c-0.552 0-1 0.448-1 1s0.448 1 1 1zM21 13h2c0.552 0 1-0.448 1-1s-0.448-1-1-1h-2c-0.552 0-1 0.448-1 1s0.448 1 1 1zM4.927 20.487l1.42-1.42c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-1.42 1.42c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0zM19.067 6.347l1.42-1.42c0.391-0.391 0.391-1.024 0-1.414s-1.024-0.391-1.414 0l-1.42 1.42c-0.391 0.391-0.391 1.024 0 1.414s1.024 0.391 1.414 0z"&amp;gt;&amp;lt;/path&amp;gt;\ &amp;lt;/svg&amp;gt;'); --icon-sun-filter: invert(0.61) sepia(0.8) saturate(5) hue-rotate(0deg) brightness(0.92); --icon-moon: url('data:image/svg+xml,\ &amp;lt;svg version="1.1" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24"&amp;gt;\ &amp;lt;path d="M21.996 12.882c0.022-0.233-0.038-0.476-0.188-0.681-0.325-0.446-0.951-0.544-1.397-0.219-0.95 0.693-2.059 1.086-3.188 1.162-0.696 0.047-1.399-0.027-2.077-0.226-0.656-0.192-1.29-0.501-1.874-0.932-0.655-0.484-1.181-1.074-1.575-1.729-0.409-0.68-0.676-1.432-0.792-2.206s-0.082-1.571 0.11-2.342c0.184-0.741 0.514-1.46 0.999-2.115 0.142-0.191 0.216-0.435 0.191-0.691-0.053-0.55-0.542-0.952-1.092-0.898-1.117 0.109-2.186 0.399-3.172 0.843-1.005 0.452-1.925 1.065-2.723 1.808-0.883 0.82-1.618 1.801-2.159 2.901-0.523 1.064-0.863 2.238-0.978 3.485-0.125 1.347 0.024 2.658 0.402 3.878 0.392 1.266 1.031 2.431 1.863 3.433s1.86 1.843 3.033 2.461c1.13 0.595 2.392 0.982 3.739 1.106s2.659-0.025 3.878-0.403c1.266-0.392 2.431-1.031 3.433-1.863s1.843-1.86 2.461-3.033c0.595-1.13 0.982-2.392 1.106-3.739zM19.567 14.674c-0.126 0.351-0.276 0.689-0.447 1.014-0.493 0.937-1.166 1.76-1.969 2.427s-1.735 1.178-2.747 1.491c-0.973 0.302-2.021 0.421-3.102 0.321s-2.089-0.41-2.99-0.884c-0.937-0.493-1.76-1.166-2.427-1.969s-1.178-1.735-1.491-2.747c-0.302-0.973-0.421-2.021-0.321-3.102 0.092-1 0.365-1.938 0.782-2.786 0.43-0.878 1.018-1.661 1.725-2.319 0.64-0.595 1.377-1.086 2.183-1.449 0.179-0.081 0.362-0.155 0.548-0.223-0.092 0.257-0.171 0.516-0.236 0.778-0.256 1.029-0.302 2.091-0.147 3.121s0.51 2.032 1.056 2.941c0.527 0.875 1.23 1.663 2.1 2.306 0.775 0.573 1.622 0.986 2.5 1.243 0.907 0.266 1.846 0.364 2.772 0.302 0.752-0.050 1.496-0.207 2.21-0.465z"&amp;gt;&amp;lt;/path&amp;gt;\ &amp;lt;/svg&amp;gt;'); --icon-moon-filter: invert(0.75); --background: #efefef; --text-color: #141414; --button-icon: var(--icon-moon); --button-icon-filter: var(--icon-moon-filter); --button-background: var(--color-dark); --button-color: var(--color-light); --border-color: var(--color-dark-alpha);}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There’s a big chunk in there, so let’s break it down a bit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We define the &lt;code&gt;--color-mode&lt;/code&gt; variable and set it to &lt;code&gt;'light'&lt;/code&gt; by default. This is used to communicate to the JavaScript what the user’s preference is&lt;/li&gt;
&lt;li&gt;We’re defining some SVG icons in CSS (I know, cool, right?). I probably wouldn’t do this on a production site, but it’s a pretty cool trick, and ever since &lt;a href="https://twitter.com/Una/status/1129401554732277760"&gt;I saw on Twitter&lt;/a&gt; that &lt;a href="https://twitter.com/leaverou"&gt;Lea Verou&lt;/a&gt; was demoing this technique in her talk, I really wanted to have a go&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest is pretty self explanatory theme colours and the default application of the light theme.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dealing with the &lt;code&gt;prefers-color-scheme&lt;/code&gt; media query
&lt;/h3&gt;

&lt;p&gt;We’ve got all of our base code in place now, so let’s deal with the user’s preference for &lt;code&gt;prefers-color-scheme&lt;/code&gt;. We’re also going to deal with the JavaScript controlled preference, too, while we’re at it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body { background: var(--background); color: var(--text-color); transition: background 500ms ease-in-out, color 200ms ease;}@media (prefers-color-scheme: dark) { :root { --color-mode: 'dark'; } :root:not([data-user-color-scheme]) { --background: var(--color-dark); --text-color: var(--color-light); --button-icon: var(--icon-sun); --button-icon-filter: var(--icon-sun-filter); --button-background: var(--color-light); --button-color: var(--color-dark); --border-color: var(--color-light-alpha); }}[data-user-color-scheme='dark'] { --background: var(--color-dark); --text-color: var(--color-light); --button-icon: var(--icon-sun); --button-icon-filter: var(--icon-sun-filter); --button-background: var(--color-light-alpha); --button-color: var(--color-dark); --border-color: var(--color-light-alpha);}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s cover some key bits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the user prefers dark mode, inside of the media query we’re making the relevant theme changes&lt;/li&gt;
&lt;li&gt;In that same media query, we’re also setting the &lt;code&gt;--color-mode&lt;/code&gt;, which JavaScript can hook on to&lt;/li&gt;
&lt;li&gt;Notice how the CSS is applied if the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; (&lt;code&gt;:root&lt;/code&gt;) element doesn’t have a &lt;code&gt;data-user-color-scheme&lt;/code&gt; attribute. This is to prevent the default overriding the user preference&lt;/li&gt;
&lt;li&gt;Under the media query, we’re using this attribute selector to look for a &lt;code&gt;data-user-color-scheme&lt;/code&gt; attribute with the value of &lt;code&gt;dark&lt;/code&gt;. We set this with JavaScript later in this tutorial, but notice how this does the same thing as the media query. This could be refactored with a Sass mixin, but for this tutorial, we’ll wear the mild repetition&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding the toggle styles
&lt;/h3&gt;

&lt;p&gt;The last bit of CSS is making the toggle button look cool. We interchange a sun and moon icon, as well as colouring it in the inverse of the current theme.&lt;/p&gt;

&lt;p&gt;Add this CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.no-js .user-toggle { display: none;}.user-toggle { margin: 2rem auto 0 auto; padding-top: 2.5rem; max-width: 20rem; border-top: 1px solid var(--border-color); text-align: center;}.toggle-button { display: inline-flex; background: var(--button-background); color: var(--button-color); border: none; font: inherit; font-size: 1.5rem; padding: 0.5rem 1rem; transition: background 500ms ease-in-out, color 200ms ease;}.toggle-button__icon { background: var(--button-icon); width: 1.2em; height: 1.2em; margin: 0 0 0 0.5em; filter: var(--button-icon-filter); transform: translateY(1px); /* Optical adjustment */ transition: filter 500ms ease-in-out;}.toggle-button:focus { outline: 1px solid var(--button-background); outline-offset: 0.5rem;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It’s all mostly presentational CSS, but there’s a couple of bits I need to explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By default, because the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element has a class of &lt;code&gt;no-js&lt;/code&gt;, we hide the &lt;code&gt;.user-toggle&lt;/code&gt; element, because everything in it requires JavaScript. This means that if a user has no JavaScript available, they’ll still get dark mode if that’s their system preference—they just won’t be able to change it&lt;/li&gt;
&lt;li&gt;Because we’re using CSS to render icons, we’re going to use &lt;code&gt;filter&lt;/code&gt; to colour them. Check out &lt;a href="https://css-tricks.com/the-many-ways-to-change-an-svg-fill-on-hover-and-when-to-use-them/"&gt;this handy explainer article&lt;/a&gt; for how that works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we’ve added all of the CSS, let’s do the JavaScript bit!&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding the interaction
&lt;/h3&gt;

&lt;p&gt;We’ve got our &lt;a href="https://andy-bell.design/wrote/the-power-of-progressive-enhancement/"&gt;minimum viable experience&lt;/a&gt; working, so let’s wire up some JavaScript to enhance it and give the user more control.&lt;/p&gt;

&lt;p&gt;Add the following to your JavaScript file (or JS panel in CodePen):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.documentElement.classList.remove('no-js');
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We’re removing the &lt;code&gt;no-js&lt;/code&gt; class from the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element because we have JavaScript available. You’ll have probably noticed that the user toggle control has suddenly appeared.&lt;/p&gt;

&lt;p&gt;Let’s set up some constants. Add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const STORAGE_KEY = 'user-color-scheme';const COLOR_MODE_KEY = '--color-mode';const modeToggleButton = document.querySelector('.js-mode-toggle');const modeToggleText = document.querySelector('.js-mode-toggle-text');const modeStatusElement = document.querySelector('.js-mode-status');
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The two shouty constants are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;STORAGE_KEY&lt;/code&gt; is what we use to store the user’s preference in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage"&gt;localStorage&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COLOR_MODE_KEY&lt;/code&gt; is what we use to extract the current CSS Custom Property value, &lt;code&gt;--color-mode&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest of this section is us grabbing the relevant HTML elements for later.&lt;/p&gt;

&lt;p&gt;Next up, let’s add a function to extract the &lt;code&gt;--color-mode&lt;/code&gt; value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getCSSCustomProp = propKey =&amp;gt; { let response = getComputedStyle(document.documentElement).getPropertyValue(propKey); if (response.length) { response = response.replace(/\"/g, '').trim(); } return response;};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is a condensed version of the function we use in &lt;a href="https://andy-bell.design/wrote/get-css-custom-property-value-with-javascript/"&gt;this tutorial&lt;/a&gt;, which is worth reading if you’re interesting in how this function works. The end result in this tutorial is a string of either &lt;code&gt;'light'&lt;/code&gt; or &lt;code&gt;'dark'&lt;/code&gt;, depending on the media query situation.&lt;/p&gt;

&lt;p&gt;Next, let’s add a function that applies the user preference that’s either set in local storage or passed in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const applySetting = passedSetting =&amp;gt; { let currentSetting = passedSetting || localStorage.getItem(STORAGE_KEY); if (currentSetting) { document.documentElement.setAttribute('data-user-color-scheme', currentSetting); setButtonLabelAndStatus(currentSetting); } else { setButtonLabelAndStatus(getCSSCustomProp(COLOR_MODE_KEY)); }};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function has one job: it tries to load a setting that’s either passed in or from local storage as a fallback—then, depending wether a setting was loaded or not, the function applies the &lt;code&gt;data-user-color-scheme&lt;/code&gt; attribute if necessary. It then updates the button label and the status text with another function, which we’ll add now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const setButtonLabelAndStatus = currentSetting =&amp;gt; { modeToggleText.innerText = `Enable ${currentSetting === 'dark' ? 'light' : 'dark'} mode`; modeStatusElement.innerText = `Color mode is now "${currentSetting}"`;};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, we set the text depending on what the current colour mode is. Because we’ll have a &lt;code&gt;'dark'&lt;/code&gt; or &lt;code&gt;'light'&lt;/code&gt; value, either from local storage &lt;em&gt;or&lt;/em&gt; the CSS property, we can safely set the button to be the inverse, and the status to announce what the colour mode currently is.&lt;/p&gt;

&lt;p&gt;Next, let’s add the code that toggles the colour mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const toggleSetting = () =&amp;gt; { let currentSetting = localStorage.getItem(STORAGE_KEY); switch (currentSetting) { case null: currentSetting = getCSSCustomProp(COLOR_MODE_KEY) === 'dark' ? 'light' : 'dark'; break; case 'light': currentSetting = 'dark'; break; case 'dark': currentSetting = 'light'; break; } localStorage.setItem(STORAGE_KEY, currentSetting); return currentSetting;};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first thing that this function does is try to load the current setting from local storage. It then runs what it got through a switch. If the setting is found, we invert it. If not, we load from CSS, then invert that instead.&lt;/p&gt;

&lt;p&gt;The last thing this function does is return the setting that it calculated.&lt;/p&gt;

&lt;p&gt;The last thing we do in this tutorial is add an event to the button, then apply the setting by default, and then we are done!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;modeToggleButton.addEventListener('click', evt =&amp;gt; { evt.preventDefault(); applySetting(toggleSetting());});applySetting();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the click handler, we pass the value that was returned by &lt;code&gt;toggleSetting()&lt;/code&gt; straight into &lt;code&gt;applySetting()&lt;/code&gt;. Job done. We run &lt;code&gt;applySetting()&lt;/code&gt; by default to make sure that the user’s preference is applied on page load.&lt;/p&gt;

&lt;p&gt;Here’s a demo of the final, working system:&lt;/p&gt;

&lt;p&gt;See the Pen &lt;a href="https://codepen.io/hankchizljaw/pen/163767d9126b8d5559cff3990ba5f826/"&gt;PiccalilliIssue#10 — User controlled dark mode&lt;/a&gt; by Andy Bell (&lt;a href="https://codepen.io/andybelldesign"&gt;@andybelldesign&lt;/a&gt;) on &lt;a href="https://codepen.io"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;This little tutorial gets you going in the right direction, but there’s plenty of work to do to get it up to speed on your website. The most important thing that you need to do is make sure that both your light &lt;strong&gt;and&lt;/strong&gt; dark themes are fully accessible—especially in terms of colour contrast. There are many tools you can use for this. I prefer to use &lt;a href="https://khan.github.io/tota11y/"&gt;tota11y&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also improve this system further. A couple of quick ideas are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Observe changes to the user’s dark/light mode setting, probably via the &lt;code&gt;prefers-color-scheme&lt;/code&gt; media query and update the default state accordingly&lt;/li&gt;
&lt;li&gt;Refactor the CSS theming to not repeat itself as much. I personally would roll out some &lt;a href="https://sass-lang.com/"&gt;Sass&lt;/a&gt; for this situation&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>ux</category>
      <category>a11y</category>
    </item>
  </channel>
</rss>
