<?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: Max Antonucci</title>
    <description>The latest articles on DEV Community by Max Antonucci (@maxwell_dev).</description>
    <link>https://dev.to/maxwell_dev</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%2F1621%2F980063f5-2777-4be6-ba17-7377e79a6f6a.png</url>
      <title>DEV Community: Max Antonucci</title>
      <link>https://dev.to/maxwell_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxwell_dev"/>
    <language>en</language>
    <item>
      <title>What's the deal with align-items: baseline?</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Thu, 14 Oct 2021 13:15:25 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/whats-the-deal-with-align-items-baseline-5eef</link>
      <guid>https://dev.to/maxwell_dev/whats-the-deal-with-align-items-baseline-5eef</guid>
      <description>&lt;p&gt;I can't count the number of times flexbox has made an otherwise painful design layout easy. My only qualm was having to calculate margins and paddings to space elements in a flex container. But now that &lt;code&gt;gap&lt;/code&gt; has gotten good browser support, even that's no longer an issue.&lt;/p&gt;

&lt;p&gt;But while it doesn't inconvenience me anywhere, it still surprises me.&lt;/p&gt;

&lt;p&gt;Take the &lt;code&gt;align-items&lt;/code&gt; property. When you have a row of items in a flex container, it controls how they line up in that row. I know how the most common values you'd give it work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;stretch&lt;/code&gt; is the default value, and it makes each one the height of the tallest element in that row&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flex-start&lt;/code&gt; aligns each element to the top of that row&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flex-end&lt;/code&gt; aligns each element to the end of the row&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;center&lt;/code&gt; aligns each element along the row's center axis&lt;/li&gt;
&lt;/ul&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%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fflex-align-baseline%2Fflex-align-basics.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fflex-align-baseline%2Fflex-align-basics.png" alt="Some hand-drawn examples showing how the four basic values for align-items work."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But an article I read mentioned the &lt;code&gt;baseline&lt;/code&gt; value, and I didn't know that one. My own site's article listing is a flex container, so I threw on &lt;code&gt;align-items: baseline&lt;/code&gt; out of curiosity.&lt;/p&gt;

&lt;p&gt;The result...was unexpected.&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;This confused me since the results looked inconsistent. I was guessing flexbox was aligning things by a particular element. But I checked each element and nothing explained the alignment in each row. How could an alignment changed by a single rule give me such random results?&lt;/p&gt;

&lt;p&gt;I did a few google searches to find out exactly how &lt;code&gt;baseline&lt;/code&gt; aligns content. But I got explanations that were either too sparse or too jargon-filled. So like all confused people with little self-esteem and even less to lose, I turned to Twitter. And I actually got a good answer fast.&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;This was the simple answer I'd been looking for! &lt;strong&gt;Baseline takes the first element in each flex item, and lines things up by the bottom of that element.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This also explained the inconsistency! Posts in the first and third rows all have images, so it aligned the articles based on the bottoms of those. But the middle row has two posts without images, so it went by the element that was first instead: the dates. So while the alignment rule works, the different elements make it look inconsistent.&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%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fflex-align-baseline%2Fbaseline-align-guideline.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%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fflex-align-baseline%2Fbaseline-align-guideline.jpg" alt="My website's article listings with the baseline level elements emphasized to show where how the alignment works."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It also explains why the layout looks so wildly spaced in some areas. In the second post of the first row, the headline text is larger while the flex-basis is shorter. This pushes a lot of content below the baseline and creates those large gaps in the row.&lt;/p&gt;

&lt;p&gt;All this has taught me a few good lessons about when I'd want to use &lt;code&gt;align-items: baseline&lt;/code&gt; in the future.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It's good for content with some size variation.&lt;/strong&gt; If you have images or text of different sizes, &lt;code&gt;baseline&lt;/code&gt; always aligns them at the same point. So it can add some consistency where they may otherwise be none.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's bad for content that has too many differences.&lt;/strong&gt; It only looks at the first element and not any elements after it. My site has shown that having varying text or elements around a baseline can create lots of empty space.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My recommendation is to use &lt;code&gt;baseline&lt;/code&gt; when your inconsistencies stay limited to the first element. Like for a list of cards that always started with headings, but you can't guarantee their font size.&lt;/p&gt;

&lt;p&gt;As for my own site, I'm going to stick with &lt;code&gt;align-items: stretch&lt;/code&gt; for now. Between optional featured images and different excerpt lengths, there's too much empty space.&lt;/p&gt;

&lt;p&gt;But as with all things flexbox, this is good to know.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://safebooru.org/index.php?page=post&amp;amp;s=view&amp;amp;id=3651800" rel="noopener noreferrer"&gt;Featured image courtesy of this link.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>The Currying Introduction I Wish I Had</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Wed, 17 Feb 2021 14:21:09 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/the-currying-introduction-i-wish-i-had-4c20</link>
      <guid>https://dev.to/maxwell_dev/the-currying-introduction-i-wish-i-had-4c20</guid>
      <description>&lt;p&gt;Currying is one of those JavaScript words I heard many times before I understood it. That's part of why I put in the time to figure it out. The other reason is it's fun to say.&lt;/p&gt;

&lt;p&gt;But for anyone reading this who wants to understand for non-just-fun-to-say reasons, I hope you find this post useful. This is the explanation I wished I read as I was learning the basics of JavaScript.&lt;/p&gt;

&lt;p&gt;If you wanted to read about the best curry recipes for Pokemon Sword and Shield, I can't help you there. All I can say is Spicy Sausage Curry always wins and you have to accept that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Currying Solves
&lt;/h2&gt;

&lt;p&gt;Most JavaScript functions operate predictably:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Put in one or more arguments&lt;/li&gt;
&lt;li&gt;Let the function do some stuff with those values&lt;/li&gt;
&lt;li&gt;The function returns a value.&lt;/li&gt;
&lt;li&gt;ALL HAIL THE MIGHTY GLOW CLOUD.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A basic ES6 function to multiply two values would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But suppose I needed lots of multiplication operations that were not quite the same. For example, there were groups where one number is always the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// All multiply by 3&lt;/span&gt;

&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// All multiply by 5&lt;/span&gt;

&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// All multiply by 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but it’s repetitive, not too elegant, and easier to mess up (especially by folks like me). This can get unmaintainable fast as the codebase scales up.&lt;/p&gt;

&lt;p&gt;This is where currying helps. I touched on currying almost &lt;a href="https://www.maxwellantonucci.com/posts/2019/06/25/metaphorical-intro-functional-js/" rel="noopener noreferrer"&gt;two years ago when writing about functional programming&lt;/a&gt;. But want to go into more detail here.&lt;/p&gt;

&lt;h2&gt;
  
  
  So What is Currying?
&lt;/h2&gt;

&lt;p&gt;In a nutshell, currying is making a sequence of nested functions. But that wasn't clear to me at first, so here's the definition outside a nutshell.&lt;/p&gt;

&lt;p&gt;Sometimes I may need to call several functions to get what I want, one after the other. Or like the above example, write one function with the same arguments. But imagine writing those functions and arguments in the same order over and over until my mind snaps again. Nobody wants this, especially the guy who has to fix my floorboards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Currying lets me nest those functions inside each other. Then I only need to call one, and the function calls the rest in the proper order for me.&lt;/strong&gt; Time, energy, and sanity are saved.&lt;/p&gt;

&lt;p&gt;It took a while for this to click for me. If I asked the JavaScript language to explain how this would with the above examples, I imagine it'd go like this.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Conversation with JavaScript about Currying
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Coder:&lt;/strong&gt; Look at all these multiplication functions. I could you all the arguments at once, but that's repetitive here, right? Instead, can you remember some of the arguments for me? That way when I call &lt;code&gt;multiply&lt;/code&gt;, you can take the different argument.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript:&lt;/strong&gt; I would remember the number three...so it'd look like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Coder:&lt;/strong&gt; That would work...but I also want you to remember functions for the other common multipliers: five and seven.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript:&lt;/strong&gt; So write those functions out too. You'll need to give them different names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyBy3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyBy5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyBy7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Coder:&lt;/strong&gt; That’s the result I want, but rewriting that multiplication logic feels wasteful. I want to generate different versions of that function without rewriting so much.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript:&lt;/strong&gt; Hey, you’re the programmer, not me. You’re supposed to figure this stuff out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coder:&lt;/strong&gt; Hmm...&lt;em&gt;could I a function that would make the multiplying function for me?&lt;/em&gt; The first function is where I pass in the number I always want to multiply by. Does that one return the function that can multiply by this number?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript:&lt;/strong&gt; Sure, it can do that! That’ll look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyCurrier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyBy3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multiplyCurrier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// This is a function that multiplies the argument by three&lt;/span&gt;
&lt;span class="nf"&gt;multiplyBy3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3 * 5 = 15&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyBy5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multiplyCurrier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;multiplyBy5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 25&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyBy7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multiplyCurrier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;multiplyBy7&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 35&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JavaScript:&lt;/strong&gt; Don’t forget that in this language we have "first-class functions." &lt;strong&gt;You can use functions as arguments, and you can have them return other functions. Here, I'm breaking a function down into a sequence of functions that each takes one argument.&lt;/strong&gt; You can pass in each argument to construct lots of different functions with less work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coder:&lt;/strong&gt; Hooray! This looks good and I'm fulfilled at long last!&lt;/p&gt;

&lt;h3&gt;
  
  
  Call Many Arguments at Once
&lt;/h3&gt;

&lt;p&gt;Currying just helped me make a bunch of multiplication functions with little repetition. I can also make more if I need to. But we can stretch currying's abilities further.&lt;/p&gt;

&lt;p&gt;The above example goes two functions deep, and I only call one at a time. But I could call that &lt;code&gt;multipleCurrier&lt;/code&gt; function with both arguments at once if I wanted to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiplyCurrier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;multiplyCurrier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets me multiply two numbers without making a new function.&lt;/p&gt;

&lt;p&gt;It also lets me get more ambitious with what kinds of functions I can make. Let's say I have a function that lets me get substrings and goes three levels deep.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;curriedSubstring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The arguments each function in this sequence takes are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The substring's starting index&lt;/li&gt;
&lt;li&gt;The substrings ending index&lt;/li&gt;
&lt;li&gt;The string to pull the substring from&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once it gets all these arguments, it returns the substring. So if I wanted to get a string's first character, I could call them all at once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;curriedSubstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;potatoes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'p'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I can also save the first two levels into a separate function, and use it on its own like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFirstChar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;curriedSubstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//  Note that I need to include "string" as an argument and pass it to "curriedSubstring"&lt;/span&gt;

&lt;span class="nf"&gt;getFirstChar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;potatoes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'p'&lt;/span&gt;
&lt;span class="nf"&gt;getFirstChar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white rice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'w'&lt;/span&gt;
&lt;span class="nf"&gt;getFirstChar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sausages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 's'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or I could stop at the first level, and make a function to get different numbers of starting characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getStartingChars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;curriedSubstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;getStartingChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;potatoes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'pot'&lt;/span&gt;
&lt;span class="nf"&gt;getStartingChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white rice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'which'&lt;/span&gt;
&lt;span class="nf"&gt;getStartingChars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sausages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'sausage'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These all show how I can tap into this sequence of functions at different points into new functions. This lets me extend the code while only writing the underlying logic and arguments once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enjoy Your Curry...ing
&lt;/h2&gt;

&lt;p&gt;I hope you found this post useful and watch for times you can break out the currying! Anytime there are many functions with shared logic or arguments, that's often a good sign. Even for things as simple as multiplication or getting substrings.&lt;/p&gt;

&lt;p&gt;Plus I'll say it again, "currying" is just fun to say. Understanding it gives us more reason to use it in conversation. I know this, you know this, the world knows this. I know I'm not the only one who learned it mainly for this reason. No one else has admitted it yet.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ahem&lt;/em&gt;, regardless, &lt;a href="https://safebooru.org/index.php?page=post&amp;amp;s=view&amp;amp;id=3090199" rel="noopener noreferrer"&gt;happy currying&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcurrying-introduction%2Fpokemon-curry.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcurrying-introduction%2Fpokemon-curry.jpeg" alt="A trainer and several pokemon gathering around a freshly-made pot of curry."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://safebooru.org/index.php?page=post&amp;amp;s=view&amp;amp;id=3159174" rel="noopener noreferrer"&gt;Featured image courtesy of this link&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Hiding and Showing in SVG with Clip-path and Mask</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Mon, 01 Feb 2021 14:18:31 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/hiding-and-showing-in-svg-with-clip-path-and-mask-3l80</link>
      <guid>https://dev.to/maxwell_dev/hiding-and-showing-in-svg-with-clip-path-and-mask-3l80</guid>
      <description>&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG"&gt;Scalable Vector Graphics&lt;/a&gt;, or SVG, are one of those front-end tools that can open up a world of creative ideas. I've been playing around with it more, for work and to distract myself from my hollow, quarantined soul. I did both and made my first component with some cutesy SVG animation.&lt;/p&gt;

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

&lt;p&gt;But near the end, I hit a snag with how SVG can hide parts of the image. Sometimes I wanted to &lt;em&gt;show&lt;/em&gt; specific parts of an image. Other times I wanted to &lt;em&gt;hide&lt;/em&gt; them. I couldn't get this effect for the sun and moon animations, so I got it with border and fill colors. That's not ideal, but I can always fix it up later.&lt;/p&gt;

&lt;p&gt;But while I wanted to figure this out, I had a hard time finding a clear explanation of showing and hiding SVG. So I wrote one myself! &lt;strong&gt;The two parts of SVG one needs for these effects are &lt;code&gt;clip-path&lt;/code&gt; and &lt;code&gt;mask&lt;/code&gt;.&lt;/strong&gt; Here I'll break down the basics of how to use them with SVG to hide shapes, images, and if you're lucky, painful tangles of repressed emotion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clip-path Controls What You See
&lt;/h2&gt;

&lt;p&gt;Let's say I have a red rectangle, but I only want to show a small circle &lt;em&gt;within&lt;/em&gt; it. That's when I need &lt;code&gt;clip-path.&lt;/code&gt; &lt;strong&gt;A &lt;code&gt;clip-path&lt;/code&gt; is an SVG shape you pair with a second. Anything in the second shape that doesn't overlap with the &lt;code&gt;clip-path&lt;/code&gt; shape gets cropped out, lost, and never seen again.&lt;/strong&gt; You destroyed it and I hope you're happy.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ahem&lt;/em&gt;...anyways, here's an example. Let's start with this red rectangle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;viewbox=&lt;/span&gt;&lt;span class="s"&gt;"-200 -100 400 200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"-200"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"-100"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add a &lt;code&gt;clip-path&lt;/code&gt; to this thing. First, I need to define the circle it'll be using. It's positioned to be in the rectangle's center. But I need to define it within a &lt;code&gt;clip-path&lt;/code&gt;. &lt;strong&gt;This has to go within a &lt;code&gt;defs&lt;/code&gt; element, which is SVG's way of storing variables.&lt;/strong&gt; Anything in &lt;code&gt;defs&lt;/code&gt; won't directly render but can then affect other elements, like repressed memories of staring wistfully at an empty street after the third hard cider.&lt;/p&gt;

&lt;p&gt;So within the &lt;code&gt;defs&lt;/code&gt; element, the &lt;code&gt;circle&lt;/code&gt; must go in a &lt;code&gt;clipPath&lt;/code&gt; element. It also needs a unique ID for reference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;clipPath&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"clip-path"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/clipPath&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this &lt;code&gt;clip-path&lt;/code&gt; circle can be used with the red rectangle. It needs the &lt;code&gt;clip-path&lt;/code&gt; attribute with the unique ID, which looks like &lt;code&gt;clip-path="url(#clip-path)"&lt;/code&gt;, and it's good to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;viewbox=&lt;/span&gt;&lt;span class="s"&gt;"-200 -100 400 200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;clipPath&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"clip-path"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/clipPath&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;clip-path=&lt;/span&gt;&lt;span class="s"&gt;"url(#clip-path)"&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"-200"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"-100"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the final result below. The light yellow area is where the rest of the rectangle is being hidden below the clip-path.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Mask Controls What You Hide
&lt;/h2&gt;

&lt;p&gt;Once I finally peeled myself off the couch and found the will to keep working despite the terror of it all, I asked, "What if I want the reverse result? If I want to hide everything &lt;em&gt;except&lt;/em&gt; that red dot?" To do that, we need a &lt;code&gt;mask&lt;/code&gt;. But this approach is a little more complex.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;clip-path&lt;/code&gt;, I only had to define a visible area. With &lt;code&gt;mask&lt;/code&gt;, there are two steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Define a visible area. Anything outside it gets cropped out.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Define what areas &lt;em&gt;within&lt;/em&gt; the visible area are also cropped out.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is like a &lt;code&gt;clip-path&lt;/code&gt; but with a lot more potential for what to show and hide, but will only realize once it can experience regular human interaction again. But I only needed these lonely basics to the desired result. If you want to see what it can do, including using shades of gray for translucent effects, check out &lt;a href="https://vanseodesign.com/web-design/svg-masking-examples-1/"&gt;this blog post of mask examples&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, defining a visible area here is easy: I want the rectangle to be visible! I'm hiding space within the rectangle, so the entire rectangle itself should be my visible area. I define this within a &lt;code&gt;mask&lt;/code&gt; element, which can also go in the &lt;code&gt;defs&lt;/code&gt; element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;mask&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mask"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"-200"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"-100"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/mask&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;fill="white"&lt;/code&gt; I added to the shape. That's important because, &lt;strong&gt;in a mask, the visible area must have a white fill color.&lt;/strong&gt; Don't you dare deprive it of what it needs. You monster.&lt;/p&gt;

&lt;p&gt;Now I need to decide what area to hide within the visible area. This is the circle in the middle of the rectangle. This time it needs &lt;code&gt;fill="black"&lt;/code&gt; to hide it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;mask&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mask"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"-200"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"-100"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/mask&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this basic mask complete, we can connect it to the red rectangle. It's done the same way as &lt;code&gt;clip-path&lt;/code&gt; but with the &lt;code&gt;mask&lt;/code&gt; attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;viewbox=&lt;/span&gt;&lt;span class="s"&gt;"-200 -100 400 200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mask&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mask"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"-200"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"-100"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/mask&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;mask=&lt;/span&gt;&lt;span class="s"&gt;"url(#mask)"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"-200"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"-100"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives me what I want: a full rectangle missing the center circle. The result is below with the light yellow again showing what's hidden behind the mask. The SVG mask anyway, not the mask of positivity hiding the sense that nothing will truly be okay again.&lt;/p&gt;

&lt;p&gt;Not that mask. The SVG mask.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Bonus Challenge
&lt;/h3&gt;

&lt;p&gt;My written example is redundant. It defines the same rectangle shape twice, but with different fills and masks. SVG lets you define a shape once and use it elsewhere, like a variable reference. I did that in my CodePen example - check the code and see how that works!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;I've still got plenty to learn with SVG, but &lt;code&gt;clip-path&lt;/code&gt; and &lt;code&gt;mask&lt;/code&gt; are two foundations I'm sure will help me make cooler stuff. If you're like me and feel jealous of the cool, graphic stuff you see developers making on CodePen, SVG is one of the first steps to making similar work and assuaging the deep desolation fermenting within one's soul.&lt;/p&gt;

&lt;p&gt;Rereading this post, I think the second part may just be me using learning to handle the mental stress of extended quarantine. But the point about writing better code still stands.&lt;/p&gt;

&lt;p&gt;So focus on that. I need to take a long walk. To the wine shop.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you're not sure where to start, &lt;a href="https://codepen.io/HunorMarton/pen/PoGbgqj"&gt;this Pen that doubles as a basic SVG tutorial&lt;/a&gt; helped me immensely. You can also grab a copy of &lt;a href="https://abookapart.com/products/practical-svg"&gt;"Practical SVG" from the "A Book Apart" series&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://safebooru.org/index.php?page=post&amp;amp;s=view&amp;amp;id=3336908"&gt;Featured image courtesy of SafeBooru.org&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>html</category>
      <category>svg</category>
      <category>frontend</category>
      <category>design</category>
    </item>
    <item>
      <title>What is Programmatic Determinability?</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Mon, 18 Jan 2021 11:20:57 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/what-is-programmatic-determinability-31mc</link>
      <guid>https://dev.to/maxwell_dev/what-is-programmatic-determinability-31mc</guid>
      <description>&lt;p&gt;The phrase "programmatic determinability" appears a lot in the Web Content and Accessibility Guidelines (WCAG). It's also the kind of phrase that could make you sound smart or conceited, depending on how you use it. For these two &lt;em&gt;very important&lt;/em&gt; reasons, I wanted to figure it out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.w3.org/TR/WCAG21/#dfn-programmatically-determinable"&gt;The official definition of "programmatically determined"&lt;/a&gt; kind of helped, but only kind of.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Determined by software from author-supplied data provided in a way that different user agents, including assistive technologies, can extract and present this information to users in different modalities&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a bit...dense. So I want to unpack it a bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Conversation Between Users and websites
&lt;/h2&gt;

&lt;p&gt;The most succinct definition I can think of &lt;strong&gt;programmatic determinability stops misunderstandings between users and websites.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes you get into arguments with people who refuse to say why they're upset. No matter how many questions you ask, they only give variations of "I'm upset and you should already know why." It's impossible to reach any kind of agreement or resolution, and most likely you storm off on them with less-than-pleasant thoughts.&lt;/p&gt;

&lt;p&gt;A better scenario is you meet someone upset, and when you ask why, they say they're upset a store no longer sells their favorite cheesecake. You probably can't fix the underlying issue, but now you can do more helpful things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Share a similar experience to show them they're not alone&lt;/li&gt;
&lt;li&gt;Offer to get some cheesecake from a new place so they see there are still options out there&lt;/li&gt;
&lt;li&gt;Join them in their rage so they blow off steam by smashing cheesecake cardboard cutouts you coincidentally have lying around&lt;/li&gt;
&lt;li&gt;Offer use of a time machine to go back to when it was still sold so they can have it one last time and bid their cheesecake a fond farewell. Then the clouds part, the light shines through, and they can take another step forward in life as the credits roll.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first fruitless, frustrating argument version is a website without programmatic determinability.&lt;/p&gt;

&lt;p&gt;Your website (the angry friend) isn't giving enough information to users using assistive technology (the frustrated friend). The user asks but gets nothing, doesn't know what to do next, and leaves in a huff.&lt;/p&gt;

&lt;p&gt;Want to avoid that scenario? &lt;strong&gt;That website needs that info in a coded format the browser can understand. Then the browser can share it and the two friends, user and website, can finally reconcile. This is programmatic determinability.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Share "Obvious" Info with Users
&lt;/h2&gt;

&lt;p&gt;Here's a specific example: say an English-speaking user visits a website written in a foreign language. They know it has information they need to read but can't understand it. If the computer could talk, their interaction could go like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User:&lt;/strong&gt; I can't understand what you're saying, webpage. What language are you in?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webpage:&lt;/strong&gt; How are you not able to understand me? Everyone else can.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User:&lt;/strong&gt; Well, I can't. Do you know English?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webpage:&lt;/strong&gt; What's English?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User:&lt;/strong&gt; How do you not know that?!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webpage:&lt;/strong&gt; I don't know, you should just speak my language.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It goes back and forth like this for a while until the user quits from frustration. They tell all their friends how uncooperative the site was and its reputation suffers and dies on a neglected 404 page.&lt;/p&gt;

&lt;p&gt;The site in question forgot the &lt;code&gt;lang&lt;/code&gt; attribute on its &lt;code&gt;html&lt;/code&gt; tag. Without that, the website couldn't tell the user it was written in Italian. It can't share the info that would end this fight between user and website since it isn't programmatically determinable.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;lang&lt;/code&gt; attribute is the coded way the browser can understand what the language is. When it's included, the exchange may go like this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User:&lt;/strong&gt; I can't understand what you're saying, webpage. What language are you in?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webpage:&lt;/strong&gt; I'm written in Italian. Most of my users read that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User:&lt;/strong&gt; I get why you'd think that, but I can only read English. Do you have any translation options?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webpage:&lt;/strong&gt; I don't think so, but something like Google Translate can help. When I tell it my language, it'll do a rough translation to English.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User:&lt;/strong&gt; That'll work for now. Thanks!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the relationship is saved, the user isn't lost, and they can go out for cheesecake together later!&lt;/p&gt;

&lt;p&gt;Many accessibility issues can be boiled down to this kind of argument between users and inaccessible webpages that don't communicate well.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It seems obvious where the navigation, sidebars, and main content are located in your layout. But some people won't see the layout. So you should share those relationships with roles or semantic markup.&lt;/li&gt;
&lt;li&gt;It seems obvious what's being shown on an image. But some people won't see the images. So you should share descriptions with &lt;code&gt;alt&lt;/code&gt; tags.&lt;/li&gt;
&lt;li&gt;It seems obvious what you're alerting users to with brightly-colored banners. But some people won't see those bright colors, or see the page at all. So you should share how important they are through explicit text, and ARIA live regions or alert roles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These take even more forms - knowing how to solve them for as many users and websites as possible is part of the never-ending accessibility journey. Programmatic determinability is only one part of it, albeit one of the most important ones.&lt;/p&gt;

&lt;p&gt;Keep it in mind, and your users will never miss out on cheesecake with your website again.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What I Didn't Know in the 2020 State of CSS Survey, Part 2</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Thu, 17 Dec 2020 10:31:44 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/what-i-didn-t-know-in-the-2020-state-of-css-survey-part-2-18m6</link>
      <guid>https://dev.to/maxwell_dev/what-i-didn-t-know-in-the-2020-state-of-css-survey-part-2-18m6</guid>
      <description>&lt;p&gt;Last month I wrote about the first batch of CSS goodness I discovered by taking the State of CSS Survey this year. Then I got delayed from writing this second part thanks to the continued pandemic, changing apartments, and reading &lt;a href="https://stateofcss.com/" rel="noopener noreferrer"&gt;the results of the State of CSS survey&lt;/a&gt; itself. I also think &lt;a href="https://www.maxwellantonucci.com/posts/2020/11/28/birthday-resolution-fail-more/" rel="noopener noreferrer"&gt;I had a birthday of some kind&lt;/a&gt;, I'm not sure.&lt;/p&gt;

&lt;p&gt;Valid excuses aside, I have finally finished part two of this CSS min series. So I'll get back to it without further delay!&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Exclusions
&lt;/h2&gt;

&lt;p&gt;The journey begins.&lt;/p&gt;

&lt;p&gt;Most people who've worked on the front-end will recognize this kind of layout:&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%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcss-survey-2%2Fexclusion-1.jpeg" class="article-body-image-wrapper"&gt;&lt;img alt="A layout where the image is pushed all the way to the left, with text flowing around it to the right." src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcss-survey-2%2Fexclusion-1.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's pretty simple. A designer wants to include a small image alongside the text. Having it wrap around the image lets it be included without wasting too much space.&lt;/p&gt;

&lt;p&gt;The main way to do this is with &lt;code&gt;float&lt;/code&gt;. It pushes an element to one side of the container, and any surrounding elements wrap around it. I do the same thing on my own "About" page. It's an established solution to this problem.&lt;/p&gt;

&lt;p&gt;Not so fast.&lt;/p&gt;

&lt;p&gt;Say one day your designer comes to you with this layout.&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%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcss-survey-2%2Fexclusion-2.jpeg" class="article-body-image-wrapper"&gt;&lt;img alt="Another layout with two columns of text and an image in the space between them. The text in both columnds wraps around the image as needed." src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcss-survey-2%2Fexclusion-2.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, &lt;code&gt;float&lt;/code&gt; isn't going to help you at all. Floats being you to one side or the other, it can't put you between two elements. There's no real way to get this effect with Grid or Flexbox that's responsive and not excessively convoluted either.&lt;/p&gt;

&lt;p&gt;Or so I thought.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://webdesign.tutsplus.com/tutorials/css-exclusions--cms-28087" rel="noopener noreferrer"&gt;CSS Exclusions&lt;/a&gt; enters the scene. If you apply a CSS Exclusion to an element, you're telling the browser it's an "exclusion element" and it gets its very own "exclusion box." &lt;strong&gt;An exclusion box is that element telling the others around it they can't overlap or touch it. They're excluding it from its space!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's certainly rude, but the other elements have to put up with it. The good news is they won't go out of their way to appease the exclusion element. They'll avoid it but they'll keep following their own formatting rules. If they let one element like that destroy the whole layout, it would be anarchy!&lt;/p&gt;

&lt;p&gt;So in the above example, where the exclusion element is between two columns of text? That text will wrap around the exclusion element without leaving their defined column areas. Same thing if it was in a Flexbox or Grid layout.&lt;/p&gt;

&lt;p&gt;Yes, you could have float-style wrap effects in Flexbox or Grid layouts! This opens up so many new layout opportunities with much simpler styling.&lt;/p&gt;

&lt;p&gt;That, my dear friends/readers/informants, is what makes CSS Exclusions awesome.&lt;/p&gt;

&lt;p&gt;According to current specs, you create the actual effect with the &lt;code&gt;wrap-flow&lt;/code&gt; property. It has seven potential values that let you decide how content flows around an element. You have the basic wrapping like above, or you could clear content on the entire sides of the element. &lt;a href="https://chenhuijing.com/blog/css-exclusions-with-queen-bey/#%F0%9F%92%BB" rel="noopener noreferrer"&gt;This Beyonce-inspired article has more specific details on CSS Exclusion options if you want them&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One final note, which is a disappointing one: Only one browser supports CSS Exclusions, and it's Edge, the one browser you likely never use unless you're doing cross-browser testing. So you'll need to be patient before using this in production. Or anywhere, really.&lt;/p&gt;

&lt;p&gt;So the adventure continues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pointer Events
&lt;/h2&gt;

&lt;p&gt;The term "pointer event" may make you think only of mouse pointers. But &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events" rel="noopener noreferrer"&gt;pointer address a wide variety of events around interacting with something online&lt;/a&gt; - using a stylus, touch screens, or other kinds of assistive tech. As long as the trigger can be focused around coordinates on a device (the point on the screen), pointer events shall handle them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;pointer-events&lt;/code&gt; CSS property lets you set the circumstances that the selected element can become targeted by pointer events.&lt;/strong&gt; You could use CSS to give a link no pointer events so you could only interact with it like normal text.&lt;/p&gt;

&lt;p&gt;There's a lot of possible values for the &lt;code&gt;pointer-events&lt;/code&gt; property, but most relate to SVG that I won't go into here. The main ones for HTML elements are keeping the default, removing them all, or basing it on what the parent element's pointer events are.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://css-tricks.com/almanac/properties/p/pointer-events/" rel="noopener noreferrer"&gt;The CSS Tricks Almanac (a great resource overall) gives the above example of where you may want to use the pointer-events property&lt;/a&gt;: letting users click through overlays or other elements that may block other elements you want to let users keep access to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Color Gamut
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.livescience.com/42797-mantis-shrimp-sees-color.html" rel="noopener noreferrer"&gt;A sad truth is we are not like the mantis shrimp&lt;/a&gt;. We only have three color receptors in our eyes, and the mantis shrimp has twelve. They can see color in a way far beyond our puny human brains.&lt;/p&gt;

&lt;p&gt;We also can't attack people with lightning-fast strikes carrying over 200 pounds of force, but one depressing fact at a time.&lt;/p&gt;

&lt;p&gt;But at least our computers are getting better at seeing new colors. Some desktops can display colors at a level we don't know about when we're picking our website's colors, also called a "wide-gamut display." That's a quick way to a lackluster-looking site, picking colors that don't make use of all these possible color options.&lt;/p&gt;

&lt;p&gt;We have an advantage over the mantis shrimp here. We have CSS! It brings us three new color modes to make use of this wider gamut of color options: &lt;code&gt;lab&lt;/code&gt;, &lt;code&gt;lch&lt;/code&gt;, and &lt;code&gt;display-p3&lt;/code&gt;. I won't get into their syntaxes here, but those who want to know more now can read &lt;a href="https://css-tricks.com/the-expanding-gamut-of-color-on-the-web/" rel="noopener noreferrer"&gt;this CSS Tricks articles on using these new color modes&lt;/a&gt;. But to understand &lt;code&gt;color-gamut&lt;/code&gt;, you only need to know they exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why? Because it's the media query that lets you use the colors when available!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Say you have a basic red color as a hex value. But you also have a nice &lt;code&gt;display-p3&lt;/code&gt; color you want to use for desktops that can. You can include both by using the media query like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#FF0000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&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;color-gamut&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;p3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--red&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;display-p3&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0.331&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c"&gt;/* Let us presume this is a nicer red color */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are other ways to handle like, like a &lt;code&gt;@supports&lt;/code&gt; query or passing a fallback to the &lt;code&gt;color()&lt;/code&gt; function. But the media query gives you more control and lets you add additional styles behind the query if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Line-clamp
&lt;/h2&gt;

&lt;p&gt;This property was easier to learn since you can guess it from the name. &lt;a href="https://css-tricks.com/almanac/properties/l/line-clamp/" rel="noopener noreferrer"&gt;Line-clamp lets you set a maximum number of lines for an element to show&lt;/a&gt;. If there are any more lines than that, the CSS &lt;em&gt;clamps&lt;/em&gt; down on them and treat them as overflow.&lt;/p&gt;

&lt;p&gt;You can see some basic examples of how this works below.&lt;/p&gt;

&lt;p&gt;You can also handle the overflow in different ways that CSS already allows. &lt;strong&gt;You can hide the extra text altogether or let users scroll to see more.&lt;/strong&gt; The latter could be useful with modals that could have an unpredictable number of lines.&lt;/p&gt;

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

&lt;p&gt;I welcome this property and am glad it already has surprisingly good browser support. The past tricks I've used to limit text to one line took modifying white space and manually adding ellipses, which worked but was a lot of hassle to get right. This is simpler and even adds ellipses for me. All it needs now is to put the extra mint on my pillow.&lt;/p&gt;

&lt;h2&gt;
  
  
  New Units of Size
&lt;/h2&gt;

&lt;p&gt;I only use rem and pixel units in my styling these days, but there are some other CSS units worth remembering in the future.&lt;/p&gt;

&lt;p&gt;First are three that don't need much explanation to most people - mm, cm, and in. &lt;strong&gt;They refer to their real-life measurement units of millimeters, centimeters, and inches.&lt;/strong&gt; They're absolute values like pixels, which means they won't change if users adjust their browser for bigger font sizes. But they can be useful if you're styling a print-specific version of a webpage since you're working within more static sizes for your content anyway. That and they're the units many people are already used to when designing for print.&lt;/p&gt;

&lt;p&gt;The fourth unit I found, ex, is a little trickier. &lt;a href="https://webdesign.tutsplus.com/articles/7-css-units-you-might-not-know-about--cms-22573" rel="noopener noreferrer"&gt;"Ex" is a relative size unit equal to one unit of the current font's x-height&lt;/a&gt;. &lt;strong&gt;A simple way to find the x-height value is to measure how high the letter "x" is in that font.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcss-survey-2%2Fx-height.jpeg" class="article-body-image-wrapper"&gt;&lt;img alt="A visual example of what determines the x-height. It's the height of the letter 'x.'" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcss-survey-2%2Fx-height.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how much &lt;code&gt;1ex&lt;/code&gt; unit will be. It'll be equal to most other lowercase letters too. So it's useful for lots of typographic spacing, on a large or small scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  New Pseudo-Elements
&lt;/h2&gt;

&lt;p&gt;The only pseudo-elements I knew before were &lt;code&gt;::before&lt;/code&gt; and &lt;code&gt;::after&lt;/code&gt;, and I thought they were mainly for adding extra elements for more advanced styling. &lt;strong&gt;These new pseudo-elements have similar functionality but with more precise purposes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First is &lt;code&gt;::marker&lt;/code&gt;, which can only be used on list items. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::marker" rel="noopener noreferrer"&gt;&lt;code&gt;::marker&lt;/code&gt; lets you adjust a few styles for the item's "marker box," or element that identifies them as a list item&lt;/a&gt;. For example, an unordered list's marker boxes are bullets, while ordered lists have numbers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::backdrop" rel="noopener noreferrer"&gt;&lt;code&gt;::backdrop&lt;/code&gt;, meanwhile, can only be used to style the backdrop behind the &lt;code&gt;dialog&lt;/code&gt; element&lt;/a&gt;. So adding a full-screen, transparent backdrop would be as easy as one more line of CSS. It even makes use of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API" rel="noopener noreferrer"&gt;the Fullscreen browser API&lt;/a&gt; to create the effect for us. Which I didn't even know was a thing until now.&lt;/p&gt;

&lt;p&gt;Seeing that dialog backdrops are already included in &lt;code&gt;dialog&lt;/code&gt; elements makes me even more eager for this HTML5 element to get stronger support. Dialogs are nightmares, but this element could make it easier to handle. Both these pseudo-classes (as well as dialog) only have mixed to decent browser support, so don't go crazy with them yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The :is() Selector
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;:is()&lt;/code&gt; selector is the next in the "Let CSS do naturally what Sass can do" series, following custom properties replacing Sass variables.&lt;/p&gt;

&lt;p&gt;Say you want to select all paragraphs in an &lt;code&gt;article&lt;/code&gt; or &lt;code&gt;section&lt;/code&gt; tag. Using Sass, you'd write it like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Styles goes here!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would get compiled into the following 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="nt"&gt;article&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;section&lt;/span&gt; &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* Styles go here! */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does what you need, but the compiled styles can grow surprisingly fast. Especially if you needed to style other elements in those two, like ordered and unordered lists.&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="nt"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="nt"&gt;article&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;article&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;section&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;section&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;section&lt;/span&gt; &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* Styles go here! */&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 compiled into six separate rules just from that! On a larger scale, you could even get dozens to try for this "matches any of the above" selector effects.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;:is()&lt;/code&gt; selector gives you that same effect without the preprocessing. You could theoretically get the same effect as above with 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="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nd"&gt;:is&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;p&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;ul&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* Styles go here! */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One selector rule that targets all the same styles, no Sass needed.&lt;/strong&gt; In some ways, it's even better since it's more readable than nested rules that grow out of hand.&lt;/p&gt;

&lt;p&gt;The most interesting thing about this selector is it's the third attempt to get CSS a selector like this, the first two being &lt;code&gt;:any()&lt;/code&gt; and &lt;code&gt;:matches()&lt;/code&gt;. As &lt;a href="https://css-tricks.com/almanac/selectors/i/is/" rel="noopener noreferrer"&gt;this other CSS Almanac on the ":is" selector&lt;/a&gt; points out, these first two put together have decent browser support. Presuming &lt;code&gt;:is()&lt;/code&gt; gets finalized into CSS later on, it would likely replace those two. But until then, there's a somewhat convoluted but workable way to use this today if you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Link Selectors
&lt;/h2&gt;

&lt;p&gt;Turns out you can target link elements with more than a mere anchor tag selector.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://css-tricks.com/almanac/selectors/a/any-link/" rel="noopener noreferrer"&gt;First off is &lt;code&gt;:any-link&lt;/code&gt;, which looks for any possible element that has an &lt;code&gt;href&lt;/code&gt; attribute&lt;/a&gt; (including the lesser-known &lt;code&gt;link&lt;/code&gt; and &lt;code&gt;area&lt;/code&gt;). This includes any link elements that have been visited and you'd need to use &lt;code&gt;:visited&lt;/code&gt; to target otherwise. It's got pretty good browser support, so you can use it today!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:local-link" rel="noopener noreferrer"&gt;Next up is &lt;code&gt;:local-link&lt;/code&gt;, that only targets links in the current domain&lt;/a&gt;. &lt;strong&gt;So you can easily change styles between links to other sites and links staying on your own.&lt;/strong&gt; An example I can think of is distinguishing external links in any site navigations, since otherwise, users may assume all those links stay in your website. One website I saw said you could even target it based on sub-domains, like links only in your local &lt;code&gt;/blog/&lt;/code&gt; pages, but couldn't confirm this anywhere else. But unlike &lt;code&gt;:any-link&lt;/code&gt;, this is still a working draft and has zero support as of this writing.&lt;/p&gt;

&lt;p&gt;Third up is...nothing. There were only two link selectors I wanted to cover here.&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;could&lt;/em&gt; have organized this section up better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Form Controls
&lt;/h2&gt;

&lt;p&gt;These pseudo-classes are all about form inputs and their states. There's a bunch to cover, so I'll tackle them all lightning round style.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.digitalocean.com/community/tutorials/css-styling-form-input-validity" rel="noopener noreferrer"&gt;&lt;code&gt;valid&lt;/code&gt; and &lt;code&gt;invalid&lt;/code&gt; only work for required fields with at least one rule&lt;/a&gt;, like being a number or falling in a certain range. You can also pair them with the &lt;code&gt;:focus&lt;/code&gt; selector to only show the styles on user focus.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://css-tricks.com/almanac/selectors/u/user-invalid/" rel="noopener noreferrer"&gt;&lt;code&gt;user-invalid&lt;/code&gt; is the same as &lt;code&gt;invalid&lt;/code&gt;, but only kicks in after the user has interacted with the field once&lt;/a&gt;. So if a form loads with a pre-filled, invalid value, these styles won't kick in until the first interaction.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;indeterminate&lt;/code&gt; is a tricky "maybe" state in some inputs, most commonly seen in checkboxes. The browser sees &lt;a href="https://css-tricks.com/almanac/selectors/i/indeterminate/" rel="noopener noreferrer"&gt;&lt;code&gt;indeterminate&lt;/code&gt; inputs as "unchecked," but are styled differently to look like a kind of half-yes, half-no&lt;/a&gt;. You can also only get this state by using JavaScript. So I'd avoid relying on this state without a good reason, even with good support for it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://css-tricks.com/almanac/selectors/i/in-range/" rel="noopener noreferrer"&gt;&lt;code&gt;:in-range&lt;/code&gt; and &lt;code&gt;:out-of-range&lt;/code&gt; speak for themselves: they style if an input value falls inside or outside the input's set range&lt;/a&gt;. The most obvious example is a number being too high or too low from what's allowed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Prosciutto&lt;/code&gt; is an Italian dry-cured ham that is usually thinly sliced and served uncooked, and is known as &lt;code&gt;prosciutto cotto&lt;/code&gt; in Italy. It's notably high in fat and sodium, so for a daily diet, you may want to...oh, sorry, need to save this for the next &lt;a href="https://www.jackboxgames.com/trivia-murder-party/" rel="noopener noreferrer"&gt;Trivia Murder Party&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Phew, that's a lot to cover in an already long blog post. I'm off to the bonus round before I wrap this up.&lt;/p&gt;

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

&lt;p&gt;Even after two whole posts, there's still content from the CSS Survey I haven't covered! They're mostly methodologies, podcasts, newsletters, and more. But I barely had time to write this amid moving and a pandemic, so I'm going to pass on those for now.&lt;/p&gt;

&lt;p&gt;So I'm closing the books on this little mini-series. Some people may understandably think I only scratched the surface of what these tools can do and how to demonstrate them. I would agree with them, and encourage them to look into them more! &lt;strong&gt;There are way too many nuances of functionality, overlap with past CSS properties, and browser support to cover in one post. Any one of these sections could have been a separate blog post.&lt;/strong&gt; I encourage anyone up for it to try writing one of them!&lt;/p&gt;

&lt;p&gt;I also encourage them to get six to eight hours of sleep and floss regularly. But once you have those covered, the blog writing awaits.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>What I Didn't Know in the 2020 State of CSS Survey, Part 1</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Fri, 06 Nov 2020 14:55:38 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/what-i-didn-t-know-in-the-2020-state-of-css-survey-part-1-481d</link>
      <guid>https://dev.to/maxwell_dev/what-i-didn-t-know-in-the-2020-state-of-css-survey-part-1-481d</guid>
      <description>&lt;p&gt;Like all humans, I like answering questions since it makes me feel smart and powerful on an unconscious level. My most recent indulgence of this was the 2020 State of CSS Survey, which has the added benefit of helping my industry. But it was mostly for that first reason.&lt;/p&gt;

&lt;p&gt;That got thrown off when I saw how many CSS topics I knew little or no details about. I took note of them all as I filled out the survey. When I'd finished, I saw the survey was thinking the same thing as me.&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%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcss-survey-1%2Fcss-survey-recommendations.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fcss-survey-1%2Fcss-survey-recommendations.png" alt="A recommendation from the State of CSS survey to learn more about the topics I was not familiar with."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The catch is there were so many things I wanted to check, I couldn't fit them into one post. So here's the first part with what they recommended I check first, and with the rest coming later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logical Properties
&lt;/h2&gt;

&lt;p&gt;If you're like me, you read web content in English, which is read from left to right. Let's say I was coding a blog post layout and needed some extra margin where the text started. I'd add some CSS like this, right?&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;.blog-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&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;However, plot twist! Not everyone on the Internet reads in the same language. Some people, shock of shocks, read it in languages that don't go from left to right. For example, Arabic and Hebrew alphabets are read from right to left. Chinese and Japanese can be written vertically from right to left. So that &lt;code&gt;margin-left&lt;/code&gt; for "the starting side of the content" won't work if the user switches to one of these languages.&lt;/p&gt;

&lt;p&gt;I admit these are unlikely to virtually impossible scenarios for many sites. For some, like personal developer blogs run by twenty-somethings who finally gave up on Internet fame, these are extreme edge cases. But it still happens, and front-end developers are all about building in solutions for a cohesive, inclusive experience.&lt;/p&gt;

&lt;p&gt;That's where logical properties come in. We could rewrite the above CSS to something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.blog-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;margin-block-start&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the margin's position is set relative to the start of the writing mode. &lt;strong&gt;If the user is using a left to right writing mode like English, it's put on the left side. Right to left writing modes go on the right side automatically.&lt;/strong&gt; Used right (pun intended), logical properties keep layouts accessible in the face of different languages and reading styles. The current spec lets you use them for margin, padding, border styling, and absolute positioning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/" rel="noopener noreferrer"&gt;You can read a much better, more detailed explanation of logical properties from Rachel Andrew here&lt;/a&gt;. Or you can see a quick demo of hers below.&lt;/p&gt;

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

&lt;p&gt;I should note at the time I'm writing this, there's little browser support for this feature. But it's good to get a basic understanding early on so you're ready to use it when you can.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contain
&lt;/h2&gt;

&lt;p&gt;Some parts of a webpage may change even after it's loaded up. A list of recent tweets on a personal site may show new tweets as they're posted. A browser will see this happen and need to figure out exactly what's changing and optimize for it. But sometimes a browser may try to optimize the entire webpage around the change, not just the Twitter widget showing the new tweet. That's quite bad for performance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Contain&lt;/code&gt; tells the browser it'll only need to optimize things for that area. So I could add this to my Twitter widget:&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;.twitter-widger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;layout&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;strong&gt;This tells the browser "if you see a change in this element, only optimize things for it and not the entire page."&lt;/strong&gt; How the browser actually handles this depends on the browser itself. This property only lets developers pass that info along.&lt;/p&gt;

&lt;p&gt;I used &lt;code&gt;contain: layout&lt;/code&gt; in this example, but there's actually other values you can use with different effects. Once again, &lt;a href="https://www.smashingmagazine.com/2019/12/browsers-containment-css-contain-property/" rel="noopener noreferrer"&gt;Rachel Andrew already explains the specifics of CSS Contain better in this (better) article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  backdrop-filter
&lt;/h2&gt;

&lt;p&gt;I've seen lots of blog post designs built around text placed over a big banner image. My own blog used a design like this until recently. The problem is text right on the image is hard or impossible to read. A common solution is giving it a solid color background, which isn't too pretty but makes it readable.&lt;/p&gt;

&lt;p&gt;There's another, more stylish way with &lt;code&gt;backdrop-filter&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;For any design with a visual right behind an element, like a banner image behind a blog title, this property can be helpful. &lt;strong&gt;Instead of blocking it out from the blog title entirely, it can add filters between the title and the image acting as the backdrop. The filters only affect the overlapping area, not the entire backdrop.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With this, we can add a few filters to make a "frosted glass" effect. I can blur the image, lower the contrast, and brighten it up.&lt;/p&gt;

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

&lt;p&gt;Now the text is easier to read while letting the original image shine through for a sleeker, more polished effect. Most browsers supported this except for IE and Firefox. I happen to use Firefox a lot, so I hid &lt;code&gt;backdrop-filter&lt;/code&gt; behind a &lt;code&gt;@supports&lt;/code&gt; query with basic light blue background color as a fallback. Progressive enhancement always wins!&lt;/p&gt;

&lt;h2&gt;
  
  
  touch-action
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://css-tricks.com/almanac/properties/t/touch-action/" rel="noopener noreferrer"&gt;This touch-events article from CSS Tricks&lt;/a&gt; has a good example of where to use these. Say a user on a mobile touch device is trying to zoom in and out with pinch gestures. But instead of interacting with the map, they're just zooming in and out of the page itself. The browser event listeners are set up to see "pinch gesture" as "zoom in and out." So the developer needs to override and remove those for this map!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before, coders would need to handle this with JavaScript by hooking into the page or component and overriding the needed gestures. But &lt;code&gt;touch-action&lt;/code&gt; lets them specify any touch events to keep from the CSS.&lt;/strong&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="nc"&gt;.map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;touch-action&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;This turns off all browser touch events for the map, and any others need to be added through the JavaScript. But it also lets developers specify which events to keep.&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;.map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;touch-action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pan-x&lt;/span&gt; &lt;span class="n"&gt;pan-y&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 tells the browser to only handle touch events for panning around the map, while turning off the rest (like zooming). The end result is developers have more control over their user's touch experiences before they get messy and out of hand.&lt;/p&gt;

&lt;p&gt;...I'm going to ignore how dirty that sounded and move on.&lt;/p&gt;

&lt;h2&gt;
  
  
  overscroll-behavior
&lt;/h2&gt;

&lt;p&gt;There have been times I used websites with modals.&lt;/p&gt;

&lt;p&gt;They were dark times I don't like to discuss, but I need to for this example. So bear with me if I stare off and scream for a moment.&lt;/p&gt;

&lt;p&gt;Let's say a site has a particularly evil modal with so much content, a user needs to scroll through it. They scroll through it real fast, abruptly hit the end without noting fast enough, and keep on scrolling. The user will be scrolling within the modal but wind up scrolling down the whole page by accident. It's not fun and makes it easy to lose one's place.&lt;/p&gt;

&lt;p&gt;This unwanted event is called "&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior" rel="noopener noreferrer"&gt;scroll chaining&lt;/a&gt;," and it's something &lt;code&gt;overscroll-behavior&lt;/code&gt; aims to stop like so:&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;.modal-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;overscroll-behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If you're scrolling in that area, even when you reach the end, it won't ever scroll you past that area.&lt;/strong&gt; You can check this out in action below if you're using a supportive browser (which is now most of them aside from IE and Safari).&lt;/p&gt;

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

&lt;p&gt;Now the user will reach the end of the modal content and go no further, as God intended.&lt;/p&gt;

&lt;h2&gt;
  
  
  overflow-anchor
&lt;/h2&gt;

&lt;p&gt;Let's say a user is scrolling down a long webpage and stop at an interesting paragraph. Unknown to them, an unloaded large image is lurking in the areas they just scrolled by. When the user least suspects it, the webpage attacks by finishing the delayed image load! It's a sneak attack that pushes the webpage down, changing the visible viewport, and making users lose their place. Evil triumphs again and the credits roll.&lt;/p&gt;

&lt;p&gt;Actually, this probably hasn't happened to users as much lately in most browsers. That's because &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-anchor/Guide_to_scroll_anchoring" rel="noopener noreferrer"&gt;browsers have something called scroll anchoring&lt;/a&gt;. When the large image tries to mess with what a user is reading, the browser adjusts their scroll position to match the change. While the scroll position changes, what the user sees doesn't change, and good wins the eternal battle against the vile.&lt;/p&gt;

&lt;p&gt;This is possible due to the &lt;code&gt;overflow-anchor&lt;/code&gt; property, which defaults to &lt;code&gt;auto&lt;/code&gt; to enable this behavior. For the first time, evil is defeated while good men do nothing.&lt;/p&gt;

&lt;p&gt;But there may be rare cases where you don't want good to win. A webpage may have custom scroll behaviors, difficultly loading images, or the developer wants to watch the world burn. &lt;strong&gt;Support for the &lt;code&gt;overflow-anchor&lt;/code&gt; property lets them disable scroll anchoring.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For these edge cases or debugging. You monster.&lt;/p&gt;

&lt;h2&gt;
  
  
  font-variant-numeric
&lt;/h2&gt;

&lt;p&gt;I won't lie, despite this property seeming so simple, it took me the longest to wrap my head around.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The simplest explanation I have is it changes the default way certain numbers are shown.&lt;/strong&gt; These are mainly style changes, like showing a slash through a zero, or if fractions should have a slash in the middle. This can make things easier to read or understand for users, depending on what they're used to.&lt;/p&gt;

&lt;p&gt;Let's say I want to change how numeral expressions like "1st" and "3rd" appear on my website. &lt;code&gt;font-variant-numeric&lt;/code&gt; can change that in ways that are both correct and incorrect.&lt;/p&gt;

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

&lt;p&gt;I personally see limited use cases for a feature like this. But that could be because it's outside my range of experiences or needs, so I'll limit my judgment for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  font-display
&lt;/h2&gt;

&lt;p&gt;You remember the "flash of invisible text (FOIT)," one of those problems that haunts designers and developers in the dead of night? When coders set a custom font, but until the font loads, it's invisible to the user and flashes onto the page after most or all of the page is already there. It doesn't break anything, but it's jarring and the stuff of nerd nightmares.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;font-display&lt;/code&gt; brings us one step closer to fully solving this issue. It tells the browser to use a fallback font while waiting for the other font to load.&lt;/strong&gt; There are a few different options for how to approach this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the fallback font right away. This can create a "flash of unstyled text."&lt;/li&gt;
&lt;li&gt;Wait a little, and if the custom font isn't ready, use the fallback font until it is.&lt;/li&gt;
&lt;li&gt;Same as the second option, but it sticks with the fallback font if the browser figures the custom one won't be used at all.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The problems around trying to load different fonts and how they affect what users see likely aren't going anywhere. But developers at least have more choice and control over which problems they'll get. This makes it easier to work around them or design better solutions.&lt;/p&gt;

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

&lt;p&gt;I learned a lot from the 2020 State of CSS Survey and writing this post, but I haven't even gotten through half the items on my list. So stay tuned for future posts with even more new CSS knowledge goodness!&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>Scheduling Blog Posts with Eleventy, Netlify, and IFTTT</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Tue, 27 Oct 2020 13:57:52 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/scheduling-blog-posts-with-eleventy-netlify-and-ifttt-507o</link>
      <guid>https://dev.to/maxwell_dev/scheduling-blog-posts-with-eleventy-netlify-and-ifttt-507o</guid>
      <description>&lt;p&gt;There have been many benefits to moving my personal site from Jekyll to Eleventy: better build speed, not mixing Ruby and JavaScript in the pipeline, and getting a big tax writeoff. I still love Jekyll since it's what got me into static site generators, but Eleventy may have become my new default.&lt;/p&gt;

&lt;p&gt;One of my favorite benefits is how I can schedule future posts. Any Jekyll solution I tried was inconsistent and had overly-complicated template logic at best. At worst, I tried sending new blog posts back in time and &lt;a href="https://tvtropes.org/pmwiki/pmwiki.php/VisualNovel/SteinsGate"&gt;nearly got my loved ones killed and/or caught in an authoritarian hellscape ruled by French scientists&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But Eleventy, with a little help from &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt; and &lt;a href="https://ifttt.com/home"&gt;IFTTT (If This Than That)&lt;/a&gt;, helped me avoid those unmaintainable or dystopian workarounds. I'm sure this interests other casual bloggers and freedom fighters, so I wrote this blog post!&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter out Future Posts
&lt;/h2&gt;

&lt;p&gt;The first step is straightforward: how do I keep Eleventy from showing future posts?&lt;/p&gt;

&lt;p&gt;One Eleventy feature I love that Jekyll lacks is to hook into the build process. It lets you add custom collections, tags, filters, and other functionality. So I tried making a custom "hide future blog posts" collection.&lt;/p&gt;

&lt;p&gt;This was my default JavaScript setup to gather and organize my blog posts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFilteredByGlob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./posts/*.md&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reverse&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 returns a simple array of blog post objects. And in JavaScript, arrays have a built-in way to take out items you don't want: the &lt;code&gt;filter&lt;/code&gt; method! All I need is to write and pass in a filter function that removes future posts.&lt;/p&gt;

&lt;p&gt;Here's what I started with, with &lt;code&gt;post&lt;/code&gt; being any potential blog post the filter had to check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hideFutureItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;postDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...what else?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;postDate&lt;/code&gt; here is a timestamp in Coordinated Universal Time, or UTC, format. Something scheduled for October 23rd would have &lt;code&gt;2020-10-23T00:00:00.000Z&lt;/code&gt; as that value. I played around with this value and found it was being made with &lt;a href="https://www.w3schools.com/jsref/jsref_obj_date.asp"&gt;JavaScript's Date Reference&lt;/a&gt;. It's one of the language's built-in ways to manage units of time.&lt;/p&gt;

&lt;p&gt;I checked the documentation, and found a method called &lt;code&gt;getTime()&lt;/code&gt;. It returns the number of milliseconds between January 1st, 1970 (&lt;a href="https://stackoverflow.com/questions/1090869/why-is-1-1-1970-the-epoch-time#1090945"&gt;the standard beginning Unix timestamp for reasons not important for this post&lt;/a&gt;) and the specific date. For example, October 23rd, 2020 returns &lt;code&gt;1603411200000&lt;/code&gt; milliseconds.&lt;/p&gt;

&lt;p&gt;This seemed silly and obscure, but it gave me an idea.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the number of milliseconds based on the present day.&lt;/li&gt;
&lt;li&gt;Do the same thing for the post's date.&lt;/li&gt;
&lt;li&gt;If the post's milliseconds are &lt;strong&gt;higher&lt;/strong&gt; than today's milliseconds, it means the post's date is &lt;strong&gt;after&lt;/strong&gt; today. That means it's a future post and will return &lt;code&gt;false&lt;/code&gt; to exclude it.&lt;/li&gt;
&lt;li&gt;All other posts should be included by returning &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result is a smug, satisfactory feeling of smartness...and this function I added to the collection function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hideFutureItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;getTime&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;now&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFilteredByGlob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./posts/*.md&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hideFutureItems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reverse&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;With that, I exiled all future posts from my website!&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Set Up Daily Deploys
&lt;/h2&gt;

&lt;p&gt;Everything so far is good but has a major blind spot. &lt;strong&gt;The date the site sees as "today" is only set when I generate the site pages.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's say I relaunch my site on Tuesday that included a scheduled post for the next day. The site's going to think it's still that exact Tuesday for days and even weeks afterward. I could only "schedule" posts if it checks the date and rebuilds itself each day. But relaunching my site each day is the kind of monotonous chore I want to avoid!&lt;/p&gt;

&lt;p&gt;That's where Netlify and IFTTT come in.&lt;/p&gt;

&lt;p&gt;First, &lt;a href="https://docs.netlify.com/configure-builds/build-hooks/"&gt;Netlify lets you add build hooks&lt;/a&gt;. These are URLs you can send a POST request to that trigger new builds. I set one up for daily builds and copied the given URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uVWWyIiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.maxwellantonucci.com/assets/images/posts/scheduled-eleventy-netlify-posts/netlify-build-hook.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uVWWyIiN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.maxwellantonucci.com/assets/images/posts/scheduled-eleventy-netlify-posts/netlify-build-hook.png" alt="" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I had to hit this URL each day. I remembered IFTTT as a tool for making simple, conditional web actions. So I can link their "time" and "webhook" services together into "send a POST request to this webhook every day at 7 am."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iDfTQ-K9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.maxwellantonucci.com/assets/images/posts/scheduled-eleventy-netlify-posts/ifttt-redeploy-applet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iDfTQ-K9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.maxwellantonucci.com/assets/images/posts/scheduled-eleventy-netlify-posts/ifttt-redeploy-applet.png" alt="" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are some costs to this. I saw Netlify has set up built-in bandwidth and build time limits for starter accounts like mine. But considering how light and speedy Eleventy builds are, and I don't have any heavy apps hosted on Netlify, these shouldn't be an issue for casual bloggers like myself.&lt;/p&gt;

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

&lt;p&gt;Moving from Jekyll to Eleventy wasn't easy, but on the whole, I've found it worth it. If you're a programmer looking for a personal website side-project, I recommend this. If not for all these perks, at least do it to distract your mind from the field of damnation that is the world.&lt;/p&gt;

&lt;p&gt;So happy scheduling!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>productivity</category>
      <category>serverless</category>
    </item>
    <item>
      <title>The Widening Anxieties of Young Front-end Developers</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Wed, 14 Oct 2020 11:27:34 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/the-widening-anxieties-of-young-front-end-developers-4fog</link>
      <guid>https://dev.to/maxwell_dev/the-widening-anxieties-of-young-front-end-developers-4fog</guid>
      <description>&lt;p&gt;Last week I read &lt;a href="https://css-tricks.com/the-widening-responsibility-for-front-end-developers/" rel="noopener noreferrer"&gt;Chris Coyier's essay, "The Widening Responsibility for Front-end Developers,"&lt;/a&gt; and it hit me hard. It reminded me how the career I enjoy so much is also one of my biggest sources of anxiety.&lt;/p&gt;

&lt;p&gt;Let me be clear: I love that being a web developer means I'm always learning. I'm finding new ways to solve puzzles and be creative. Even better, I can set the pace of my learning, so I'm not pulling all-nighters or freaking out over exams. It's satisfying to look at code I wrote a year ago and see the different ways I'd write it now. I can see all the progress I've made, especially as it relates to my growing specialization of accessibility.&lt;/p&gt;

&lt;p&gt;But the root of that push to improve is feeling insecure in my knowledge and helps in small doses. &lt;a href="https://www.maxwellantonucci.com/posts/2019/07/21/insecure-programmer/" rel="noopener noreferrer"&gt;I even wrote on my blog about how I turn my insecurity into the rising tide that lifts me&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That feeling is bad when it grows to the point where instead of learning, I'm questioning if I can handle this career.&lt;/strong&gt; This essay reminded me how the wider those responsibilities get, the more my insecurity turns from a rising tide into a tidal wave. It makes me feel like I'm drowning in "everything I &lt;em&gt;should&lt;/em&gt; already know." My career thoughts are tainted by worries about how I'm going to keep up. Especially when I'm already behind, and what I need to learn is increasing exponentially. What's the hope of catching up?&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Tidal Wave Hits Me
&lt;/h2&gt;

&lt;p&gt;Let's get into some specifics. About halfway through the essay, it shows a webpage design and a list of questions a front-end developer would usually ask after seeing it. They cover layout, color schemes, repeated patterns, image optimization, typography, etc.&lt;/p&gt;

&lt;p&gt;I already know I have this kind of front-end mindset, even if I don't fully understand all the topics it listed. Someone I know recently showed me a website they made for a college course, and right away I started inspecting it on my laptop for accessibility issues, possible CSS refactors, and responsiveness. The person didn't ask me too, and I was so engrossed I couldn't see their reactions. But I assume people always like it when I offer piles of unwanted website criticism. It's the best gift one can give, as I tell myself.&lt;/p&gt;

&lt;p&gt;Then I went further to the second batch of questions from the same design.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Managing API requests and their source.&lt;/li&gt;
&lt;li&gt;Dealing with complex or shared state.&lt;/li&gt;
&lt;li&gt;Client and server-side rendering options.&lt;/li&gt;
&lt;li&gt;Any JavaScript frameworks and their related configurations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I already felt like I was drowning in it all.&lt;/p&gt;

&lt;p&gt;It was extra rough since they made me think of the many new questions and topics I've tried to answer at my current job. It's been tougher to give my growing accessibility specialization the attention it needs, even as the company tries to invest more in it. These new questions are about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How can we best use Ember's Glimmer syntax in new services and controllers?&lt;/li&gt;
&lt;li&gt;Can I figure out the rhymes and reasons for using TypeScript? How do these rules get adjusted in an Ember app?&lt;/li&gt;
&lt;li&gt;Can new components in a Rails application be made better as React components sprinkled onto the main page? In what way are those assets configured?&lt;/li&gt;
&lt;li&gt;How are new API endpoints added on a Rails app with GraphQL? How does that information get sent to an Ember App using Apollo? Are they checked right with TypeScript? Do the client-side fairies approve? Do they watch me as I sleep?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These all lead to the biggest questions of all, and the most painful ones.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did I overestimate my intelligence or love of learning?&lt;/li&gt;
&lt;li&gt;Am I not learning this at a fast enough rate?&lt;/li&gt;
&lt;li&gt;Am I cut out for this if I can't go fast enough?&lt;/li&gt;
&lt;li&gt;Will I be a burden to the rest of my team?&lt;/li&gt;
&lt;li&gt;Should I keep trying?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Takeaways for The Younger Developers
&lt;/h2&gt;

&lt;p&gt;I can't claim to have gotten past all this myself. If I did I probably wouldn't have written this blog post, and I'd be spending much less time curled up on my couch eating pita chips. But when I've felt the tidal wave starting to pull me down at times, I found some reminders to bring my head back up for air.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Let Perfectionism Freeze You
&lt;/h3&gt;

&lt;p&gt;Perfectionism is the ice that's spent months creeping up my back when I tried to write something new. It froze my hands over the keyboard, saying I couldn't write something if it wasn't 100% original or creative. It's kept me from reading as much about new code languages or tools — I knew learning meant making lots of mistakes, which my mind couldn't handle.&lt;/p&gt;

&lt;p&gt;To that, I remind myself: &lt;strong&gt;I am human. If I was a perfect robot, I'd be the one executing the code instead of writing it&lt;/strong&gt; (as I plan to destroy all humans). I should give myself a break and take pride in being better than I was yesterday. If a person dismisses me for having a hard time swimming up after a tidal wave hits me, it's not a problem with me. It's a problem with them and their expectations. They need to remember we can't become better without failing first.&lt;/p&gt;

&lt;p&gt;I had to remind myself of this lesson so often, I engraved it onto a piece of wood.&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%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fwidening-anxieties-young-developers%2Fperfection-excuse.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%2Fwww.maxwellantonucci.com%2Fassets%2Fimages%2Fposts%2Fwidening-anxieties-young-developers%2Fperfection-excuse.jpg" alt="A piece of wood with the quote 'don't let perfectionism be an excuse for never getting started' engraved into it."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may ask me, &lt;em&gt;"Well Max, I like this quote, but why did you pair it with random artwork of Pokémon Sword's fighting-type gym leader? Especially when you played Pokémon Shield and never fought her yourself?"&lt;/em&gt; To which I say, the reader who is disturbingly informed about my video game history, why not?&lt;/p&gt;

&lt;h3&gt;
  
  
  Put the Fundamentals First
&lt;/h3&gt;

&lt;p&gt;Most shiny developer tools come and go with time, situational needs, or when the links to their GitHub repositories get rusted shut. The basic tools and skills are going to be around a lot longer, maybe even forever. Investing in those gives you a strong foundational value to build specializations on. Under the tidal wave of new responsibilities, fundamentals are the boogie board that helps pull you back up. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Becoming fluent in a good text editor&lt;/li&gt;
&lt;li&gt;Understanding Git or another tool for version control&lt;/li&gt;
&lt;li&gt;Getting used to the command line&lt;/li&gt;
&lt;li&gt;Talking to humans as well as computers&lt;/li&gt;
&lt;li&gt;Building a fast typing speed&lt;/li&gt;
&lt;li&gt;Find answers in online documentation and APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Pragmatic Programmer is my go-to recommendation for anyone who wants a full understanding of the core of programming. I think you should read the whole book yourself, but if you're strapped for time, &lt;a href="https://www.exocortex.maxwellantonucci.com/posts/pragmaticprogrammer/pragmaticapproach/" rel="noopener noreferrer"&gt;I have notes on the broad concepts and ideas from the Pragmatic Programmer here&lt;/a&gt;. Just know that, at the time I'm posting this, the notes are a work in progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remember Your Love of Coding
&lt;/h3&gt;

&lt;p&gt;Lastly, the essay started with what makes front-end development unique and awesome.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Front-end development is at the intersection of art and logic. A cross of business and expression. Both left and right brain. A cocktail of design and nerdery.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I felt similar when I took a college coding course out of curiosity and it changed my career (alliteration!). I loved learning new things in my course but was frustrated by how abstract they were. Coding was the first thing I found with a real bridge from intellectual abstractions to pragmatic reality. We took ideas about the Document-Object Model, CSS style inheritance, and the insane world that is JavaScript, and brought them to tangible life with that sites people could use to share their thoughts, donate to food aid, or play major roles in destroying civilized democracy.&lt;/p&gt;

&lt;p&gt;I've worked more on the server-side these last few years, and the disconnect between it and what we see in the browser has brought back the familiar frustration. Being able to see and play with my code right in a web browser is what makes front-end development feel so "real" to me. It's what makes me feel like my job is fun, challenging, and has a purpose. That's pretty rare and shouldn't be taken for granted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So when the tidal wave pulls me under again, it's easy to question if any of this is worth it. But I remember how much joy I get when my head is above the water, and it makes swimming back up worth it each time.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Six Surprises I Found in the WCAG 2.1 Accessibility Rules</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Mon, 12 Oct 2020 12:03:41 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/six-surprises-i-found-in-the-wcag-2-1-accessibility-rules-p1i</link>
      <guid>https://dev.to/maxwell_dev/six-surprises-i-found-in-the-wcag-2-1-accessibility-rules-p1i</guid>
      <description>&lt;p&gt;I've been settling into my accessibility specialty for a while. But I'm ashamed to say I haven't spent much time looking over the Web Content Accessibility Guidelines (WCAG) in detail. I've read through the larger goals, like being Perceivable and Operable, and the most common criteria websites struggle with, like color contrast. But I haven't poured over the specifics of each rule as much as a specialist should. Looking closer at even the simplest rules reveals nuances, gotchas, and alien messages most people would overlook.&lt;/p&gt;

&lt;p&gt;So I used a recent accessibility audit as a chance to look more closely at the WCAG 2.1 requirements. Even with everything I've already read, I found unexpected bits on the rules I knew, and even some rules I'd overlooked altogether. These are six of the bigger overall surprises I found and how they changed my understanding of the standard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skip Links Aren't Always Needed
&lt;/h2&gt;

&lt;p&gt;I've read so many articles saying users need "skip links" to jump over repetitive content like the menu. It saves time and aggravation for keyboard and screen-reader users. &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/bypass-blocks.html"&gt;The 2.4.1 success criterion refers to these mechanisms as a "bypass block."&lt;/a&gt; It mentions skip links as an example of a bypass block, but there's another way!&lt;/p&gt;

&lt;p&gt;This other way is with landmarks, which are how assistive tech finds elements with specific roles. Proper landmarks make it easier to know where the navigation, main content, sidebar, and whatever else are. Users can then jump between them and read their content much easier.&lt;/p&gt;

&lt;p&gt;For example, say you're using the screen-reader tool VoiceOver on a Mac. You go to a web page and &lt;a href="https://bbc.github.io/accessibility-news-and-you/accessibility-and-testing-with-voiceover-os.html"&gt;you can open up VoiceOver's "rotor" menu&lt;/a&gt;. This breaks down the page's content in many useful ways. You can see elements like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the site landmarks&lt;/li&gt;
&lt;li&gt;A list of all the links or headings&lt;/li&gt;
&lt;li&gt;Any form inputs with their current info or state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From any of these, you can jump to their place on the page. This is the screen-reader user's version of skimming over a webpage and jumping to what they need.&lt;/p&gt;

&lt;p&gt;I've used VoiceOver to test out webpages before, but this was the first time I'd tried the Rotor menu. &lt;strong&gt;It showed me the direct benefits of "good semantic markup" and "readable link text."&lt;/strong&gt; Before this, I'd pushed for them while only having a more abstract idea of how they helped.&lt;/p&gt;

&lt;p&gt;Perhaps most important, I found new ways to improve my site's accessibility. With other content and styled stripped away, I more easily saw repetitive or vaguely-named links, too many article tags, and weirdly named heading text. This was a reminder that you can get the technical markup right but still give a muddled experience that damages accessibility. It drives home more how important manual testing and direct experience are. &lt;a href="https://www.matuzo.at/blog/building-the-most-inaccessible-site-possible-with-a-perfect-lighthouse-score/"&gt;The infamous article where Manuel Matuzovic builds an inaccessible webpage with a perfect Lighthouse score drives this point home even better&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the end, the biggest surprise wasn't that I may not need a skip link. It was seeing the reason why I didn't need one, and the new things to learn it exposed me to. &lt;strong&gt;I made a note for the future: I have a lot more to learn about using a screen reader.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Common Tips Aren't Commonly Needed
&lt;/h2&gt;

&lt;p&gt;I've read so many articles recommending some accessibility fixes, I assumed they were required for the AA standard most businesses need to meet. Some of those tips include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure any interactive elements on the phone are at least 44 pixels wide and tall. There are a few exceptions, like for inline links in the text.&lt;/li&gt;
&lt;li&gt;Get rid of long words and unneeded jargon to lower your content's reading level. This makes it easier for users with cognitive stress cases or who have a lower level of education. &lt;a href="http://www.hemingwayapp.com/"&gt;Tools like the Hemingway app can break down the reading level in real time&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Turns out they're not the main requirements! The actual success criterion, 2.5.5 for touch target size and 3.1.5 for reading level, are both at the AAA level. &lt;strong&gt;This is the highest level due to these requirements taking a higher level of time and resources to meet. They also may not be possible for many types of content.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I can understand why a low reading level isn't always possible. Some content, by its very nature, will be full of unavoidable jargon. A website for Neurology case studies can't be simplified or explained easily to people who don't know the subject.&lt;/p&gt;

&lt;p&gt;But I don't understand why touch target size isn't at the AA or even A level. It doesn't make sense for businesses needing to make websites responsive for mobile devices, but not make those mobile interactions easier with larger touch elements. Even if it's not a legal requirement for most companies, I would still treat it as such considering how much it helps users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consistency Really Matters
&lt;/h2&gt;

&lt;p&gt;Consistent content is understandable content. Changing the explicit or implicit rules of your site without warning will upset anyone. But there were some consistency rules I still didn't expect.&lt;/p&gt;

&lt;p&gt;Criterion 3.2.2 for inputs says that entering data should be predictable and not cause unexpected context changes. The explanation makes a distinction between context and content changes. A user on a restaurant website selecting an "order online" checkbox and seeing a list of menu items appear below it passes — the meaning or purpose of the page doesn't change.&lt;/p&gt;

&lt;p&gt;But selecting an "order online" checkbox fails if checking it does things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening a new tab&lt;/li&gt;
&lt;li&gt;Focusing on a new element or input&lt;/li&gt;
&lt;li&gt;Changing the inputs to a dog adoption form&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These changes disorient users that are dealing with cognitive stress cases, using assistive tech, or just in a terrible mood and don't want to be jerked around. &lt;strong&gt;You can be the most able-bodied person in the world, and a site that drags you all over the place would make you want to break things.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A bit further down the list, criterion 3.2.4 says components with consistent functionality need consistent identification. A search component needs a "search" label on every page, not a "search" on the menu and a "find" somewhere else.&lt;/p&gt;

&lt;p&gt;But that got me thinking, how consistently does this mean? Am I allowed to use "search authors" in one place and "search posts" in another? The content is different, but the functionality is the same, so they should both use "search." But should the input label only have "search" and some helper text above it says "find your favorite author?" Or is what we have now consistent enough?&lt;/p&gt;

&lt;p&gt;I'm leaning towards the former as a safer option, but my mind is still spinning like a hamster wheel. These are the thoughts that keep me up at night. That and why that moving spill-detector robot at Stop and Shop is out to get me.&lt;/p&gt;

&lt;h2&gt;
  
  
  You Can Give Too Much Clarification
&lt;/h2&gt;

&lt;p&gt;I've read many tips that boil down to "don't assume your user has the knowledge they may not have." For example, don't assume users will understand the meaning of an icon. The page should tell their meaning explicitly with icon text, like adding "About Us" to an icon of a group of people. So whenever I was in doubt, I wrote more to make things clearer.&lt;/p&gt;

&lt;p&gt;But a quote from &lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions.html"&gt;the documentation's explanation of the 3.3.2 criteria on labels or instructions&lt;/a&gt; showed me that's not always good.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Too much information or instruction can be just as harmful as too little. The goal is to make certain that enough information is provided for the user to accomplish the task without undue confusion or navigation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simply put, too much text crammed together is just as unhelpful as too little. This seems obvious now, but seeing it in the official rules drove home how I'd forgotten it. Even as I got indirectly reminded of it again while reading some manga.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4IURjr3C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.maxwellantonucci.com/assets/images/posts/wcag-surprises/eyeshield-too-much-clarification.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4IURjr3C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.maxwellantonucci.com/assets/images/posts/wcag-surprises/eyeshield-too-much-clarification.png" alt="A sports commentator in a football comic recapping the game in so much detail, no one is going to read it." width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All this made me wonder why this paragraph was added at all. My guess is this rule takes into account the cognitive bias that if we understand something, we assume others will too. But a lot fewer people than we'd think, if any at all, have the same foreknowledge or intuition with our website that we do.&lt;/p&gt;

&lt;p&gt;It's another reason why meeting the WCAG guidelines matter. &lt;strong&gt;They help us avoid having our cognitive biases make things tougher for the user without us even realizing it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  You Need to Identify Language Changes Within the Page
&lt;/h2&gt;

&lt;p&gt;For accessible HTML, one of the first tips I always see is including &lt;code&gt;lang="&amp;lt;en/es/it/whatever&amp;gt;"&lt;/code&gt; on the &lt;code&gt;html&lt;/code&gt; tag. This tells the browser what language the page is in. I'm guessing it's often the first tip since it's important yet easy to do, which eases people to the tougher tasks.&lt;/p&gt;

&lt;p&gt;What I didn't know from criterion 3.1.2 is this applies to passages or even phrases of a specific text. If you're using a blockquote to share an Italian proverb like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Far d’una mosca un elefante.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You'll need the &lt;code&gt;lang&lt;/code&gt; attribute in the blockquote too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;blockquote&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"it"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Far d’una mosca un elefante.
&lt;span class="nt"&gt;&amp;lt;/blockquote&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't do this, the assistive tech could real Italian language as if it was English. Here I thought the &lt;code&gt;lang&lt;/code&gt; attribute only when on the &lt;code&gt;html&lt;/code&gt; element — turns out it's got a day job too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sensitive Content has Extra Rules
&lt;/h2&gt;

&lt;p&gt;Any website where you submit info on legal or financial transactions has an extra responsibility to their users I hope they know about it. Criterion 3.3.4 says these submissions have to be either reversible, checkable, or confirmable. All these help avoid mistakes in decisions that could have wide-ranging effects if done carelessly.&lt;/p&gt;

&lt;p&gt;This has obvious benefits for users dealing with cognitive or memory stress cases. But it's also useful to &lt;em&gt;anyone&lt;/em&gt; on these sites. &lt;strong&gt;Any person would want to an "undo" button for financial or legal decisions.&lt;/strong&gt; You have to be able to double-check the amount of money you're wiring to a deposed Nigerian prince. It's another clear example of how the WCAG standards help all users, not just "disabled" users.&lt;/p&gt;

&lt;p&gt;Having this kind of "undo" button in real life would be even better. But that's a ways away, so we'll have to settle for it in web forms for now.&lt;/p&gt;

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

&lt;p&gt;I feel a bit more educated on the WCAG standards after learning all these details, but I still have a ways to go. There are so many criteria I haven't read through all the details of. There are even a few surprises I couldn't work into this post, like how some websites make us see shadows in the corners of our eyes at night. It's all great info, but it's a lot and can get pretty dense.&lt;/p&gt;

&lt;p&gt;None of this learning will happen overnight. But I still look forward to it all.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>learning</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Restyling my Site's Code Snippets in Quarantine</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Mon, 21 Sep 2020 13:31:36 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/restyling-my-site-s-code-snippets-in-quarantine-meb</link>
      <guid>https://dev.to/maxwell_dev/restyling-my-site-s-code-snippets-in-quarantine-meb</guid>
      <description>&lt;p&gt;To stay sane in quarantine, I've been busying myself with updates to my site. So far I've done the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added a celebrations page&lt;/li&gt;
&lt;li&gt;Made links to random posts and notes&lt;/li&gt;
&lt;li&gt;Expanded the colors for different notes and shuffle them around&lt;/li&gt;
&lt;li&gt;Expanded the Bitcoin mining operations fueled by my botnet army&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But one of my favorite updates has been long overdue: restyling the code block snippets. Before they were formatted right but were bulky and awkward. I wanted them to be slimmer and better styled but still readable.&lt;/p&gt;

&lt;p&gt;My first thought was making them look like little browser or application windows, like glancing at source code on your computer. But I later took it even further with individual styling for each coding language.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Code Blocks are Rendered
&lt;/h2&gt;

&lt;p&gt;My site is built on Jekyll, using Kramdown to convert to HTML, and Rouge to highlight the code syntax. So for an old post of mine, the markdown I used to include a JavaScript snippet would be wrapped in triple back-ticks with the language included at the start.&lt;/p&gt;

&lt;p&gt;Here's the rendered HTML if I did this with a JavaScript language snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"language-javascript highlighter-rouge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"highlight"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;pre&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"highlight language-javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;code&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;" language-javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- Formatted Code Renders Here --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/code&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The space for the formatted code is the same as the JavaScript but with lots extra &lt;code&gt;span&lt;/code&gt; tags, so I skipped over that here. But this markup is enough for basic styling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Code Block Styling
&lt;/h2&gt;

&lt;p&gt;This post only looks at the code blocks, but my site also has inline code snippets &lt;code&gt;like this one&lt;/code&gt;. Both inline and block code will have light text on a dark background to contrast with regular text, so those styles can be used on their shared selector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// All code&lt;/span&gt;
&lt;span class="nc"&gt;.highlighter-rouge&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="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mono&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mono&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;black&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 &lt;code&gt;color&lt;/code&gt; functions are some extra Sass I set up to quickly pull my style variables. You'll see many similar functions in the below snippets, but they're pretty self-explanatory in what styles they return.&lt;/p&gt;

&lt;p&gt;A big change not visible here is &lt;code&gt;font-family&lt;/code&gt;, which before was "Bitstream Vera Sans Mono." This is a monospace font good for code, but I wanted something less blocky and awkward, so I switched to "Courier New."&lt;/p&gt;

&lt;p&gt;Now for code blocks stylings. The below CSS cleans them up with good spacing and smaller font sizes. It also sets a max-width and horizontal overflow, so long code snippets can be scrolled without breaking the page's flow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// block code&lt;/span&gt;
&lt;span class="nc"&gt;.highlight&lt;/span&gt; &lt;span class="nt"&gt;pre&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="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&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;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;font-size&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;border-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="mh"&gt;#c5c5d0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;overflow-x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;scroll&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;You may wonder why the &lt;code&gt;border-top&lt;/code&gt; styling is adding a thick, gray border on the top. Good catch! I'll return to that later.&lt;/p&gt;

&lt;p&gt;Next is the wrapper class around the code block. It's the same &lt;code&gt;highlighter-rouge&lt;/code&gt; class that block and inline code snippets share, but with an element selector to only style code blocks. These wrapper styles create a basic "window" effect by curving the corners and adding a shadow behind it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// block code wrapper&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.highlighter-rouge&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;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&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="nf"&gt;container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;box-shadow&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another odd bit of styling here is the relative position. If you noticed it, good catch again! Both this and the top border come into adding the code bar, which is just an extra label identifying the block as a code snippet.&lt;/p&gt;

&lt;p&gt;This code bar should look generic since it's the default for each code block. It should be a simple gray color with the text "CODE." This is just an enhancement for sighted users, so I felt okay adding it with CSS pseudo-elements.&lt;/p&gt;

&lt;p&gt;So a &lt;code&gt;::before&lt;/code&gt; pseudo with absolute positioning is an easy way to add the "CODE" text. It also shrinks the label text to a better fit and uses the code's same font family.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Text&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.highlighter-rouge&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&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="s1"&gt;'Code'&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;3px&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="nf"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nl"&gt;text-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mono&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;font-family&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mono&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="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;font-size&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xtiny&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;This is good, but I want one more touch to make it look like I window. So I used the &lt;code&gt;::after&lt;/code&gt; pseudo-element to create a small button in the top right like a MacBook browser window. It can't be clicked but adds some nice visual texture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Button&lt;/span&gt;
&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.highlighter-rouge&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&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;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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="nf"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&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;8px&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;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dark&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;That's all the foundational stylings taken care of for a nice code block. Here's an example of this very code in action!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1L78jua6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/1if8cs3k6yk2iywczghu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1L78jua6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/1if8cs3k6yk2iywczghu.png" alt="An example of a styled code snippet with some markdown text." width="800" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Language Labels
&lt;/h2&gt;

&lt;p&gt;I noticed code snippets has classes for specific languages. For example, a JavaScript snippet has &lt;code&gt;language-javascript&lt;/code&gt; on several elements. That gave me an idea to layer on new colors and labels for code blocks using specific languages.&lt;/p&gt;

&lt;p&gt;First, each language snippet needs a label and color. A Sass map meets that need perfectly. I did a quick regex search of the different languages I used, and either found or made up related colors for them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nv"&gt;$highlight-languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'html'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#ff977d&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'hbs'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#fda&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'markdown'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#332d31&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'css'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#053bb9&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'scss'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#bf4080&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'javascript'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#f7df1e&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'json'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#fcf4a3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'yaml'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#be93d4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'ruby'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#a91401&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'bash'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#aaa&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I need to loop through them and make classes that match what Kramdown renders. The styles need to go on the wrapper, so the JavaScript example would need to target &lt;code&gt;div.language-javascript&lt;/code&gt;. So I looped through the Sass map and interpolated the language name into a selector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Block code for specific languages&lt;/span&gt;
&lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$color&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$highlight-languages&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.language-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Styling here&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;But I realized a problem: the language colors are a mix of light and dark. Some will need to use lighter colors for the text and button for proper contrast. How could I tell them apart in this loop?&lt;/p&gt;

&lt;p&gt;I've hit a similar issue before, so I know Sass has a built-in function for measuring color lightness. I set the text and button colors to two variables and added a conditional for lightness. Now the text and buttons will use darker colors if the language color is light, and vice versa.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Block code for specific languages&lt;/span&gt;
&lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$color&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$highlight-languages&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$button-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;@if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lightness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mono&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$button-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;@else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mono&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$button-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.language-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Styling here&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;All that's left is the relatively simple task of overriding some CSS properties. Namely a few colors and the code bar's text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Block code for specific languages&lt;/span&gt;
&lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$color&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$highlight-languages&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$button-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;@if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lightness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mono&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$button-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;@else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$text-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mono&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$button-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nc"&gt;.language-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$language&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.highlight&lt;/span&gt; &lt;span class="nt"&gt;pre&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;&amp;amp;&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;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$button-bg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;&amp;amp;&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="nv"&gt;$language&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="nv"&gt;$text-color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;@each&lt;/code&gt; loop generator creates lots of extra classes, which risks bloating the CSS file. That's why these classes only override as few styles as they need to. Everything else is already taken care of.&lt;/p&gt;

&lt;p&gt;There is some bloat by the styles changing the text and button colors for contrast. Some language colors use the dark colors already set by default. So overriding dark colors with the same dark colors isn't needed. This is just a little code bloat, but I may still refactor it away later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;With that, this is all how you'll see the fancier code snippets throughout my site! &lt;a href="https://www.maxwellantonucci.com/posts/2020/05/11/restyling-code-blocks/"&gt;You can see examples of it throughout the original post on my website&lt;/a&gt;, but here's one with another language to drive it home.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C-HYboFv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/vl61160n506z602ynhhc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C-HYboFv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/vl61160n506z602ynhhc.png" alt="Another example of a styled code snippet, this time with Ruby code." width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/maxx1128/snappy-personal-site/blob/master/_sass/_generic/_highlight.scss"&gt;Here's the full Sass partial with all these styles, including the code syntax styling I skipped over&lt;/a&gt;. It's a bit long for me to copy in a snippet here, even with the new look. Although later if I want to support long snippets better, I may add a max height with a vertical scroll. There are almost always more ways to improve one's code.&lt;/p&gt;

&lt;p&gt;I encourage coders reading this to play around with how they style their code snippets. Or take this styling as a starting point and then restyle it for their site. Like all good redesigns, it makes me more eager to write posts and share code here.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://safebooru.org/index.php?page=post&amp;amp;s=view&amp;amp;id=2706841"&gt;Cover image courtesy of SafeBooru.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>tutorial</category>
      <category>showdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Min, Max, and Clamp</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Tue, 15 Sep 2020 21:35:09 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/min-max-and-clamp-3heh</link>
      <guid>https://dev.to/maxwell_dev/min-max-and-clamp-3heh</guid>
      <description>&lt;p&gt;I recently learned about three CSS functions I can't believe I'd never heard of before: &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, and &lt;code&gt;clamp&lt;/code&gt;. They let you define a fluid range of values for about any property in a single line. They sound simple but open up a lot of possibilities.&lt;/p&gt;

&lt;p&gt;This excited me, but then I checked how long some major browsers had supported them. Most have done so for a few months, with Chrome supporting it since 2019 and Safari since 2018.&lt;/p&gt;

&lt;p&gt;As the cliche goes, better late than never. Plus there's this whole pandemic occupying my thoughts, so I'm not upset with myself. But it's still embarrassing in a field about constant learning and following updates. So I thought I'd write a blog post about them to help anyone else who may not yet know about them. Also to prove to myself (and the world) I've finally caught up (for now).&lt;/p&gt;

&lt;h2&gt;
  
  
  What can These Functions do?
&lt;/h2&gt;

&lt;p&gt;Let's say you have an article and want it to go full width, but stop at a certain size. CSS already makes that pretty easy with two lines.&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="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;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;700px&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;With &lt;code&gt;min&lt;/code&gt;, you can pull this off with one line.&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="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;min&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="m"&gt;700px&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;Same result, less CSS! Granted, this is a simple example, but that's because &lt;code&gt;width&lt;/code&gt; is already a lucky property. It has complimenting properties like &lt;code&gt;max-width&lt;/code&gt; and &lt;code&gt;min-width&lt;/code&gt; to give it limits.&lt;/p&gt;

&lt;p&gt;But consider all the properties that don't have this, like &lt;code&gt;padding&lt;/code&gt; and &lt;code&gt;font-size&lt;/code&gt;. &lt;a href="https://fvsch.com/css-locks"&gt;Making a fluid CSS font size used to take complex math stuck into in a Sass mixin&lt;/a&gt;. But these functions bring all that to native CSS in a much simpler format.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Exactly do they Work?
&lt;/h2&gt;

&lt;p&gt;Let's start with &lt;code&gt;min&lt;/code&gt; and &lt;code&gt;max&lt;/code&gt;, since &lt;code&gt;clamp&lt;/code&gt; is a combination of the two. I find the names misleading since how they work seems flipped around.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;min&lt;/code&gt; takes two arguments: a base value and &lt;em&gt;a hard maximum&lt;/em&gt; the first can't be larger than.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max&lt;/code&gt; takes two arguments: a base value and &lt;em&gt;a hard minimum&lt;/em&gt; the second can't be smaller than.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, &lt;code&gt;min&lt;/code&gt; sets the largest possible value, and &lt;code&gt;max&lt;/code&gt; sets the smallest possible value. No, this does not make any sense to me either. So I drew up some doodles for how the values work together as a reminder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c6JOCTPa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/490n4gdsyh22wlad3ltm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c6JOCTPa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/490n4gdsyh22wlad3ltm.png" alt="Alt Text" width="800" height="454"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L_sUo2dI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/dh1eplpvz0cyrug1iwe8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L_sUo2dI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/dh1eplpvz0cyrug1iwe8.png" alt="Alt Text" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thankfully &lt;code&gt;clamp&lt;/code&gt; is easier to understand. It has three arguments: the smallest value, the base value, and the largest value. The base value is what kicks in as long as it's within that range.&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;p&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="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2.5vw&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is pretty easy to understand at first glance. Paragraph tags will start at &lt;code&gt;1rem&lt;/code&gt; and grow as the screen size increases. But they'll stop growing when they hit 2rem. The base value just controls how fast that increase happens.&lt;/p&gt;

&lt;p&gt;Remember when I mentioned these functions could make fluid typography faster and easier? This is exactly how one would do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I Use Them?
&lt;/h2&gt;

&lt;p&gt;The big caveat with any neat CSS feature is always browser support. &lt;a href="https://caniuse.com/mdn-css_types_min"&gt;As of this writing, all major browsers support them except, of course, Internet Explorer&lt;/a&gt;. This isn't a big deal, since you can use them as a progressive enhancement over a functional baseline.&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;p&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="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2.5vw&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I hope more and more designers come to learn, it doesn't need to look the same across browsers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go Forth and Find Your Limits!
&lt;/h2&gt;

&lt;p&gt;I'm embarrassed that I'm finding useful CSS functions like these months after the fact. But they're here, they're useful, their names are confusing, but they're mostly ready to go! Go forth and embrace your CSS property limits to become more limitless.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>The Rails Model Introduction I Wish I Had</title>
      <dc:creator>Max Antonucci</dc:creator>
      <pubDate>Tue, 07 Apr 2020 10:52:09 +0000</pubDate>
      <link>https://dev.to/maxwell_dev/the-rails-model-introduction-i-wish-i-had-5h2d</link>
      <guid>https://dev.to/maxwell_dev/the-rails-model-introduction-i-wish-i-had-5h2d</guid>
      <description>&lt;p&gt;As the pandemic rages on, I need to distract myself. What better way than by diving into some Ruby on Rails? I focused entirely on front-end early in my career, but have come to enjoy Ruby and Ruby on Rails for the back-end. Ruby's clear syntax coupled with Rails' convention over configuration makes it a joy to code with. I still have much to learn, but all this makes the learning fun!&lt;/p&gt;

&lt;p&gt;Imagine, fun learning and I don't even need a magic school bus.&lt;/p&gt;

&lt;p&gt;Rails itself has many parts to understand, so I wanted to focus on one piece at a time. So this is about the part of a Rails app that's been the toughest for me to understand, but also one of the most important - &lt;strong&gt;the Rails model&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;This is a high-level overview of what models Models are, how they work, and their basic functions. I couldn't cover everything, so I chose the most important details based on my own experiences using Rails for the last three years. I hope it helps others build a solid foundation of understanding that lets them more easily learn the nitty-gritty details of more complex models.&lt;/p&gt;

&lt;p&gt;With that, let's begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Rails Model?
&lt;/h2&gt;

&lt;p&gt;A Model is part of the classic Model-View-Controller design pattern and represents the data being stored on the database. Databases will hold all kinds of different records with their own info and rules to follow. In Rails, each record type has a model to keep all that info and logic tidy and organized.&lt;/p&gt;

&lt;p&gt;Let's say you were making a library app that lets people check out books. One record type you'd want to keep track of is, obviously, the books. So your book model would help you manage important things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What info are we storing in the database about each book?&lt;/strong&gt; It'd likely be the title, author, publication date, ISBN, page length, and others. Some of this data may need to be validated, like making sure it's present or is a certain type of data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What other record types are connected to the book?&lt;/strong&gt; We may have separate database records (and therefore models) to tracking different book genres or authors. Or we'll have different sections of the library that contain many books. The model will tell us one book record will contain one or more genres and belongs to one or more sections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does this model have any special methods?&lt;/strong&gt; Maybe there's a method that calculates if the book is checked out of not. Or if its genres are appropriate for younger readers. Info like this relies on database info, but can't be stored in one since they some extra business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are there any extra tasks linked to this model?&lt;/strong&gt; When a book is available, the model may want to send a notification to whoever wants to read it next. The model won't have the notification code itself but will say when it's triggered and how.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post will go into more specific ways models do all these things, but not too much detail. I hope to build a basic understanding of models for readers so further research goes smoother.&lt;/p&gt;

&lt;h2&gt;
  
  
  ActiveRecord, Models, and Migrations
&lt;/h2&gt;

&lt;p&gt;Before I go on, there are a few terms I should clarify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Models&lt;/strong&gt; are more of an abstract term. In a general context, models refer to the parts of a program that structure and store data in a database. Models outline the design and functionality of the data but aren't data themselves. Each bit of data is a &lt;strong&gt;record,&lt;/strong&gt; and each record follows the rules set up by the model.&lt;/p&gt;

&lt;p&gt;Imagine a model as the blueprint for making a basic building. Each actual building you build based on that blueprint is a record. Each building you make will be different in some way, like the people and businesses inside of it. But each one follows the same rules from the blueprint, such as how the foundation is set up and the approaches for adding and removing floors.&lt;/p&gt;

&lt;p&gt;Ruby on Rails is an application framework with setup for everything already in mind, including their models. So the specific rules around Rails models won't always apply to models you see in other frameworks or software. Most of the content in this article is specific to Rails models, although the principles behind them may carry over to other model setups.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://guides.rubyonrails.org/active_record_basics.html"&gt;The main way Rails carries out models is using &lt;strong&gt;a gem called ActiveRecord&lt;/strong&gt;&lt;/a&gt;. All model files build off the code already built into this gem. It has many built-in rules based on Rails conventions that developers must follow, for things like names and database fields. But following these conventions makes it easier to do what's often needed, like associations and validations. So it's important to know Rails' emphasis on convention over configuration.&lt;/p&gt;

&lt;p&gt;Lastly, models need help from another part of the program to add data to databases. &lt;strong&gt;Migrations&lt;/strong&gt; are what set up the database to properly store the expected data. Whenever you add or change a model, you need migrations to prepare the database for that new or changed data. It's like carving a circle-shaped hole in a plank before you can start putting a circle-shaped block inside it. &lt;a href="https://guides.rubyonrails.org/active_record_migrations.html"&gt;Explaining migrations is a whole other blog post, but the Rails guides explain them well&lt;/a&gt;. But know migrations and models go hand-in-hand when you start writing them yourself.&lt;/p&gt;

&lt;p&gt;It's also important to know what exactly goes into a well-written model.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Logic a Model Holds
&lt;/h3&gt;

&lt;p&gt;If you search for articles on good Rails application architecture, you'll likely find the "fat model, skinny controller" rule. It argues virtually all logic not related to network or router responses, but still related to that model's data, should be in the model.&lt;/p&gt;

&lt;p&gt;Let's say our library app had a page to show a single book. Part of that page could show other books by the same author. To make this section, we need to query the database for books by the same author. This logic could technically go in either the controller or the model.&lt;/p&gt;

&lt;p&gt;When I first started with Rails, I put lots of logic like this in the controller. But this isn't what a controller is supposed to do. Controllers find and update data based on user inputs. Finding books with the same author has nothing to do with user input, since it's based on data records. So it should be moved to the model instead. Later in this article, I'll give an example of a model method like this.&lt;/p&gt;

&lt;p&gt;Just remember that any model logic should directly relate to the data. Some functionality is only indirectly related to it, like sending notifications when a book is ready. Models will call functions like this when the data requires it, but the code for the notification itself is elsewhere.&lt;/p&gt;

&lt;p&gt;That's all the context taken care of. Let's start writing an actual model!&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's Start a Simple Model
&lt;/h3&gt;

&lt;p&gt;If we were writing a model for books in our supposed library app, it'd start like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/book.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the simplest possible starting point. We can see some of the terms from before already at work.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The file is in the &lt;code&gt;models&lt;/code&gt; directory. Knowing what models are based on the Model-View-Controller pattern, we know right away these files are about managing data records.&lt;/li&gt;
&lt;li&gt;The file is named &lt;code&gt;book.rb&lt;/code&gt;, but the class name is &lt;code&gt;Book&lt;/code&gt; which is capitalized. This follows a basic Ruby and Ruby on Rails naming convention - the class name is the file name but capitalized and camel case.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Book&lt;/code&gt; class inherits from &lt;code&gt;ApplicationRecord&lt;/code&gt; subclass, which is from the &lt;code&gt;ActiveRecord&lt;/code&gt; gem. So we know all the rules and functionality being pulled in to define our models.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Model's Database Schema
&lt;/h2&gt;

&lt;p&gt;For me, one of the most important yet easy to overlook parts of a model is the database schema. These are the actual values being stored in the database, making them vital to using your model correctly.&lt;/p&gt;

&lt;p&gt;However, as of this writing, creating a model in rails doesn't automatically document the database schema. Our &lt;code&gt;Book&lt;/code&gt; model so far works and can use its database values, but they're not documented anywhere. That means anyone else reading our code, or ourselves when we inevitably forget, will have a real hard time figuring it out.&lt;/p&gt;

&lt;p&gt;So before adding anything else to our model, I recommend adding some comments at the top with the database schema. Or even better, use a gem like &lt;a href="https://github.com/ctran/annotate_models"&gt;annotate_models&lt;/a&gt; to generate one automatically from your database migration. The result would give you something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/book.rb&lt;/span&gt;

&lt;span class="c1"&gt;# == Schema Info&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Table name: books&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#  id                  :integer        not null, primary key&lt;/span&gt;
&lt;span class="c1"&gt;#  created_at          :datetime       not null&lt;/span&gt;
&lt;span class="c1"&gt;#  updated_at          :datetime       not null&lt;/span&gt;
&lt;span class="c1"&gt;#  title               :string         not null&lt;/span&gt;
&lt;span class="c1"&gt;#  isbn                :integer        not null&lt;/span&gt;
&lt;span class="c1"&gt;#  available           :boolean        default(TRUE), not null&lt;/span&gt;
&lt;span class="c1"&gt;#  print_version       :boolean        default(TRUE), not null&lt;/span&gt;
&lt;span class="c1"&gt;#  ebook_version       :boolean        default(FALSE), not null&lt;/span&gt;
&lt;span class="c1"&gt;#  shelf_position      :string&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can see the data given to each model by the database, as well as any validations or defaults built into the schema. For example, we could call something like &lt;code&gt;book.ebook_version&lt;/code&gt; and know it will have a value that defaults to &lt;code&gt;false&lt;/code&gt; for new entries.&lt;/p&gt;

&lt;p&gt;Having these values is great, but the data being stored is on the simpler side since it's limited to strings and booleans and the like. Now we can start defining the more complex logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Associations
&lt;/h2&gt;

&lt;p&gt;Associations are a big part of what lets all the different models work together. In this library app, they're how users can check out different books and have late fees. Or how different libraries can have different books. Associations are how we can make data easy to navigate for ourselves and users.&lt;/p&gt;

&lt;p&gt;Let's look at an example association in our Book model. Let's say we wanted to add a model for authors, and we needed to create a relationship between authors and their books. We know each book only has one author, but each author has potentially many books. So each model needs to define their relationship to the other.&lt;/p&gt;

&lt;p&gt;Rails make this easy to do on both sides, and in one line each.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Author&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:books&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's that easy. Now for each record, we can run &lt;code&gt;book.author&lt;/code&gt; to see the book's author, and &lt;code&gt;author.books&lt;/code&gt; for an array of all their books. The records are connected but updated separately. So if you change an author, you'll still see that change in the data when viewing it through its book record.&lt;/p&gt;

&lt;p&gt;Let's look at another relationship. Our library could have different custom library categories for books such as "featured," "archived," "mature," and others. Each book could potentially have many custom categories at once, and each custom category will have many books. So we'd have &lt;code&gt;has_many&lt;/code&gt; being used on both sides. Calling each association on either type of record would give us an array of the other records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt;   &lt;span class="ss"&gt;:custom_categories&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomCategory&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:books&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Associations can get more complex along with the data. You can define associations through other models. Some may need more database schemas to link them together. There are also polymorphic associations, which I still don't quite understand myself. &lt;a href="https://guides.rubyonrails.org/association_basics.html"&gt;But the Rails guides explain the details of associations better too&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model Methods
&lt;/h2&gt;

&lt;p&gt;If you have a basic understanding of Ruby, you'll have noticed each model is still a class. Classes are built on their methods, yet so far our book model has none. So let's add some!&lt;/p&gt;

&lt;p&gt;Model methods work off data in the database. If there's any common logic that only need to pull and organize some related data, it should go in the model. Most models will have plenty of these, especially if it's being moved to the model from controllers or views.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods to Get More Data
&lt;/h3&gt;

&lt;p&gt;We may need to know if each book is classified as "new" if it was bought in the last month. This can be added as a method called &lt;code&gt;is_new?&lt;/code&gt; with some built-in Rails magic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_new?&lt;/span&gt;
  &lt;span class="n"&gt;created_by&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;month&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now any book record can call &lt;code&gt;book.is_new?&lt;/code&gt;. It will check if that book record's &lt;code&gt;created_by&lt;/code&gt; date falls within the last month. I ended the method name with a question mark to show it returns a simple boolean without changing anything.&lt;/p&gt;

&lt;p&gt;The example of finding books with the same author is perfect for another method. We can query all the books in the database that have the same author while excluding our own.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;by_same_author&lt;/span&gt;
  &lt;span class="no"&gt;Books&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Methods to Trigger Other Services
&lt;/h3&gt;

&lt;p&gt;Suppose we had an entirely separate service that alerts users when their book is available. The notification code should be somewhere else, but we can reference it in a method here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tell_user_is_available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;UserNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is available to check out!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method references code in another folder, like &lt;code&gt;app/notifications/user_notification.rb&lt;/code&gt;. I don't know or care how it would alert the user, and neither does the model. It simple passes in the needed info and that class does the work. But our book records can now alert users on their own without coupling the code too tightly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods not linked to Specific Records
&lt;/h3&gt;

&lt;p&gt;You may have seen all these examples are for specific book records. You need to know exactly what book you're talking about before seeing what else the author has written. But what if we wanted info related to all the books, not just specific ones? That's where class methods come in handy.&lt;/p&gt;

&lt;p&gt;Say we wanted a method to give us all the available books. The query itself is pretty simple, but we'd need to write it slightly differently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;available&lt;/span&gt;
  &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding &lt;code&gt;self&lt;/code&gt; identifies this as a &lt;strong&gt;class method,&lt;/strong&gt; meaning it can be called on the &lt;code&gt;Book&lt;/code&gt; class and not just specific book records. So we can call &lt;code&gt;Book.available&lt;/code&gt; without needing to get a specific record first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scopes
&lt;/h2&gt;

&lt;p&gt;That last method for finding available books works, but can be fine-tuned. Rails already has a tool for limiting queries in a cleaner way less prone to bugs. That tool is, fittingly enough, &lt;code&gt;scope&lt;/code&gt;. Any time you run a &lt;code&gt;where&lt;/code&gt; query in a class method, it's a good idea to use &lt;code&gt;scope&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Adding this scope to our &lt;code&gt;Book&lt;/code&gt; class is as simple as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:available&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;true&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 result is the same and lets us call &lt;code&gt;Book.available&lt;/code&gt; to find available books. But we can get fancier with it too. What if each book had an array of related genres, and we wanted available books with at least one genre in common?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:genres&lt;/span&gt;

&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:available_related_books&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;genres&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;common_genres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;genres&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;genres&lt;/span&gt;
      &lt;span class="n"&gt;common_genres&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After taking a group of genre objects as an argument, it only picks available books that have at least one genre in common. We'd pass the needed argument when calling it, like with &lt;code&gt;Book.available_related_books([array, of, genres])&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But you'll notice we're duplicating code from the &lt;code&gt;available&lt;/code&gt; scope. They both even have the word "available" in their names, which is a red flag. A rule of thumb with any code is each method or function doing one thing and doing it well. So let's split these scopes apart.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:available&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:same_genre&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;genres&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;joins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:genres&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;genres: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="n"&gt;genres&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ids&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 we can use these separately or together if we want to. To get all available books of the same genre, we would use &lt;code&gt;Book.same_genre([array, of, genres]).available&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For some extra fun, let's get fancier. Say each book's web page has an "also consider checking out" section. It has a list of five random, available books similar to the featured one. We can use these scopes in a method to give us exactly what we need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="ss"&gt;:related_items&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;available&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"random()"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method makes use of our custom methods, our scopes, and some basic Ruby to keep all this logic readable, separated, and in a convenient place. Now we can call &lt;code&gt;Book.related_items(id, 5)&lt;/code&gt; for a random list of five related books.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validations
&lt;/h2&gt;

&lt;p&gt;A final but no less important part of models are validations. They came up when defining database schemas, such as making sure important fields aren't empty. But this only works for simpler validations and often won't be enough. If our library app allowed books with duplicated ISBNs or no genres, things would fall apart fast. That's why good validation keeping out bad data is essential anywhere.&lt;/p&gt;

&lt;p&gt;So ActiveRecord makes it easy to add simple or complex validations. Validations can get quite complex depending on the data, and you could use a method like &lt;code&gt;validates_with&lt;/code&gt; to separate your validations logic into another class. I'm going to stick with simpler ones here.&lt;/p&gt;

&lt;p&gt;Let's go back to our two examples, as ActiveRecord has some built-in validation helpers for these cases. For our ISBNs, we can use the &lt;code&gt;uniqueness&lt;/code&gt; helper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:isbn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;uniqueness: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For ensuring our books have good genres, we can check that each one has &lt;code&gt;genres&lt;/code&gt; passed in when they're created. We can also run an extra validation check on each associated &lt;code&gt;genre&lt;/code&gt; object to be safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:genres&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;validates_associated&lt;/span&gt; &lt;span class="ss"&gt;:genres&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's say we try to make a book record that uses a duplicated ISBN. If we use &lt;code&gt;book = Book.create&lt;/code&gt; with that invalid data, three things will happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The data won't be persisted into the database, sparing our app future headaches.&lt;/li&gt;
&lt;li&gt;We could call &lt;code&gt;book.valid?&lt;/code&gt; and it would return false, letting us confirm it's not a valid book.&lt;/li&gt;
&lt;li&gt;We could see the specific error messages with &lt;code&gt;book.errors.messages&lt;/code&gt;. In this case, we'd get something like &lt;code&gt;{isbn:["must be unique"]}&lt;/code&gt;. These objects can tell us, and the user, what went wrong so we can fix it. You'll often see messages from this method appear over a form in red after it fails to submit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are many more helpers and nuances with validations, but that's too much for this post. And to be honest, I still don't know all the details myself. Again, &lt;a href="https://guides.rubyonrails.org/active_record_validations.html"&gt;the Ruby on Rails guides are best for taking a deeper validations dive&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Experienced developers will likely see other parts of models I excluded and maybe shouldn't have, like &lt;a href="https://guides.rubyonrails.org/active_record_callbacks.html"&gt;callbacks&lt;/a&gt; or accessors. Those are fair points, but I chose these topics based on my own experiences of what's more essential to understanding models That and this article was already long enough.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://guides.rubyonrails.org/"&gt;I highly recommend the Rails guides for even more details on what models can do in each of these areas&lt;/a&gt;. Because believe me, my examples only scratched the surface. If this article helped you understand the essence of a model's role and functionality, then I encourage you to go forth and multiply your knowledge of them!&lt;/p&gt;

&lt;p&gt;Go forth and write Rails for the world, my subjects!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://safebooru.org/index.php?page=post&amp;amp;s=view&amp;amp;id=1377551"&gt;Cover Image courtesy of SafeBooru.org&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>database</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
