<?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: Thomas C. Haflich</title>
    <description>The latest articles on DEV Community by Thomas C. Haflich (@tchaflich).</description>
    <link>https://dev.to/tchaflich</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%2F175478%2Fe6218e1c-91df-4273-be19-bf6407098a23.png</url>
      <title>DEV Community: Thomas C. Haflich</title>
      <link>https://dev.to/tchaflich</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tchaflich"/>
    <language>en</language>
    <item>
      <title>Alignment in CSS: margin &amp; padding</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Fri, 29 Jul 2022 00:47:20 +0000</pubDate>
      <link>https://dev.to/tchaflich/alignment-in-css-margin-padding-2cn2</link>
      <guid>https://dev.to/tchaflich/alignment-in-css-margin-padding-2cn2</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Annie Spratt on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First, take a look at this tweet:&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;That's basically what we're doing with this whole series!&lt;/p&gt;

&lt;h2&gt;
  
  
  What are margins? What is padding? A quick review of the box model
&lt;/h2&gt;

&lt;p&gt;CSS is basically rectangles inside other rectangles.&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%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F7%2F7a%2FBoxmodell-detail.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%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F7%2F7a%2FBoxmodell-detail.png" alt="CSS box model diagram. From outside in: Margin, border, padding, content."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sourced from &lt;a href="https://commons.wikimedia.org/wiki/File:Boxmodell-detail.png" rel="noopener noreferrer"&gt;Wikimedia Commons&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Margins&lt;/strong&gt; define space around the element, &lt;strong&gt;padding&lt;/strong&gt; creates space inside the element. They are separated by the &lt;strong&gt;border&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More reading on the box model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model#What_is_the_CSS_box_model" rel="noopener noreferrer"&gt;MDN - The box model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/44453391/what-is-the-difference-between-border-box-and-content-box-in-css" rel="noopener noreferrer"&gt;StackOverflow - What is the difference between border-box and content-box in CSS?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Percent-based margin &amp;amp; padding
&lt;/h2&gt;

&lt;p&gt;Setting a percentage for left/right properties is easy enough:&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="cm"&gt;/* The HORIZONTAL (left/right) properties */&lt;/span&gt;
&lt;span class="nn"&gt;#some-element&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;5%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does basically what you would expect. &lt;/p&gt;

&lt;p&gt;But setting a percentage &lt;em&gt;height&lt;/em&gt; is more complicated. Take a moment to guess what happens when you do 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="cm"&gt;/* The VERTICAL (top/bottom) properties */&lt;/span&gt;
&lt;span class="nn"&gt;#some-element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5%&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="m"&gt;5%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://i.giphy.com/media/eChf44Gyj2VrO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/eChf44Gyj2VrO/giphy.gif" alt="Animated GIF of a bearded man doing complex mental mathematics. The camera zooms in on his eyes for dramatic effect."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The margin and padding properties accept various formats, but &lt;a href="https://drafts.csswg.org/css-box-3/#propdef-margin" rel="noopener noreferrer"&gt;when a percent is specified, they use the width of the element&lt;/a&gt;. You can use this to make a &lt;a href="https://dev.to/tchaflich/a-width-responsive-perfect-square-in-pure-css-3dao"&gt;responsive perfect square&lt;/a&gt;, which is cool, but it's pretty annoying when all you want to do is vertically center something.&lt;/p&gt;

&lt;p&gt;An interactive example:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;💡 When specifying margin or padding in percent, the &lt;em&gt;logical width&lt;/em&gt; is always used, even if the property specified was vertical (top or bottom).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Negative margins
&lt;/h2&gt;

&lt;p&gt;If a positive margin is saying to other elements, "give me &lt;em&gt;this&lt;/em&gt; much personal space", a negative margin is saying "come this far &lt;em&gt;into&lt;/em&gt; my personal space".&lt;/p&gt;

&lt;p&gt;Let's take a look at some examples:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;💡 There's no such thing as negative padding.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For more examples on using negative margins to align things vertically, check out the &lt;a href="https://dev.to/tchaflich/alignment-in-css-absolute-positioning-2dhp"&gt;Absolute Positioning&lt;/a&gt; part of the series.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automatic margins
&lt;/h2&gt;

&lt;p&gt;If you've looked for ways to center something in CSS, it's likely that you've seen &lt;code&gt;margin: 0 auto&lt;/code&gt; before.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 This type of declaration ( &lt;code&gt;0 auto&lt;/code&gt; ) is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties#Margin_and_Padding_Properties" rel="noopener noreferrer"&gt;CSS shorthand&lt;/a&gt;. It sets the top &amp;amp; bottom margins to zero, and the left &amp;amp; right margins to auto.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;The idea is that in this case, the &lt;code&gt;auto&lt;/code&gt; property is calculated as "fill remaining space". If the margin is set to auto on both the left &lt;em&gt;and&lt;/em&gt; the right, it will divide the remaining space evenly. This effectively centers the element.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🚨 Auto-margins &lt;strong&gt;do not work vertically&lt;/strong&gt;. There is no "remaining height" in this case, since page height can always expand infinitely. When a remaining space cannot be calculated, the auto-margin is evaluated as &lt;code&gt;0&lt;/code&gt; (no margin). Automatic margins also only apply to block elements.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>Alignment in CSS: Absolute positioning</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Fri, 29 Jul 2022 00:33:38 +0000</pubDate>
      <link>https://dev.to/tchaflich/alignment-in-css-absolute-positioning-2dhp</link>
      <guid>https://dev.to/tchaflich/alignment-in-css-absolute-positioning-2dhp</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Daniel McCullough.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Welcome back to alignment in CSS! Today's post is fake-sponsored by this gif:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/13XW2MJE0XCoM0/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/13XW2MJE0XCoM0/giphy.gif" alt='The most popular google search result for "css gif"; it shows a popular cartoon character destroying a pair of blinds by adjusting them repeatedly.' width="346" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By the way, it's pronounced "gif".&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  More with absolute positioning and translations
&lt;/h2&gt;

&lt;p&gt;Have you ever tried to use a percent for &lt;code&gt;left&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt;, or &lt;code&gt;bottom&lt;/code&gt; for positioning something absolutely? You'd think that something like &lt;code&gt;top: 50%&lt;/code&gt; would work to vertically center an element...&lt;/p&gt;

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

&lt;p&gt;Normally the &lt;strong&gt;&lt;em&gt;top&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;of the child&lt;/em&gt; is flush with with &lt;strong&gt;&lt;em&gt;top&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;of the parent&lt;/em&gt;, so bumping the "baseline" down aligns the &lt;strong&gt;&lt;em&gt;top&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;of the child&lt;/em&gt; with the &lt;strong&gt;&lt;em&gt;middle&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;of the parent&lt;/em&gt;, rather than truly centering it.&lt;/p&gt;

&lt;p&gt;In order for something to be aligned, we want the &lt;strong&gt;&lt;em&gt;middle&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;of the parent&lt;/em&gt; and the &lt;strong&gt;&lt;em&gt;middle&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;of the child&lt;/em&gt; to be along the same axis.&lt;/p&gt;

&lt;p&gt;So how do we get the child element's middle to where its top currently is?&lt;/p&gt;

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

&lt;p&gt;If you happen to know the height of your inner element, and your element is positioned outside of the document flow (such as &lt;code&gt;position: absolute; top: 50%;&lt;/code&gt;) you can almost certainly &lt;a href="https://stackoverflow.com/a/11499018"&gt;use a negative margin&lt;/a&gt; to bump it up:&lt;/p&gt;

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

&lt;p&gt;The formula for this is that you want &lt;code&gt;margin-top = -0.5 * $height&lt;/code&gt;. That is &lt;strong&gt;half the height of the inner container&lt;/strong&gt;, with the margin being negative to push it in the "up" direction instead of what it would normally do (which is "down").&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Why can't I use a &lt;code&gt;margin-top: -50%&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Because CSS is cruel. The &lt;a href="https://drafts.csswg.org/css-box-3/#propdef-margin"&gt;margin and padding properties&lt;/a&gt; accept various formats, but when a percent is specified, they use the &lt;em&gt;width&lt;/em&gt; of the element. You can use this to make a &lt;a href="https://dev.to/tchaflich/a-width-responsive-perfect-square-in-pure-css-3dao"&gt;responsive perfect square&lt;/a&gt;, which is cool, but it's pretty annoying when all you want to do is vertically center something.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you don't know what your height is, you can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform"&gt;CSS transforms&lt;/a&gt;, particularly &lt;code&gt;translateY&lt;/code&gt;. This one doesn't even require any math, you just apply &lt;code&gt;transform: translateY(-50%)&lt;/code&gt; to the inner container.&lt;/p&gt;

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

&lt;p&gt;This works just as well, and since it's a 2d transform it's &lt;a href="https://caniuse.com/#feat=transforms2d"&gt;pretty well supported&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>JavaScript WTFs explained - Number type and floating point</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Thu, 28 Jul 2022 23:44:59 +0000</pubDate>
      <link>https://dev.to/tchaflich/javascript-wtfs-explained-number-type-and-floating-point-2130</link>
      <guid>https://dev.to/tchaflich/javascript-wtfs-explained-number-type-and-floating-point-2130</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover Photo by &lt;a href="https://unsplash.com/@tonny_tran?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Tony Tran&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--brXOzK2---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2r1f3n0kggl717hto2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--brXOzK2---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2r1f3n0kggl717hto2p.png" alt="A screenshot of the Firefox developer console with several confusing results output - this will be the subject of today's discussion" width="196" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source:&lt;/p&gt;


&lt;div class="ltag__reddit--container"&gt;
  &lt;div class="ltag__reddit--title-container"&gt;
    
      &lt;div class="ltag__reddit--title"&gt;
        &lt;h1&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCqI7Yj---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/reddit-icon-c6851eed10026b5707e2e8c814b5bbcbb4823de68d5b611a6f4b99c8beed6f05.svg" alt="Reddit Logo"&gt;
          &lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/w8m9em/just_started_learning_javascript_and_have_a_lot/" rel="noopener noreferrer"&gt;
            Just started learning JavaScript and have a lot of questions that begin with “Why/How tf”
          &lt;/a&gt;
        &lt;/h1&gt;
        &lt;div class="ltag__reddit--post-metadata"&gt;
          &lt;span&gt;Jul 26 '22&lt;/span&gt;
          &lt;span&gt;Author: ievisheleo&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__reddit--body"&gt;
    &lt;p&gt;
        &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nICAJdRC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://b.thumbs.redditmedia.com/cS7eCuMAf-PZSInDi9SUlZ_vLmxVvOGRa0Hptp38YQI.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nICAJdRC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://b.thumbs.redditmedia.com/cS7eCuMAf-PZSInDi9SUlZ_vLmxVvOGRa0Hptp38YQI.jpg" alt="Just started learning JavaScript and have a lot of questions that begin with “Why/How tf”"&gt;&lt;/a&gt;
    &lt;/p&gt;
  &lt;/div&gt;
  &lt;div class="ltag__reddit--btn--container"&gt;
    
      &lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/w8m9em/just_started_learning_javascript_and_have_a_lot/" rel="noopener noreferrer"&gt;See Full Post&lt;/a&gt;
    
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  About binary and numeric representation
&lt;/h2&gt;

&lt;p&gt;Computers don't have ten fingers to count on - they use a system called binary, which functions very similarly to our base-ten number system, but with only two digits (0 and 1) instead of ten (0 through 9).&lt;/p&gt;

&lt;p&gt;Some resources if you need a quick lesson on how this works:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Trevor Storr - How to count in binary&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Khan Academy - Adding in binary&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Low Level JavaScript - Floating point explained&lt;/em&gt;&lt;/p&gt;

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




&lt;h2&gt;
  
  
  &lt;code&gt;9999999999999999&lt;/code&gt; evaluates to &lt;code&gt;10000000000000000&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is not specific to JavaScript by any means! It's another consequence of how computers handle numbers and math.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;About how computers represent numbers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you think of a big number, your brain has an advantage over computers. You don't need to reserve a certain amount of space in order to think about that number; you can be as precise or imprecise as you want, without your brain crashing. Probably. &lt;/p&gt;

&lt;p&gt;In order for a &lt;em&gt;computer&lt;/em&gt; to think about a number, it first needs to know roughly how large and how precise it is, so it can reserve the right amount of space for it in its memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because of how computers represent numbers, if you have a number with a lot of "information" in it (very large, very precise, or both), the computer might run out of "space" for that number. In some circumstances, this just throws an error (the computer gives up). In JavaScript &lt;strong&gt;and many other languages&lt;/strong&gt;, the number is reduced to a version that has less "information" to store.&lt;/p&gt;

&lt;p&gt;JavaScript has a maximum number, over which it cannot guarantee precision for integers: &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt;. You can get a value for this in the console:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; Number.MAX_SAFE_INTEGER
&amp;gt; 9007199254740991 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And as you can see, our value of &lt;code&gt;9999999999999999&lt;/code&gt; is over that threshold, so it will not be guaranteed to be accurate.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;0.5 + 0.1 === 0.6&lt;/code&gt;, but &lt;code&gt;0.1 + 0.2 !== 0.3&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In JavaScript, when you add &lt;code&gt;0.1&lt;/code&gt; and &lt;code&gt;0.2&lt;/code&gt; together in the console, here's what you get:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; 0.30000000000000004
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Almost - but not &lt;em&gt;exactly&lt;/em&gt; - 0.3.&lt;/p&gt;

&lt;p&gt;This is another consequence of how computers handle numbers, and is again &lt;strong&gt;not specific to JavaScript&lt;/strong&gt; - in fact, &lt;em&gt;any&lt;/em&gt; language that uses floating point decimals will have this problem.&lt;/p&gt;

&lt;p&gt;When you tell a computer about a base-10 number, like &lt;code&gt;0.5&lt;/code&gt; (one half), it internally is thinking about this number in binary as &lt;code&gt;0.1&lt;/code&gt; (&lt;strong&gt;not&lt;/strong&gt; one-tenth, since in binary that's the &lt;em&gt;"halves place"&lt;/em&gt; and not the &lt;em&gt;"tenths place"&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;Let's convert all these numbers to binary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0.1&lt;/code&gt; in base ten =&amp;gt; &lt;code&gt;0.00011[0011...]&lt;/code&gt; in binary&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0.2&lt;/code&gt; in base ten =&amp;gt; &lt;code&gt;0.00110[0110...]&lt;/code&gt; in binary&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0.3&lt;/code&gt; in base ten =&amp;gt; &lt;code&gt;0.01001[1001...]&lt;/code&gt; in binary&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0.5&lt;/code&gt; in base ten =&amp;gt; &lt;code&gt;0.1&lt;/code&gt; in binary&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0.6&lt;/code&gt; in base ten =&amp;gt; &lt;code&gt;0.10011[0011...]&lt;/code&gt; in binary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may notice that a lot of those contain &lt;strong&gt;infinitely repeating decimals&lt;/strong&gt;. Computers aren't so great with infinite things, so they just write down however much they can, and stop when they run out of space to store the number.&lt;/p&gt;

&lt;p&gt;These infinitely repeating decimals are the core of this particular issue.&lt;/p&gt;

&lt;p&gt;Let's look at adding &lt;code&gt;0.1&lt;/code&gt; and &lt;code&gt;0.5&lt;/code&gt;, which is easy even for us humans, since &lt;code&gt;0.5&lt;/code&gt; has such a tidy representation in binary.&lt;/p&gt;

&lt;p&gt;(The logic for addition in binary is the same in base ten, except you "carry" when you get to two rather than ten. Luckily, this problem doesn't involve any carrying at all!)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  0.00011[0011...] // 0.1
+ 0.1              // 0.5
= 0.10011[0011...] // 0.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this one, you could cut off the repeating decimal at &lt;em&gt;any point&lt;/em&gt; and the value of &lt;code&gt;0.1 + 0.2&lt;/code&gt; would have the same representation as &lt;code&gt;0.3&lt;/code&gt;. We can tell this easily because one of the numbers does not infinitely repeat. Therefore, the infinite part of the result must come from the infinite part of the &lt;code&gt;0.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now let's try &lt;code&gt;0.1&lt;/code&gt; plus &lt;code&gt;0.2&lt;/code&gt; (You do need to learn how to carry for this one, sorry):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  0.00011[0011...] // 0.1
+ 0.00110[0110...] // 0.2
= 0.10011[0011...] // 0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the same &lt;em&gt;if&lt;/em&gt; you have the ability to think about infinitely long numbers. But what about a computer? They need to cut off the repeating decimals at some point.&lt;/p&gt;

&lt;p&gt;Let's take another look at what happens if we cut it off at, say, &lt;strong&gt;seven&lt;/strong&gt; decimal places:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  0.0001100 // approximately 0.1
+ 0.0011001 // approximately 0.2
= 0.1001101 // close to 0.3, but...
  0.1001100 // this is what 0.3 actually looks like when approximated to 7 decimal places!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;All languages that use floating point numbers will have some form of this problem.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those languages may not face this &lt;em&gt;exact&lt;/em&gt; issue - it depends on where exactly the program gives up keeping track of infinitely repeating decimals.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;typeof NaN&lt;/code&gt; is &lt;code&gt;"number"&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is partially a language decision, but also partially due to how computers don't do math quite like humans do.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NaN&lt;/code&gt; (Not a Number) is typically seen when a numeric system encounters non-numeric data (for example, &lt;code&gt;parseInt("a")&lt;/code&gt;). However, it is defined in the &lt;a href="http://www.hlam.ece.ufl.edu/EEL4712/Labs/Lab6/IEEEStandard754FP.pdf"&gt;IEEE764 floating point spec&lt;/a&gt; as any numeric concept or value that doesn't represent a single real number, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A number with a complex component (as in 2 + 3 &lt;em&gt;i&lt;/em&gt;, where &lt;em&gt;i&lt;/em&gt; is the square root of -1)&lt;/li&gt;
&lt;li&gt;A result of a numeric operation of numbers that has an indeterminate result&lt;/li&gt;
&lt;li&gt;A result of an invalid mathematical operation&lt;/li&gt;
&lt;li&gt;The result of a mathematical operation where one of the operands is &lt;code&gt;NaN&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JavaScript's &lt;code&gt;Number&lt;/code&gt; type is based on this floating point specification, so it makes sense that the type also includes &lt;code&gt;NaN&lt;/code&gt;. &lt;code&gt;Number&lt;/code&gt; also includes non-numbers that are more conceptual, such as &lt;code&gt;Infinity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you think of &lt;code&gt;Number&lt;/code&gt; as &lt;strong&gt;"math stuff"&lt;/strong&gt;, it probably makes more sense.&lt;/p&gt;

&lt;p&gt;...I do agree that it's hilarious, though.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;Math.max()&lt;/code&gt; is &lt;code&gt;-Infinity&lt;/code&gt; and &lt;code&gt;Math.min()&lt;/code&gt; is &lt;code&gt;Infinity&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;These functions both typically take list of arguments, such as:&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&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="mi"&gt;3&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="c1"&gt;// returns 4&lt;/span&gt;
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&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="mi"&gt;3&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="c1"&gt;// returns 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So these are basically the functions being called with an "empty array" of arguments.&lt;/p&gt;

&lt;p&gt;If you take the maximum or minimum value of an empty list, what would you expect the result to be? The question itself - &lt;em&gt;what is the smallest value in an empty list of things?&lt;/em&gt; - sounds like a question a Zen master would ask. The answer might not have any meaning at all, so it falls to us to make sure it's at least practical.&lt;/p&gt;

&lt;p&gt;Let's go over this one by example - if you had an array of numbers (in any language), what sort of algorithm would you use to find the smallest or largest? A bit of pseudo-code for the most common algorithm to replicate &lt;code&gt;Math.max&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;given LIST OF ARGUMENTS
variable RESULT
for (each ITEM in the LIST OF ARGUMENTS):
  is the ITEM greater than the current RESULT?
    if so, replace RESULT with the ITEM's value
    otherwise, do nothing; continue on to the next ITEM.
return RESULT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The question here is - &lt;strong&gt;what should the initial value of RESULT be&lt;/strong&gt;? There are two intuitive answers that work well:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It should be an &lt;strong&gt;empty value&lt;/strong&gt; such as &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. This means that you have to update the algorithm a little bit to account for the empty value, and people who use this will need to note that the return value may be empty or zero, and they will need to be careful to not confuse the two.*&lt;/li&gt;
&lt;li&gt;It should be something that is &lt;strong&gt;always "less than" any finite number&lt;/strong&gt;. in JavaScript, &lt;code&gt;-Infinity&lt;/code&gt; satisfies that logic. The logical consequence to this is that if there is nothing in the list of arguments, the &lt;code&gt;-Infinity&lt;/code&gt; will be returned.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;* &lt;em&gt;If you've ever coded in PHP, this likely brought back traumatic memories. I'm sorry.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Both of these work just fine, and the only thing that's affected is the (probably rare) case of being called with an empty list of things to compare, and some &lt;em&gt;extremely&lt;/em&gt; minor performance differences. Not an important choice in the long run, so I don't blame JavaScript for this one. At least we don't have to check the return value for &lt;code&gt;null&lt;/code&gt; every time.&lt;/p&gt;




&lt;p&gt;You made it to the end! Thanks for sticking around. Here's a picture of a kitten in a bowtie to show my appreciation (via &lt;a href="https://www.reddit.com/r/aww/comments/w9kskf/my_friend_bought_little_bowties_for_some_kittens/"&gt;reddit&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--liaBF1u8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://preview.redd.it/ld5tkt53c5e91.jpg%3Fwidth%3D640%26crop%3Dsmart%26auto%3Dwebp%26s%3D9b49b67fa16e2cb0a0c3256893e8ce98977c60a0" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--liaBF1u8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://preview.redd.it/ld5tkt53c5e91.jpg%3Fwidth%3D640%26crop%3Dsmart%26auto%3Dwebp%26s%3D9b49b67fa16e2cb0a0c3256893e8ce98977c60a0" alt="A picture of a very small kitten wearing a bowtie" width="640" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tchaflich/javascript-wtfs-explained-type-coercion-4i8o"&gt;The other half of the Reddit post is discussed here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>math</category>
    </item>
    <item>
      <title>JavaScript WTFs explained - Type coercion</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Thu, 28 Jul 2022 23:44:37 +0000</pubDate>
      <link>https://dev.to/tchaflich/javascript-wtfs-explained-type-coercion-4i8o</link>
      <guid>https://dev.to/tchaflich/javascript-wtfs-explained-type-coercion-4i8o</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover Photo by &lt;a href="https://unsplash.com/@tonny_tran?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Tony Tran&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3lHhz3xY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1t92oatsx66m68wr543.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3lHhz3xY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1t92oatsx66m68wr543.png" alt="A screenshot of the Firefox developer console with several confusing results output - this will be the subject of today's discussion" width="344" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source:&lt;/p&gt;


&lt;div class="ltag__reddit--container"&gt;
  &lt;div class="ltag__reddit--title-container"&gt;
    
      &lt;div class="ltag__reddit--title"&gt;
        &lt;h1&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCqI7Yj---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/reddit-icon-c6851eed10026b5707e2e8c814b5bbcbb4823de68d5b611a6f4b99c8beed6f05.svg" alt="Reddit Logo"&gt;
          &lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/w8m9em/just_started_learning_javascript_and_have_a_lot/" rel="noopener noreferrer"&gt;
            Just started learning JavaScript and have a lot of questions that begin with “Why/How tf”
          &lt;/a&gt;
        &lt;/h1&gt;
        &lt;div class="ltag__reddit--post-metadata"&gt;
          &lt;span&gt;Jul 26 '22&lt;/span&gt;
          &lt;span&gt;Author: ievisheleo&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__reddit--body"&gt;
    &lt;p&gt;
        &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nICAJdRC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://b.thumbs.redditmedia.com/cS7eCuMAf-PZSInDi9SUlZ_vLmxVvOGRa0Hptp38YQI.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nICAJdRC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://b.thumbs.redditmedia.com/cS7eCuMAf-PZSInDi9SUlZ_vLmxVvOGRa0Hptp38YQI.jpg" alt="Just started learning JavaScript and have a lot of questions that begin with “Why/How tf”"&gt;&lt;/a&gt;
    &lt;/p&gt;
  &lt;/div&gt;
  &lt;div class="ltag__reddit--btn--container"&gt;
    
      &lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/w8m9em/just_started_learning_javascript_and_have_a_lot/" rel="noopener noreferrer"&gt;See Full Post&lt;/a&gt;
    
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The few examples to follow look pretty unhinged, fair warning. &lt;/p&gt;

&lt;p&gt;The factor most at fault is &lt;strong&gt;automatic type conversion&lt;/strong&gt; due to loose typing, but &lt;strong&gt;operator overload&lt;/strong&gt; is also a problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  The plus &lt;code&gt;+&lt;/code&gt; operator is overloaded
&lt;/h2&gt;

&lt;p&gt;The + operator in JavaScript has two different functions. As you might expect, it can &lt;strong&gt;add numbers together&lt;/strong&gt;, but it can also &lt;strong&gt;concatenate strings&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Concatenation&lt;/strong&gt; is when two (or more) strings are taped together to form a new, combined string.&lt;/p&gt;

&lt;p&gt;For example, concatenating &lt;code&gt;"hello"&lt;/code&gt; and &lt;code&gt;"world"&lt;/code&gt; results in &lt;code&gt;"helloworld"&lt;/code&gt;.&lt;br&gt;
This is done with the &lt;code&gt;+&lt;/code&gt; operator in JavaScript, but other languages might use other methods, such as a &lt;code&gt;concat()&lt;/code&gt; function or a different operator.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When an operator can do multiple different things like this, it is referred to as an &lt;strong&gt;overloaded operator&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By contrast, if you look at the minus &lt;code&gt;-&lt;/code&gt; operator, it only does math, and doesn't have a defined operation for strings at all. Minus is &lt;em&gt;not&lt;/em&gt; overloaded.&lt;/p&gt;




&lt;h2&gt;
  
  
  Type coercion
&lt;/h2&gt;

&lt;p&gt;JavaScript has &lt;strong&gt;two distinct equality operators&lt;/strong&gt;, one that compares content but &lt;em&gt;not&lt;/em&gt; type (&lt;code&gt;==&lt;/code&gt;), and one that compares content &lt;em&gt;and&lt;/em&gt; type (&lt;code&gt;===&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// number&lt;/span&gt;

&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "2" == "2"&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "2" === 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So how does the loose equality operator (&lt;code&gt;==&lt;/code&gt;) determine if two variables have the "same" content? It &lt;strong&gt;converts&lt;/strong&gt; one or both values.&lt;/p&gt;

&lt;p&gt;Taking a look at &lt;code&gt;"2" == 2&lt;/code&gt;, let's go over the process step-by-step.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check if both values are of the same type. In this case, they &lt;strong&gt;aren't&lt;/strong&gt;, and need to be converted.&lt;/li&gt;
&lt;li&gt;Determine the type(s) to convert to. JavaScript's &lt;a href="https://explained.blog/javascript/loose-equality--algorithm/#comparing-string-to-number"&gt;loose equality algorithm&lt;/a&gt; determines which values to convert, and to what. In this case, the string is converted to a number.&lt;/li&gt;
&lt;li&gt;Compare the converted values. In this case, &lt;code&gt;2&lt;/code&gt; (converted from string) and &lt;code&gt;2&lt;/code&gt; (original) are equal, so the return value is true.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another resource to check for this is the &lt;a href="https://dorey.github.io/JavaScript-Equality-Table/"&gt;JavaScript Equality Table&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Advanced note on equality for arrays and objects&lt;/p&gt;

&lt;p&gt;So far, we've looked at strings and numbers for &lt;code&gt;==&lt;/code&gt; and &lt;code&gt;===&lt;/code&gt;, but it functions differently for more complicated constructs like arrays and objects. In these cases, &lt;em&gt;both&lt;/em&gt; operators check that the operands have the same &lt;em&gt;reference&lt;/em&gt;. For more information, see &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality"&gt;MDN&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Empty array + empty array
&lt;/h2&gt;

&lt;p&gt;Let's take a look at the first (and easiest to explain), empty array plus empty array.&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="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// evaluates to "" &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what's happening:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JavaScript sees the &lt;code&gt;+&lt;/code&gt; operator and thinks about what types are valid for this: strings and numbers. Additionally, the two operands should match each other.

&lt;ul&gt;
&lt;li&gt;Two strings will be concatenated (&lt;code&gt;"a" + "b"&lt;/code&gt; =&amp;gt; &lt;code&gt;"ab"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Two numbers will be added numerically (&lt;code&gt;1 + 2&lt;/code&gt; =&amp;gt; &lt;code&gt;3&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;JavaScript looks at what the actual variables used in the operation, and sees if any need to be converted. In this case, both arrays need to be converted, since they aren't strings or numbers. For &lt;code&gt;+&lt;/code&gt;, both arguments must be converted to "primitive" values (either a string, number, or boolean).&lt;/li&gt;
&lt;li&gt;JavaScript uses a &lt;a href="https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-applystringornumericbinaryoperator"&gt;specific set of logic&lt;/a&gt; to cast the arguments to the type it wants

&lt;ul&gt;
&lt;li&gt;Arrays are converted to a predetermined primitive type, which is a string 📝. An empty array becomes an empty string, &lt;code&gt;""&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Two empty strings concatenated together make an empty string - and there's your result!&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;📝 How does an array become a string?&lt;/p&gt;

&lt;p&gt;In JavaScript, you can test this out by using &lt;code&gt;String([...])&lt;/code&gt; or &lt;code&gt;([...]).toString()&lt;/code&gt; to observe how different arrays are transformed into strings.&lt;/p&gt;

&lt;p&gt;The elements in the array are transformed into strings, and those stringified elements are joined together with a comma.&lt;/p&gt;


&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "a,b"&lt;/span&gt;
&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&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;// "a,2,b,3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This is much different from the result of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify"&gt;&lt;code&gt;JSON.stringify&lt;/code&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Empty array + empty object
&lt;/h2&gt;

&lt;p&gt;This one works very similarly to the above. JavaScript determines that both operands need to be strings in order to continue, and converts them both. As we have seen previously, &lt;code&gt;[]&lt;/code&gt; becomes &lt;code&gt;""&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The only difference is that an empty object &lt;code&gt;{}&lt;/code&gt;, when cast to a string, becomes &lt;code&gt;"[object Object]"&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Why &lt;code&gt;"[object Object]"&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://stackoverflow.com/a/25419538"&gt;https://stackoverflow.com/a/25419538&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As others have noted, this is the default serialisation of an object. But why is it [object Object] and not just [object]?&lt;/p&gt;

&lt;p&gt;That is because there are different types of objects in Javascript!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://es5.github.io/spec.html#x15-toc"&gt;Object specification&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Empty object + empty array
&lt;/h2&gt;

&lt;p&gt;Despite the title of this section, the &lt;code&gt;{}&lt;/code&gt; is actually &lt;em&gt;not interpreted as an object&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;When used at the start of an expression, and there's no other indication that it &lt;em&gt;ought&lt;/em&gt; to be an object, JS decides it's a block statement instead.&lt;/p&gt;

&lt;p&gt;Here's what a &lt;em&gt;non&lt;/em&gt;-empty block statement looks like:&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo&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've seen these before, though they're usually used with constructs like if-statements, loops, and the like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo&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;In the case of this particular example, it's interpreted as an &lt;strong&gt;empty block statement&lt;/strong&gt;, which is functionally equivalent to typing nothing.&lt;/p&gt;

&lt;p&gt;The reason the previous example was interpreted as an empty object instead of an empty block was that it was being used as a right-hand operand for &lt;code&gt;+&lt;/code&gt;. JavaScript supports &lt;code&gt;+&lt;/code&gt; being used to cast to number type when used without a left-hand operand:&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="c1"&gt;// left and right&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "11"&lt;/span&gt;

&lt;span class="c1"&gt;// casting with right-side only&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1&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="c1"&gt;// 1&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, we can reduce the problem to &lt;code&gt;+[]&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;When JS converts an array to a number, it is effectively the same as casting that same array to a string (as seen in the two previous examples), &lt;em&gt;then&lt;/em&gt; casting that string to a number. (Note that casting the array to a string converts values such as &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; to empty string as well.)&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="p"&gt;[].&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ""&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "1"&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "1,2"&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1,2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// NaN, can't parse this&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "a"&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// NaN, can't parse this&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now we can see where the &lt;code&gt;0&lt;/code&gt; comes from - it's the numeric value of an empty string.&lt;/p&gt;




&lt;h2&gt;
  
  
  Type coercion with different operators
&lt;/h2&gt;

&lt;p&gt;So far we've worked only with the &lt;code&gt;+&lt;/code&gt; operator, which is an &lt;em&gt;overloaded operator&lt;/em&gt;: it can be used for more than one thing, depending on the operands. However, the mathematical opposite, &lt;code&gt;-&lt;/code&gt;, is only used for mathematical subtraction, and can't be used to manipulate strings at all.&lt;/p&gt;

&lt;p&gt;The examples used in the reddit post:&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="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "91"&lt;/span&gt;
&lt;span class="mi"&gt;91&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 90&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since one of the operands of &lt;code&gt;9 + "1"&lt;/code&gt; is a string, even if it's a numeric string, the &lt;code&gt;+&lt;/code&gt; operation results in a string concatenation.&lt;/p&gt;

&lt;p&gt;However, since &lt;code&gt;-&lt;/code&gt; cannot be used for string concatenation, the "1" is interpreted as numeric.&lt;/p&gt;

&lt;p&gt;Here are some more examples of this principle in action:&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="c1"&gt;// two numeric operands is always math&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -1&lt;/span&gt;

&lt;span class="c1"&gt;// numeric strings are concatenated for addition, and converted for subtraction&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "12"&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "12"&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "12"&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -1&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -1&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -1&lt;/span&gt;

&lt;span class="c1"&gt;// non-numeric strings are concatenated for addition, and result in a math error for subtraction&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "1hello"&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&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="c1"&gt;// "hello1";&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&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="c1"&gt;// NaN&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  When is a &lt;code&gt;true&lt;/code&gt; a &lt;code&gt;1&lt;/code&gt;?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;true&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="c1"&gt;// true&lt;/span&gt;
&lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As in the section dealing with &lt;code&gt;[]+[]&lt;/code&gt;, we know that JavaScript will convert operands if they aren't of the appropriate type. In this case, the boolean value &lt;code&gt;true&lt;/code&gt; is cast to a numeric &lt;code&gt;1&lt;/code&gt;, and as we all know, &lt;code&gt;1 + 1 + 1&lt;/code&gt; is in fact three.&lt;/p&gt;

&lt;p&gt;Similarly, &lt;code&gt;1 - 1&lt;/code&gt; we know to be zero.&lt;/p&gt;

&lt;p&gt;Note that these &lt;em&gt;can&lt;/em&gt; be cast to the strings "true" and "false", for example when a string is an operand:&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "1hellotruefalse" &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When is a &lt;code&gt;true&lt;/code&gt; &lt;em&gt;not&lt;/em&gt; a &lt;code&gt;1&lt;/code&gt;?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kc"&gt;true&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="c1"&gt;// true&lt;/span&gt;
&lt;span class="kc"&gt;true&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="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The numeric value of &lt;code&gt;true&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt;, so the loose equality operator sees them as having the same value.&lt;/p&gt;

&lt;p&gt;The reddit post lists the following statements:&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="kc"&gt;true&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="c1"&gt;// yes, because true is cast to 1&lt;/span&gt;
&lt;span class="kc"&gt;true&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="c1"&gt;// no, because true and 1 are not the same type&lt;/span&gt;
&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// yes, because empty array is cast to 0 (see empty object + empty array example)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Abusing type coercion for fun and profit
&lt;/h2&gt;

&lt;p&gt;The last example from reddit is basically a gigantic exercise in learning automatic type conversion, so let's break it down.&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!&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="c1"&gt;// 9&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing we need to ask here is: The length of &lt;em&gt;what&lt;/em&gt;, exactly? Let's take a look at what's in those parentheses.&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="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;+!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// "truefalse"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.length&lt;/code&gt; might have led to you believe that it was an &lt;em&gt;array&lt;/em&gt; of length 9, but here we have a &lt;em&gt;string&lt;/em&gt; of length 9. Now, let's figure out why we get that string out of that expression.&lt;/p&gt;

&lt;p&gt;Let's separate it out a little bit, so it's more readable:&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!+&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;([])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That first set of parentheses contains two &lt;strong&gt;explicit&lt;/strong&gt; conversions, which are worked from the "inside out" - the closest conversion to the value goes first, then it works its way outwards. So first, &lt;code&gt;[]&lt;/code&gt; is our value, which is converted to a number by &lt;code&gt;+[]&lt;/code&gt;, which results in &lt;code&gt;0&lt;/code&gt;. Next, the &lt;code&gt;!&lt;/code&gt; converts the number to a boolean value and inverts it - &lt;code&gt;0&lt;/code&gt; converts to a boolean &lt;code&gt;false&lt;/code&gt;, which when inverted results in &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's leave that empty array in the middle for a moment. It isn't being explicitly cast.&lt;/p&gt;

&lt;p&gt;On the right, we have &lt;code&gt;![]&lt;/code&gt; - at first glance, it seems like this also ought to be true, since &lt;code&gt;!+[]&lt;/code&gt; is true. However, the extra conversion to number makes all the difference! When converted &lt;em&gt;directly&lt;/em&gt; to a boolean value, an empty array results in &lt;code&gt;true&lt;/code&gt;, which when inverted is &lt;code&gt;false&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nb"&gt;Boolean&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="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now, we have the simplified form of our expression from earlier:&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="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now on to that &lt;code&gt;+&lt;/code&gt; operand. The choice with &lt;code&gt;+&lt;/code&gt; is either numeric plus, or string concatenation, and JavaScript's internal ruleset says that when you are using &lt;code&gt;+&lt;/code&gt; with a boolean and an array, both are cast automatically to strings and concatenated. From left to right, we can work this expression out:&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="c1"&gt;// true + [] + false&lt;/span&gt;
&lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// "true"&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// "truefalse"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wait, so... &lt;strong&gt;&lt;em&gt;why&lt;/em&gt;&lt;/strong&gt;?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why is JavaScript loosely typed, and why does it do automatic type conversion?
&lt;/h3&gt;

&lt;p&gt;Brandon Eich designed the language in 1995 in &lt;a href="https://thenewstack.io/brendan-eich-on-creating-javascript-in-10-days-and-what-hed-do-differently-today/"&gt;under two weeks&lt;/a&gt;. I don't really think there's a "why" to it, to be honest. Maybe we can blame a lack of sleep on his part.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does X convert to Y?
&lt;/h3&gt;

&lt;p&gt;There &lt;em&gt;is&lt;/em&gt; an internal logic to all the automatic type conversion JavaScript does - it is, after all, run by a computer, and computers don't just spontaneously decide to do something a little different to mess with you.&lt;/p&gt;

&lt;p&gt;You might notice that arrays and objects are tricky, being cast to many different possible primitive values:&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="c1"&gt;// empty arrays&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;// ""&lt;/span&gt;
&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="c1"&gt;// arrays with stuff in them&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="nb"&gt;Number&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="c1"&gt;// 1&lt;/span&gt;
&lt;span class="nb"&gt;Number&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="c1"&gt;// 2&lt;/span&gt;
&lt;span class="nb"&gt;Number&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// "a"&lt;/span&gt;
&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&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="c1"&gt;// "a,1"&lt;/span&gt;
&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// ""&lt;/span&gt;
&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="c1"&gt;// empty objects&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// "[object Object]"&lt;/span&gt;
&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most JavaScript-specific WTFery actually depends, deep down, on these conversions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final notes
&lt;/h2&gt;

&lt;p&gt;Much of this isn't JavaScript-specific. The many examples of JavaScript shenanigans are often simple floating-point errors, which can be found in any programming language that uses floating point numbers. (Please stop using these as examples of why JavaScript is bad. There's enough wrong about JavaScript to be mad about without bringing in floating point arithmetic.)&lt;/p&gt;

&lt;p&gt;The true WTF is not necessarily that JavaScript can do automatic type conversion, but the absolute bonkers scale of how much it will convert, and to what.&lt;/p&gt;

&lt;h3&gt;
  
  
  What do I even do about this?
&lt;/h3&gt;

&lt;p&gt;If you're coming from a strongly-typed language and/or felt like crying several times during this article, I suggest &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you can't or don't want to use TypeScript, make sure to follow these two rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Always use strict equality (&lt;code&gt;===&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Always explicitly convert types, rather than allowing JavaScript to implicitly convert them &lt;em&gt;for&lt;/em&gt; you&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;JavaScript can't break your stuff with automatic type conversion if you've made sure things are the right type to begin with.&lt;/p&gt;




&lt;p&gt;You made it to the end! Congrats for wading knee-deep into JavaScript's type system. Have a picture of a squirrel eating at a tiny table for your trouble. (via &lt;a href="https://www.reddit.com/r/aww/comments/w9lz4q/this_squirrel_likes_to_hang_out_on_my_porch_so_i/"&gt;reddit&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2qwiCuCt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://preview.redd.it/upwo5mwqk5e91.jpg%3Fwidth%3D960%26crop%3Dsmart%26auto%3Dwebp%26s%3Dece2e70fdc67895c29801e1c147c8f961ee2219f" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2qwiCuCt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://preview.redd.it/upwo5mwqk5e91.jpg%3Fwidth%3D960%26crop%3Dsmart%26auto%3Dwebp%26s%3Dece2e70fdc67895c29801e1c147c8f961ee2219f" alt="A squirrel eating at a table, there's a tiny bucket and some corn." width="880" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tchaflich/javascript-wtfs-explained-number-type-and-floating-point-2130"&gt;The other half of the Reddit post is discussed here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Alignment in CSS: text and vertical alignment</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Sun, 04 Aug 2019 23:11:36 +0000</pubDate>
      <link>https://dev.to/tchaflich/alignment-in-css-text-and-vertical-alignment-56hl</link>
      <guid>https://dev.to/tchaflich/alignment-in-css-text-and-vertical-alignment-56hl</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Alex Wong.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  This is the beginning of a long journey to learn how to get things to finally, finally align properly on our webpages.
&lt;/h3&gt;

&lt;p&gt;Today's tutorial is about two properties: &lt;code&gt;text-align&lt;/code&gt; and &lt;code&gt;vertical-align&lt;/code&gt;. Text align is a very simple property, often the first to be learned by beginners. Vertical align seems to be its simple counterpoint, but can be deceptive due to its complex rules and is an early stumbling block for many.&lt;/p&gt;

&lt;h1&gt;
  
  
  📌 Text align
&lt;/h1&gt;

&lt;p&gt;The purpose of &lt;code&gt;text-align&lt;/code&gt; is to align text &lt;em&gt;horizontally&lt;/em&gt;. Play around with it:&lt;/p&gt;

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

&lt;p&gt;If you've worked with any sort of text editor before, these options will be strikingly familiar.&lt;/p&gt;

&lt;p&gt;There are more options coming soon - for example, &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt;, which depend on the text direction, aligning via a specific character (such as a decimal), and &lt;code&gt;justify-all&lt;/code&gt;, which forces the last line of text to be justified. These vary widely in support as of the authoring date (Aug 2019), as they are currently still editor's drafts in terms of specification - so make sure to check compatibility tables before using anything fancy.&lt;/p&gt;

&lt;p&gt;References &amp;amp; further reading for text-align:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/text-align"&gt;MDN: text-align&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  📌 Vertical align
&lt;/h1&gt;

&lt;p&gt;As you might have guessed by the name, the purpose of &lt;code&gt;vertical-align&lt;/code&gt; is to align text &lt;em&gt;vertically&lt;/em&gt;. In the sample below, I have highlighted some key plant-related phrases; the buttons toggle the vertical align property of these highlights.&lt;/p&gt;

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

&lt;p&gt;If you're applying vertical-align to &lt;code&gt;display: inline&lt;/code&gt; or &lt;code&gt;display: inline-block&lt;/code&gt; elements, then you will be able to align them with each other. You can align anything that can flow horizontally, as long as it has a valid display property set. Text, images, icons, buttons, inputs...&lt;/p&gt;

&lt;h3&gt;
  
  
  When using &lt;code&gt;vertical-align&lt;/code&gt; on inline or inline-block elements, the alignment is relative to sibling elements in a horizontal line, rather than the parent element.
&lt;/h3&gt;

&lt;p&gt;Vertical align also works on tables (as well as elements with display set to table-cell). Here's a sample table to play around with:&lt;/p&gt;

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

&lt;p&gt;An important note:&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚠️ Vertical-align does not align block elements. ⚠️
&lt;/h3&gt;

&lt;p&gt;So if you're thinking... "wait, vertical-align didn't work for me! Why are you telling lies?", look into your element's &lt;code&gt;display&lt;/code&gt; property. &lt;strong&gt;Vertical-align is not an all-purpose way to align everything.&lt;/strong&gt; Since block level elements cannot have an in-flow sibling on the same line as them, they will not be aligned. Block elements &lt;em&gt;can&lt;/em&gt;, however, have children inherit their vertical-align property; it's not strictly invalid, just useless for positioning.&lt;/p&gt;

&lt;p&gt;If you remember the days of table-based layout (way, &lt;em&gt;waaaay&lt;/em&gt; back... hopefully), you might remember the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td#attr-valign"&gt;&lt;code&gt;valign&lt;/code&gt;&lt;/a&gt; &lt;em&gt;attribute&lt;/em&gt; on table cells. It's speculated that the &lt;code&gt;vertical-align&lt;/code&gt; property was created specifically to emulate the behavior of this attribute.&lt;/p&gt;

&lt;h4&gt;
  
  
  tl;dr
&lt;/h4&gt;

&lt;p&gt;Use this for vertically aligning text, images, icons, or other things that display "in line" with each other horizontally. Unless you're using it in a table, vertical align changes items' behavior relative to &lt;em&gt;each other&lt;/em&gt;, rather than with respect to their parent element.&lt;/p&gt;

&lt;p&gt;References &amp;amp; further reading for vertical-align:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align"&gt;MDN: vertical-align&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://christopheraue.net/design/vertical-align"&gt;Vertical-Align: All You Need To Know (CSS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://phrogz.net/css/vertical-align/index.html"&gt;Understanding vertical-align, or "How (Not) To Vertically Center Content"&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bonus vertical align: A tall ghost 👻
&lt;/h2&gt;

&lt;p&gt;Here's a neat trick that uses vertical align. I don't use it in production anymore now that flexbox is well-supported, but it's still a good exploration of how vertical align works.&lt;/p&gt;

&lt;p&gt;This trick is an extension of the fact that vertical align works to center inline-block elements &lt;em&gt;with one another&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CVVaD5Vc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xjmaijcc5g179ndmikox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CVVaD5Vc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xjmaijcc5g179ndmikox.png" alt="An illustration on graph paper of the container setup. There's an inner container (complete with drawn cat), an outer container, and a &amp;quot;tall ghost&amp;quot; dotted line on the left." width="781" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An outer container, larger than the inner container&lt;/li&gt;
&lt;li&gt;An inner container that we want to center vertically&lt;/li&gt;
&lt;li&gt;An invisible "tall ghost" container that only assists with alignment&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The important bits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The tall ghost and inner container are &lt;strong&gt;both&lt;/strong&gt; &lt;code&gt;display: inline-block&lt;/code&gt; and &lt;code&gt;vertical-align: middle&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The tall ghost is 100% height (that's why it's tall!)&lt;/li&gt;
&lt;li&gt;The tall ghost is zero width, to make sure it doesn't throw off alignment (it's invisible)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The invisible aligning element is &lt;em&gt;set&lt;/em&gt; to be the height of its parent with &lt;code&gt;height: 100%&lt;/code&gt;, so whatever is aligned vertically with the "tall ghost" will &lt;em&gt;happen&lt;/em&gt; to align with its parent block element. The two elements inside the container are both inline-block, and so they are available to vertically align with each other. They're both set to &lt;code&gt;vertical-align: middle&lt;/code&gt;. And so, the inner container that we want to align (the cat) sits in the middle.&lt;/p&gt;

&lt;p&gt;Now, that code is a bit messy, so we can clean it up by using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::before"&gt;pseudo-elements&lt;/a&gt;:&lt;/p&gt;

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

&lt;p&gt;There are a couple other small notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;content&lt;/code&gt; attribute containing a space is just to make sure the element can render in all browsers.&lt;/li&gt;
&lt;li&gt;While the width and height are explicitly set in this example, they do not need to be; as long as the inner content doesn't overflow the parent, this trick will work, since it's based on percentage.&lt;/li&gt;
&lt;li&gt;The cat is horizontally centered with &lt;code&gt;text-align: center&lt;/code&gt; because I think it looks nice. This is optional.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EpLgVSQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/j9ygt43b5h3mewoo605m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EpLgVSQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/j9ygt43b5h3mewoo605m.gif" alt="Bob Ross: &amp;quot;I'm glad you could join me today.&amp;quot;" width="400" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anything else you'd like to know about these properties? Any requests for the next entry in the series? I have a &lt;em&gt;lot&lt;/em&gt; planned... it turns out CSS has a lot of ways to align stuff. (How come none of them ever work? 🤔)&lt;/p&gt;

</description>
      <category>css</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What is software to you? Day job, passion, hobby, career, something else?</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Sun, 21 Jul 2019 11:45:29 +0000</pubDate>
      <link>https://dev.to/tchaflich/what-is-software-to-you-day-job-passion-hobby-career-something-else-1a88</link>
      <guid>https://dev.to/tchaflich/what-is-software-to-you-day-job-passion-hobby-career-something-else-1a88</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Dylan Gillis on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We all came to software from different places, and we're all going somewhere different, so I figure we all &lt;em&gt;see&lt;/em&gt; it differently as well. &lt;/p&gt;

&lt;p&gt;Tell me about how you relate to the field in general, if you would?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>Here's how floats work in CSS</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Sat, 20 Jul 2019 21:36:00 +0000</pubDate>
      <link>https://dev.to/tchaflich/here-s-how-floats-work-in-css-13eg</link>
      <guid>https://dev.to/tchaflich/here-s-how-floats-work-in-css-13eg</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by J A N U P R A S A D via Unsplash.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Does anyone else remember the old days of using floats for layout? We used to have to do our CSS uphill in the snow, barefoot, both ways. Whippersnappers these days with their flexbox and their grids...&lt;/p&gt;

&lt;p&gt;In any case, floats are still useful for things that aren't large-scale layout. And even if you don't end up wanting to use them in your newest app, you may end up maintaining an old legacy application that uses a heavy-handed approach to floats. Having a basic knowledge of how they work can come in handy in a variety of situations.&lt;/p&gt;

&lt;p&gt;Plus, floats are one of the big CSS fears. Applying a float and having everything on the page suddenly shift (and not knowing why) is something many of us have done. Let's get over that stumbling block today.&lt;/p&gt;

&lt;p&gt;So, let's jump right in and examine the mystery of the float.&lt;/p&gt;

&lt;h2&gt;
  
  
  The basics
&lt;/h2&gt;

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

&lt;p&gt;This is what floats are best at: &lt;strong&gt;Flowing text around other things.&lt;/strong&gt; Floats are the absolute best way to mimic print layouts when it comes to this.&lt;/p&gt;

&lt;p&gt;What is happening is, very simply, this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The floating element is placed where it would otherwise be&lt;/li&gt;
&lt;li&gt;It's removed from the normal document flow and shoved as far left or right as it can go&lt;/li&gt;
&lt;li&gt;Elements that come after it will arrange themselves &lt;em&gt;around&lt;/em&gt; the floating element&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Can I float center?
&lt;/h4&gt;

&lt;p&gt;Nope. I know it would be cool, but it does not work.&lt;/p&gt;

&lt;p&gt;I guess imagine how you would implement the text-and-cat-picture version of this. How would you go about breaking the text up neatly? There's no great way to do it. That's probably why it was never implemented.&lt;/p&gt;

&lt;h4&gt;
  
  
  Floats aren't in the normal document flow? So it's like "position: absolute"?
&lt;/h4&gt;

&lt;p&gt;Not quite. Elements with &lt;code&gt;position: absolute&lt;/code&gt; (or a similar property) are removed &lt;em&gt;entirely&lt;/em&gt; from the document flow. An absolutely positioned element can often end up on top of or underneath other nearby elements, since they simply ignore each other.&lt;/p&gt;

&lt;p&gt;When an element is floated, it's not exactly &lt;em&gt;in&lt;/em&gt; the normal document flow, but it does interact with other elements; they are subject to special positioning rules, mostly that they will arrange themselves &lt;em&gt;around&lt;/em&gt; it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Floats don't want to be large
&lt;/h2&gt;

&lt;p&gt;A floating element that doesn't have an explicit size set will &lt;a href="https://www.w3.org/TR/CSS2/visudet.html#float-width" rel="noopener noreferrer"&gt;"shrink to fit"&lt;/a&gt; its content - that is, it will only take up as much width as it needs to. If there's not much content inside of it, it won't be very large; if there's a lot, it gets bigger. You may have seen similar behavior before in &lt;code&gt;position: absolute&lt;/code&gt; and &lt;code&gt;position: fixed&lt;/code&gt; elements.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Predicting where floats will go
&lt;/h2&gt;

&lt;p&gt;While you were playing around with the Jabberwocky example, did you happen to find something like this?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fks6sfk9hbpeyfh5bdgfg.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fks6sfk9hbpeyfh5bdgfg.png" alt="Floats floating around in a rather confusing and distressing manner."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the reasons people tend to avoid floats is that they can seem unpredictable. What happens if a series of floats of different heights overflows its line?&lt;/p&gt;

&lt;p&gt;Let's take a look at the specification for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/float#How_floated_elements_are_positioned" rel="noopener noreferrer"&gt;how floating elements are positioned&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[...] when an element is floated, it is taken out of the normal flow of the document (though still remaining part of it). It is shifted to the left, or right, until it touches the edge of its containing box, &lt;em&gt;or another floated element&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So when we have something that would fit within our width, all fine and dandy. When it doesn't, it goes downward and floats some more until it hits an edge that it would like to stop at - the edge of its parent container, or another float.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fw2faalo13deu3s8j5toa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fw2faalo13deu3s8j5toa.gif" alt="An explanation, in GIF form, of the aforementioned distressing float ordering."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Why didn't the last one move upward to fill in that terrible whitespace?
&lt;/h4&gt;

&lt;p&gt;A float will never position itself above something that comes before it in the HTML order.&lt;/p&gt;

&lt;p&gt;It will, however, try to "float" as high as it can, keeping that restriction in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Margins, the box model, and HTML order
&lt;/h2&gt;

&lt;p&gt;In the basic example, were you bothered by this?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fig4wfeugarbm8wu37v2r.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fig4wfeugarbm8wu37v2r.png" alt="A snipped image of the above pen, with the hard left edge highlighted."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What we need here is a &lt;em&gt;margin&lt;/em&gt;. You have about a 1/3 chance of guessing which element to apply the margin to if you choose randomly. As much as it &lt;em&gt;feels&lt;/em&gt; like random guessing is the essence of CSS, though, let's try to understand what the floats are doing here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flrut8ihyqubiq9ez45k0.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flrut8ihyqubiq9ez45k0.png" alt="A drawing on paper of the effect of adding margins to all three elements."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#1&lt;/strong&gt; - This is what happens if you add margin-left to the outer container &lt;code&gt;#container&lt;/code&gt; - it just shoves &lt;em&gt;everything&lt;/em&gt; to the right. This doesn't really fix the problem of the text coming to a hard edge with the floating box. Probably nobody has tried to fix floats this way, except at 3am, crying with desperation. (Who &lt;em&gt;hasn't&lt;/em&gt; been there?)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#2&lt;/strong&gt; - This is something you might actually have tried - applying a &lt;code&gt;margin-left&lt;/code&gt; to the text itself. The text's margin, however, is based on the text's "box" - where the text &lt;em&gt;would&lt;/em&gt; be if the float wasn't there. (You can picture it as having a margin "under" the floating element.)&lt;/p&gt;

&lt;p&gt;The text &lt;em&gt;itself&lt;/em&gt; is still flowing around the float as it was before, but it has a margin left relative to its parent element. The margin property cannot add a "zigzag" margin to the text, and it must have a separation from its parent element represented by the margin, so the separation from the float just won't do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#3&lt;/strong&gt; - The margin is added to the actual floating element, expanding its box. The text will flow around the &lt;em&gt;entire&lt;/em&gt; floating box, margin included. So adding &lt;code&gt;margin-right&lt;/code&gt; to our left-floating cats and &lt;code&gt;margin-left&lt;/code&gt; to our right-floating cats will give the text a bit of space.&lt;/p&gt;

&lt;p&gt;In summary - putting the margin &lt;strong&gt;on the floating element&lt;/strong&gt; causes other stuff to flow around the combined float's box, including any margins.&lt;/p&gt;

&lt;p&gt;The idea that we're getting at here is this - other stuff on the page moves around the float, rather than the float moving around other stuff on the page.&lt;/p&gt;

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

&lt;p&gt;We can also stack floats next to each other! Floats will sit nicely next to other floats, and the text will keep flowing around them all.&lt;/p&gt;

&lt;p&gt;Just note that it's important where in the HTML order the floats are placed. &lt;strong&gt;When in doubt, floats come first.&lt;/strong&gt; Pretend you're the browser, and you're reading the HTML "in order" - you'd want to know where your floating things are first, so you don't have to redraw all the stuff that has to flow around it afterward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clearing floats
&lt;/h2&gt;

&lt;p&gt;An element with the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clear" rel="noopener noreferrer"&gt;&lt;code&gt;clear&lt;/code&gt;&lt;/a&gt; property on it describes how that element will interact with nearby floating elements. You can put a clear property on both floating things &lt;em&gt;and&lt;/em&gt; non-floating things.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  The clear property means: I don't want any floats near me, in this direction!
&lt;/h3&gt;

&lt;p&gt;Since it's rude to push other things around the page, the element that has the clear property on it will move downward if there's a conflicting float nearby. Think of a clearing element as being socially awkward and conflict-avoidant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Floats don't take up space the way you might expect
&lt;/h2&gt;

&lt;p&gt;If you've used floats before, you might have found yourself in this position:&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;#container&lt;/code&gt; that holds all the floats (and &lt;em&gt;only&lt;/em&gt; floats) has collapsed. This is because floating an element removes it from &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flow_Layout/In_Flow_and_Out_of_Flow" rel="noopener noreferrer"&gt;normal document flow&lt;/a&gt;, and the surrounding container does not create a new &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context" rel="noopener noreferrer"&gt;block formatting context&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Remember when I said above:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's removed from the normal document flow and shoved as far left or right as it can go&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"Removed from document flow" has a meaning and technical consequences here!&lt;/p&gt;

&lt;p&gt;Due to the rules that our CSS overlords have specified, the height of a container is determined by all of its contents that are "within normal document flow". However, we can also make the container be a "block formatting context" - kind of like a mini-layout within a page - to tell the container that it needs to treat itself as if it's a mini-document, in that it stretches to fit all its contents, even the out-of-flow ones.&lt;/p&gt;

&lt;p&gt;We will need to do some convincing to get the container to stretch to fit our floats, but know that we have options.&lt;/p&gt;

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

&lt;p&gt;A couple possible solutions:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create an element that is in-flow, but after the floats
&lt;/h3&gt;

&lt;p&gt;This is the &lt;code&gt;clearfix-type-one&lt;/code&gt; solution in the pen above. It's also the "old school" clearfix.&lt;/p&gt;

&lt;p&gt;We know now that the container will stretch to fit all elements within its flow, and floats are not in the flow. So we need a non-floating element that's placed &lt;em&gt;just&lt;/em&gt; after our floating elements. We can do this using the &lt;code&gt;clear&lt;/code&gt; property:&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;id=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"floaty-left"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://placekitten.com/100/200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"floaty-left"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://placekitten.com/100/100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"floaty-left"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://placekitten.com/160/200"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"floaty-left"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://placekitten.com/100/120"&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;style=&lt;/span&gt;&lt;span class="s"&gt;"clear: both;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will cause the container to stretch down to our cleared div. &lt;/p&gt;

&lt;p&gt;However, that element will have a bit of its own height (because it's supposed to have some text inside), so we can add something like &lt;code&gt;height: 0&lt;/code&gt; to make sure it doesn't affect the height of the container while continuing to apply the clearfix. Over the years I've seen other ways to do this, such as using &lt;code&gt;max-height&lt;/code&gt; and even &lt;code&gt;font-size: 0&lt;/code&gt;. ¯\_(ツ)_/¯&lt;/p&gt;

&lt;p&gt;Since this is only for display and isn't semantic, we can also move it to an &lt;code&gt;::after&lt;/code&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::after" rel="noopener noreferrer"&gt;pseudo-element&lt;/a&gt; applied to the container.&lt;/p&gt;

&lt;p&gt;That's how we end up with something like the following:&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;// the "basic" clearfix with after&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;.clearfix-type-one&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="mh"&gt;#644&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="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;both&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;visibility&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be refined even further; there are many similar solutions online. For example, &lt;a href="http://nicolasgallagher.com/micro-clearfix-hack/" rel="noopener noreferrer"&gt;Nicholas Gallagher's micro clearfix&lt;/a&gt; from 2011. Clearfix solutions of this type tend to have amazing cross-browser support since they've been around for nearly a decade. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use &lt;code&gt;overflow: hidden&lt;/code&gt; to create a new block formatting context
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;(Technically you can use any overflow value that isn't visible, but hidden is the one that tends to work best. Give me a second to explain...)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the &lt;code&gt;clearfix-type-two&lt;/code&gt; solution in the pen above. From the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Block_formatting_context" rel="noopener noreferrer"&gt;MDN docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A block formatting context contains everything inside of the element creating it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thus, forcing the parent container to form a new block formatting context will force it to expand, since it &lt;em&gt;must&lt;/em&gt; fully contain all its children. And it's done with just one property, so &lt;strong&gt;why isn't this the single best solution?&lt;/strong&gt; Why is it only number two of three on a list?&lt;/p&gt;

&lt;p&gt;Well... you're using &lt;code&gt;overflow: hidden&lt;/code&gt;. This isn't consequence-free; you have to deal with having a container that doesn't show anything at all outside of itself. What if we also want to have some rainbow drop shadows on some of our elements that would be clipped, or absolutely positioned glitter outside of our wrapper? It would be madness to get rid of those just to clear our floats.&lt;/p&gt;

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

&lt;p&gt;You can see what a travesty this would be.&lt;/p&gt;

&lt;p&gt;And remember how I said earlier that you could use any overflow value that wasn't visible? Well, imagine how crappy that would look with &lt;code&gt;overflow: scroll&lt;/code&gt; creating scrollbars on the sides. Big yikes.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Use &lt;code&gt;display: flow-root&lt;/code&gt; to create a new block formatting context
&lt;/h3&gt;

&lt;p&gt;This is the &lt;code&gt;clearfix-type-three&lt;/code&gt; solution in the pen above.&lt;/p&gt;

&lt;p&gt;Unlike the solutions above, this is &lt;em&gt;meant&lt;/em&gt; to work on an inherent level, and isn't a "hack". From the &lt;a href="https://drafts.csswg.org/css-display/#valdef-display-flow-root" rel="noopener noreferrer"&gt;spec&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The element generates a block container box, and lays out its contents using flow layout. It always establishes a new block formatting context for its contents.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So this basically does the same thing as &lt;code&gt;overflow: hidden&lt;/code&gt;, but with no side effects. ✨&lt;/p&gt;

&lt;p&gt;That sounds like exactly what we want! The reason it isn't used is &lt;a href="https://caniuse.com/#feat=flow-root" rel="noopener noreferrer"&gt;cross-browser support&lt;/a&gt; - it's not currently supported on almost 30% of devices, with Safari and IE/Edge being the problem children as always.&lt;/p&gt;

&lt;h1&gt;
  
  
  What else do you want to know about floats?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F00d71a4wiitq0vihc33d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F00d71a4wiitq0vihc33d.jpg" alt="A series of hot-air balloons "&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Footer photo by Cristina Gottardi on Unsplash.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A few JavaScript puzzlers</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Sat, 13 Jul 2019 13:02:13 +0000</pubDate>
      <link>https://dev.to/tchaflich/a-few-javascript-puzzlers-2p1l</link>
      <guid>https://dev.to/tchaflich/a-few-javascript-puzzlers-2p1l</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Kyle Glenn on Unsplash.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Good morning! 🌥️ How's your weekend going?
&lt;/h3&gt;

&lt;p&gt;I've been sick lately, so haven't had a lot of energy to work on the usual posts. But I've put together a few quick "riddles" specific to JavaScript.&lt;/p&gt;

&lt;p&gt;If you get the answers early on, try to not spoil the answers in the comments for those just looking for hints rather than solutions. (Spoiler tags when?)&lt;/p&gt;

&lt;h2&gt;
  
  
  #1 - Non-reflexive
&lt;/h2&gt;

&lt;p&gt;This one is fairly simple if you know the language "gotchas", but quite a puzzle indeed if you've never seen this behavior before.&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;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;[]];&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is more than one answer, see if you can find the whole solution space for an additional challenge.&lt;/p&gt;

&lt;p&gt;Hint links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/4170978/explain-why-this-works"&gt;StackOverflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"&gt;MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://patriciopalladino.com/blog/2012/08/09/non-alphanumeric-javascript.html"&gt;Blog post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  #2 - Reciprocal
&lt;/h2&gt;

&lt;p&gt;Here's another head scratcher:&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;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="c1"&gt;// true&lt;/span&gt;
&lt;span class="mi"&gt;1&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;===&lt;/span&gt; &lt;span class="mi"&gt;1&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="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find values of x &amp;amp; y.&lt;/p&gt;

&lt;p&gt;The senior JS devs are groaning and probably already know the answer. But for those of you less practiced, here is a hint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ecma-international.org/ecma-262/5.1/#sec-8.5"&gt;ECMAScript specification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  #3 - Prototype
&lt;/h2&gt;

&lt;p&gt;And another one:&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;var&lt;/span&gt; &lt;span class="nx"&gt;someone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="nx"&gt;someone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;alice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;someone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;alice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;someone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;bob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;eve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;someone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the end of this code, what is &lt;code&gt;eve.attributes.name&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Your hints are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/launch-school/javascript-weekly-data-types-and-mutability-e41ab37f2f95"&gt;Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new"&gt;MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;JavaScript really is quite a puzzling language, isn't it? Which ones did you get immediately, and which did you need to look up?&lt;/p&gt;

&lt;p&gt;Have a great weekend, and don't forget to be awesome!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/100QWMdxQJzQC4/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/100QWMdxQJzQC4/giphy.gif" alt="Small white dog wearing a bow-tie giving a high-five." width="450" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>The parable of the turkey: or, The way things have always been done</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Wed, 26 Jun 2019 23:41:34 +0000</pubDate>
      <link>https://dev.to/tchaflich/the-parable-of-the-turkey-or-the-way-things-have-always-been-done-d2e</link>
      <guid>https://dev.to/tchaflich/the-parable-of-the-turkey-or-the-way-things-have-always-been-done-d2e</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Randy Fath via Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The story goes:
&lt;/h3&gt;

&lt;p&gt;A young couple, happily married, is celebrating their first Thanksgiving together. The bride wants to cook her husband her family's classic turkey recipe, and asks her mother for the recipe.&lt;/p&gt;

&lt;p&gt;Her mother sends her the recipe, and the woman cooks it to perfection. Even the breast-meat is perfectly tender and juicy. However, at the end, her husband remarks: "Darling, where are the legs? I always liked those best."&lt;/p&gt;

&lt;p&gt;"There on the side," she tells him.&lt;/p&gt;

&lt;p&gt;He picks around the bird, and he seems still confused, so she points them out to him. He asks, "but love, why are they shaped like this? They don't look like drumsticks to me. They're all... squashed-y?"&lt;/p&gt;

&lt;p&gt;She says, "It's in the recipe. You take the legs off, take the bones out, and cook the meat on the side."&lt;/p&gt;

&lt;p&gt;He still doesn't understand, but the turkey was very tasty, so he leaves it be.&lt;/p&gt;




&lt;p&gt;The next day, the woman calls up her mother and asks, "So mom, about that turkey recipe. Why do we take the bones out and cook the meat on the side?"&lt;/p&gt;

&lt;p&gt;Her mother replies, "Hm, I don't actually know why. Your grandmother just always did it that way, and it's her recipe."&lt;/p&gt;




&lt;p&gt;The mother and grandmother are having a pleasant brunch one morning, and the question of the turkey comes up once more.&lt;/p&gt;

&lt;p&gt;"Oh, right," says the mother. "Ma, I gave my daughter your turkey recipe, and she asked about the turkey legs."&lt;/p&gt;

&lt;p&gt;"What about them?" asked the grandmother.&lt;/p&gt;

&lt;p&gt;"Well, why do we cut them off, take the bones out, and cook the meat on the side?"&lt;/p&gt;

&lt;p&gt;The grandmother bursts into gales of laughter. "I did that when you were a kid because my pan was too small to fit the whole turkey!"&lt;/p&gt;




&lt;p&gt;At least, that's how it was related to me. &lt;a href="https://www.snopes.com/fact-check/grandmas-cooking-secret/"&gt;There are many variations.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/348lrWhJAUiuhkcePl/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/348lrWhJAUiuhkcePl/giphy.gif" alt="A boston terrier in a turkey costume riding a roomba." width="480" height="267"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;I couldn't find a good way to transition here. I'm making the best of it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You've probably sussed out the moral of the story by now. But just to make sure we're all on the same page:&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing what has always been done without knowing &lt;em&gt;why&lt;/em&gt; is not a good idea.
&lt;/h2&gt;

&lt;p&gt;Imagine that the young woman had never asked, but instead had to hack some other rig together for her turkey. In several generations, what would this recipe look like? I don't think it would be quite as tasty if all those hasty fixes had been passed down as "I don't know why it works, don't touch it" over the generations.&lt;/p&gt;

&lt;p&gt;So if you see some code, and you don't know how it works, you'll get a tastier... program? if you figure it out. It might be on &lt;a href="https://meta.stackoverflow.com/questions/361904/what-is-stack-overflow-driven-development"&gt;StackOverflow&lt;/a&gt; or in your legacy codebase full of technical debt, but consider it your job to &lt;em&gt;learn&lt;/em&gt; what it's doing.&lt;/p&gt;

&lt;p&gt;Don't fall for the trap of &lt;a href="https://www.alejandrodu.com/2016/04/copy-paste-based-development.html"&gt;copy-paste driven development&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>codequality</category>
    </item>
    <item>
      <title>A width-responsive perfect square in pure CSS</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Sun, 23 Jun 2019 15:20:01 +0000</pubDate>
      <link>https://dev.to/tchaflich/a-width-responsive-perfect-square-in-pure-css-3dao</link>
      <guid>https://dev.to/tchaflich/a-width-responsive-perfect-square-in-pure-css-3dao</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Daniel McCullough via Unsplash.&lt;/em&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Points of interest
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Resizable block-level divs
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/resize" rel="noopener noreferrer"&gt;&lt;code&gt;resize&lt;/code&gt;&lt;/a&gt; property - I wasn't aware you could actually control this past textareas, but stumbled upon it when looking for a way to make a user-resizable div without using JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the square is made
&lt;/h3&gt;

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

&lt;span class="nn"&gt;#square&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;padding-bottom&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;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;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#2980b9&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;Breaking this down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;width: 100%&lt;/code&gt; is to make sure it's defined as having the same width as its outer, resizable container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;padding-bottom: 100%&lt;/code&gt; is based on a trick in the CSS spec. When specifying a margin or padding by percentage, it's always &lt;a href="https://drafts.csswg.org/css-box-3/#propdef-margin" rel="noopener noreferrer"&gt;based on the width&lt;/a&gt;, even if it's a -top or -bottom property. In this way we get a property that's equal to the width.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;position: relative&lt;/code&gt; is so that I can put stuff inside it without disrupting the padding; any additional content would add content to the box, which would make it a rectangle&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;background-color&lt;/code&gt; is there so you can see where it is ¯\_(ツ)_/¯&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How the circle is made
&lt;/h3&gt;

&lt;p&gt;Once you have &lt;em&gt;any&lt;/em&gt; square, making a circle is easy enough. The only trick you really need is &lt;code&gt;border-radius: 50%&lt;/code&gt;, but let's break down the responsive circle a bit more.&lt;/p&gt;

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

&lt;span class="nn"&gt;#circle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&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="mh"&gt;#27ae60&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;position: absolute&lt;/code&gt; makes sure that this circle stays within the &lt;code&gt;position: relative&lt;/code&gt; square while not adding any in-flow content to it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top: 0; bottom: 0; width: 100%; height: 100%;&lt;/code&gt; constrains the circle to the exact dimensions of the responsive square. At this point, what we have is a position: absolute container that is an inner copy of our square.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;border-*&lt;/code&gt; properties are used to build the outline of the circle. We have a 4px green solid border, and it has a radius of half the edge of the square.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick geometry recap
&lt;/h3&gt;

&lt;p&gt;Here's an illustration of why &lt;code&gt;50%&lt;/code&gt; is the magic number to make a circle from a square:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuk84nlztvy437v5262hs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuk84nlztvy437v5262hs.png" alt="A very pixelated drawing showing a circle inside a square with some radials. It's very geometric."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;radius&lt;/em&gt; of the circle is equal to &lt;em&gt;half&lt;/em&gt; the side of the square.&lt;/p&gt;

</description>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to actually animate a text gradient in CSS</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Sat, 22 Jun 2019 23:29:27 +0000</pubDate>
      <link>https://dev.to/tchaflich/how-to-actually-animate-a-text-gradient-in-css-3a33</link>
      <guid>https://dev.to/tchaflich/how-to-actually-animate-a-text-gradient-in-css-3a33</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Kristopher Roller via Unsplash.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Since you all liked my &lt;a href="https://dev.to/tchaflich/today-i-learned-how-to-animate-a-text-gradient-in-css-and-javascript-2ehp"&gt;iridescent shambling monstrosity&lt;/a&gt;, I figured it was worth a second swing. Thanks to &lt;a href="https://dev.to/erinjzimmer"&gt;@erinjzimmer&lt;/a&gt; for letting me know that it's possible to animate the gradient background by animating &lt;code&gt;background-position&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, instead of writing a humorous article where I make the worst technically-functional CSS possible, let's try to make this thing not terrible. I swear, the only JavaScript I used this time was for the buttons. &lt;/p&gt;

&lt;p&gt;I don't have a problem, I can stop whenever I want.&lt;/p&gt;

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

&lt;p&gt;Since we figured out how to get the rainbow text last time, let's jump to the good parts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Animating background position
&lt;/h2&gt;

&lt;p&gt;To use transitions with this, it's very likely that I would have had to resort to similar tactics as in the previous post (&lt;em&gt;yikes&lt;/em&gt;) to make sure that the gradient moved in one direction continuously. But instead of going through all that effort, I decided to use &lt;code&gt;@keyframes&lt;/code&gt;, which turned out to be as easy as forgetting to add files before you commit.&lt;/p&gt;

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

&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="nt"&gt;whoosh&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;background-position-x&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="nt"&gt;100&lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;background-position-x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.animated-thing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation-name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;whoosh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// references @keyframes name&lt;/span&gt;
  &lt;span class="nl"&gt;animation-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2000ms&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// or whatever&lt;/span&gt;
  &lt;span class="nl"&gt;animation-timing-function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linear&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;animation-iteration-count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;infinite&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;There's an important caveat to be mentioned to make this look good, though.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/tchaflich/embed/QXvwJR?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;em&gt;A... catveat? Eh?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The cat image is 200px wide, and the window is either 400px wide or 500px wide. (Click to toggle.) When the container is 400px wide, the animation is smooth and you don't notice it suddenly resetting to the beginning when it loops. When it's 500px wide, the end of the animation is 100px offset and the jump is &lt;em&gt;very&lt;/em&gt; noticeable.&lt;/p&gt;

&lt;p&gt;Using gifs for illustration:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhj74g9bgzl45098rjj3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhj74g9bgzl45098rjj3.gif" alt="A cat walking on a spinning chair. The gif loop is very good."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the loop resets, it's in the same position as when it started, making the looping is much less noticeable. (There may still &lt;em&gt;be&lt;/em&gt; a jump, but it should be very small.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6v0stp12kxduk1o6djeo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6v0stp12kxduk1o6djeo.gif" alt="A fluffy white cat sitting in a tree. At the last minute, the camera turns downward."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite the cuteness of this fluffy cloud-friend, the jump is very noticeable due to the camera turning downward sharply at the last moment. Would pat cat, would not animate smoothly.&lt;/p&gt;

&lt;p&gt;Another issue is that setting the background to be &lt;em&gt;exactly&lt;/em&gt; the same width as its container in this case causes it to not animate. I guess CSS thinks it has nowhere to go! So it needs to be some exact fraction or exact multiple, but not &lt;em&gt;equal&lt;/em&gt;. And it needs to reset to the exact same position it started in.&lt;/p&gt;
&lt;h2&gt;
  
  
  Animating background position &lt;em&gt;with gradients&lt;/em&gt;
&lt;/h2&gt;

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

&lt;p&gt;To make CSS actually animate it, I set the &lt;code&gt;background-size&lt;/code&gt; to 200% width (and 100% height). That was the easy part.&lt;/p&gt;

&lt;p&gt;To get the gradient to animate &lt;em&gt;smoothly&lt;/em&gt; was trickier.&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;$first-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#996699&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$second-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mh"&gt;#B39500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$third-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mh"&gt;#009980&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$fourth-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#006699&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$angle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;75deg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$angle&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;see&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;repetition&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;colors&lt;/span&gt; &lt;span class="n"&gt;easily&lt;/span&gt;
    &lt;span class="nv"&gt;$first-color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$second-color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$third-color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$fourth-color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
    &lt;span class="nv"&gt;$first-color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$second-color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$third-color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$fourth-color&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;back&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;
    &lt;span class="nv"&gt;$first-color&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 how the gradient is set up so that it doesn't appear to "jump" when the loop resets. It needs to repeat twice, but also repeat the first bit of the loop. In the final pen, this was turned into a mixin.&lt;/p&gt;

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

&lt;span class="k"&gt;@mixin&lt;/span&gt; &lt;span class="nf"&gt;flag-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$direction&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$color-stops&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$grads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$color-stops&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;@each&lt;/span&gt; &lt;span class="nv"&gt;$stop&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$color-stops&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$grads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$grads&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$stop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nv"&gt;$grads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$grads&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;nth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;nth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$grads&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="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="c1"&gt;// [ clipped ]&lt;/span&gt;

  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$direction&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$grads&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 does all that repetition work for you. It copies the arg list sent in, then loops over it to append each of the new color stops (hmu if you know a better way to do that part), Then picks out the color part of the first color stop and tacks that onto the end. That way you only need to specify your actual flag colors.&lt;/p&gt;

&lt;p&gt;Also take note of the angle you put the gradient towards - the steeper it is, the more noticeable the jump will be. Somewhere between 75 and 90 is nearly invisible but still looks tilty enough to be aesthetically pleasing. The smaller the width the sharper this angle needs to be, as well. 90 is safe!&lt;/p&gt;

&lt;p&gt;If you're viewing the inline pen on dev.to, you'll see the 90 degree variant, because of this bit:&lt;/p&gt;

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

&lt;span class="k"&gt;@mixin&lt;/span&gt; &lt;span class="nf"&gt;flag-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$direction&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$color-stops&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// [ clipped ]&lt;/span&gt;

  &lt;span class="k"&gt;@if&lt;/span&gt; &lt;span class="nv"&gt;$direction&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;75deg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="nf"&gt;and&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;800px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80deg&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="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="nf"&gt;and&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90deg&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="c1"&gt;// [ clipped ]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Since the animation quality varies so sharply based on the angle &amp;amp; width, I auto adjusted it if you don't send an override.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding more flags 🏳️‍🌈 (refactoring)
&lt;/h2&gt;

&lt;p&gt;After I got the initial rainbow animation going, it seemed... too easy. I needed to work harder in the eternal struggle against CSS. I wondered, was this able to be generalized? Could I show &lt;em&gt;even more pride&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfcqcajih002470shnaq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfcqcajih002470shnaq.PNG" alt="A code screenshot showing the bi pride flag using multiple colors in a row for color stops."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the bi pride flag, I discovered another interesting caveat. In order to make the jumps less noticeable, the gradient should be as smooth as possible. Using percentage based color stops generally turns out poorly; just plain duplicating the colors turned out to have better results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrgvxd0dddeo7gxysl6q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrgvxd0dddeo7gxysl6q.png" alt="Trans pride flag colors (blue, pink, and white) against a white background."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hm, I'd really like to see a text shadow on there to make the white bits not blend into the background so much. White shows up on a few different flags, so it's definitely a general issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5hmx8dbxd6nge0u0zil.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5hmx8dbxd6nge0u0zil.png" alt="The text is now covered entirely in darkness. Oh no!"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;That went well.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is actually entirely logical, if you think about it. The entire reason the gradient text trick works in the first place is by making the text itself transparent, and clipping the background; not by actually &lt;em&gt;applying&lt;/em&gt; the background to the text. &lt;/p&gt;

&lt;p&gt;I did look into fixing this. &lt;a href="https://stackoverflow.com/a/28750655" rel="noopener noreferrer"&gt;StackOverflow&lt;/a&gt; suggests:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Basically, the idea is to have 2 div overplayed on each other. The lower one provides the background and the shadow. And the the div above just uses a mask to cut out the exact same text from the background image, so that it covers the text of lower element, but not the shadow:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  2 div overplayed on each other
&lt;/h4&gt;

&lt;h3&gt;
  
  
  2 div overplayed on each other
&lt;/h3&gt;

&lt;h2&gt;
  
  
  2 div overplayed on each other
&lt;/h2&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%2Fmedia.tenor.co%2Fimages%2F60d6ac6564c529d7c964aa9e66c62bce%2Fraw" 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%2Fmedia.tenor.co%2Fimages%2F60d6ac6564c529d7c964aa9e66c62bce%2Fraw" alt="A gif of a dog hopping away, with lots of "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not going down that road again! You can't make 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7r6bidqeertypzxr9b0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7r6bidqeertypzxr9b0.png" alt="The text with trans-pride gradient now has a dark background"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Close enough.&lt;/p&gt;

&lt;p&gt;After a bit of playing around with various flag designs and colors, I settled on needing four different "themes", based around light/dark and warm/cool. That's what all this is for:&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;$background-map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;light-cool&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#ecf0f1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;light-warm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#f2eded&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dark-cool&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#10181e&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dark-warm&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#0e070a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;@function&lt;/span&gt; &lt;span class="nf"&gt;get-opposite-tone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$tone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@if&lt;/span&gt; &lt;span class="nv"&gt;$tone&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'light'&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;@return&lt;/span&gt; &lt;span class="s1"&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;@return&lt;/span&gt; &lt;span class="s1"&gt;'light'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@mixin&lt;/span&gt; &lt;span class="nf"&gt;set-background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$tone&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'light'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'cool'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;$secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&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;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$background-map&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$tone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="si"&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;#picker&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;button&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;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$background-map&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nf"&gt;get-opposite-tone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$tone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="si"&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="nc"&gt;.highlight&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;@if&lt;/span&gt; &lt;span class="nv"&gt;$tone&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'light'&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;lighten&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$background-map&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nf"&gt;get-opposite-tone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$tone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&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="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;darken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$background-map&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nf"&gt;get-opposite-tone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$tone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&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="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;map-get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$background-map&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$tone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nv"&gt;$temp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// [ clipped ]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;At this point, all I needed was 8 lines of JavaScript (... plus jQuery) to hook the buttons up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefq97c235j7pejr5fsgq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefq97c235j7pejr5fsgq.gif" alt="Frodo from LOTR in front of the volcano: "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrap-up fun facts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The buttons on the side use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/grid" rel="noopener noreferrer"&gt;CSS Grid&lt;/a&gt; for layout and it was extremely easy and convenient&lt;/li&gt;
&lt;li&gt;Did you know there's not one standard "lesbian" pride flag? I picked the lipstick lesbian flag because that was easy to find color definitions for and seemed to be the most popular&lt;/li&gt;
&lt;li&gt;SCSS &lt;a href="https://www.sitepoint.com/sass-multiple-arguments-lists-or-arglist/" rel="noopener noreferrer"&gt;arglists&lt;/a&gt; are a thing&lt;/li&gt;
&lt;li&gt;You can't put an &lt;code&gt;@media&lt;/code&gt; query statement inside an &lt;code&gt;@function&lt;/code&gt; (lmao I tried just to see if it &lt;em&gt;would&lt;/em&gt; work, but the compiler throws an exception)&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3aza52f584t58ngvfe36.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3aza52f584t58ngvfe36.gif" alt="Dazzling, luminescent glitter text reading "&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Today I learned how to animate a text gradient in CSS (and JavaScript)</title>
      <dc:creator>Thomas C. Haflich</dc:creator>
      <pubDate>Fri, 21 Jun 2019 00:36:05 +0000</pubDate>
      <link>https://dev.to/tchaflich/today-i-learned-how-to-animate-a-text-gradient-in-css-and-javascript-2ehp</link>
      <guid>https://dev.to/tchaflich/today-i-learned-how-to-animate-a-text-gradient-in-css-and-javascript-2ehp</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by Clem Onojeghuo via Unsplash.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  I'm very sorry. And you're welcome.
&lt;/h3&gt;

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

&lt;p&gt;Look at that bad boy &lt;em&gt;chug&lt;/em&gt;. I think I set my CPU on fire making it... poor thing is really doing its best. I see why the CSS overlords didn't want to let me do this now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part one: Getting a text gradient 🌈
&lt;/h2&gt;

&lt;p&gt;You might notice this part of the code:&lt;/p&gt;

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

&lt;span class="k"&gt;@mixin&lt;/span&gt; &lt;span class="nf"&gt;lead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$one&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$two&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$three&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$four&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$five&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$six&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;80deg&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$one&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$two&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$three&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$four&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$five&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$six&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background-clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;text-fill-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;-webkit-background-clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="na"&gt;-webkit-text-fill-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;That's what's generating the actual "rainbow text" part of this disaster.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;background&lt;/code&gt; part is just generating the gradient itself; the good old rainbow barf you might have seen elsewhere before. Removing all the &lt;code&gt;background-clip&lt;/code&gt; and &lt;code&gt;text-fill&lt;/code&gt; shenanigans in that mixin makes it look like this:&lt;/p&gt;

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

&lt;h4&gt;
  
  
  It's all that other stuff that makes the text look like the background.
&lt;/h4&gt;

&lt;p&gt;Normally the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip" rel="noopener noreferrer"&gt;background-clip property&lt;/a&gt; is used to fine-tune the appearance of background around borders and paddings and the like, but the "text" value is highly magical.&lt;/p&gt;

&lt;p&gt;The text-fill-color is &lt;em&gt;roughly&lt;/em&gt; equivalent to your standard &lt;code&gt;color&lt;/code&gt; attribute. (For this pen you could just as easily substitute &lt;code&gt;color: transparent&lt;/code&gt;, I tried and it worked.) In this case we can set it to "transparent" so that our background shows through.&lt;/p&gt;

&lt;p&gt;So what's going on here to get the "rainbow text" is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The background is turned into rainbows&lt;/li&gt;
&lt;li&gt;The background is clipped so that the only part of it that shows is the part that would normally be covered by text&lt;/li&gt;
&lt;li&gt;The text is made transparent so we can see the background through it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Part two: You can animate a background, but you can't make it linear-gradient
&lt;/h2&gt;

&lt;p&gt;This is where everything started to go off the rails. My first approach was to slap a &lt;code&gt;transition&lt;/code&gt; on a single container and call it a day; it would have taken about five minutes, and most of that was googling how to make the gradient clip to the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;However&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Time to try another tactic.&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;id=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container lead-red"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  HAPPY PRIDE MONTH
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"fade"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container lead-orange"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  HAPPY PRIDE MONTH
&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;Wait, why are there two-&lt;/p&gt;

&lt;h3&gt;
  
  
  🤔
&lt;/h3&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;intervalFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;rainbowify&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;getNextTimeoutDuration&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;intervalFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;What are you doing on an interval-&lt;/p&gt;

&lt;h1&gt;
  
  
  🤔 ... 🤔 ... 🤔 ...
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Oh no.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's the gist:&lt;/p&gt;

&lt;p&gt;Have two nearly identical HTML elements overlap each other. The first one, &lt;code&gt;#main&lt;/code&gt;, is on the bottom layer and is always visible; it "blinks" between gradients at a constant opacity. The second one, &lt;code&gt;#fade&lt;/code&gt;, is on the top layer and is constantly blinking in (when aligned) and fading out (to achieve an appearance of transition using &lt;code&gt;opacity&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;These two are not on the same "rainbow cycle" - the &lt;code&gt;#fade&lt;/code&gt; text is ahead of the &lt;code&gt;#main&lt;/code&gt; by one color. JavaScript runs a loop using setInterval to juggle the classes on these two elements to keep the colors moving.&lt;/p&gt;

&lt;p&gt;That also didn't work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part three: Blink in, fade out
&lt;/h2&gt;

&lt;p&gt;My code looked something like this: During the main setInterval loop, attempt to halt animation with a &lt;code&gt;.halt&lt;/code&gt; class that sets the transition-timing property to 0ms (effectively disabling transitions). I would then set the opacity to 1 to get it to "blink in", and remove the &lt;code&gt;.halt&lt;/code&gt; class. The I would set the opacity back to 0 and let the transition do its magic. This all happened immediately, on about four lines of code.&lt;/p&gt;

&lt;p&gt;Well, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#JavaScript_examples" rel="noopener noreferrer"&gt;CSS transitions do not work that way&lt;/a&gt;. It turns out that in order for it to transition, the rendering engine needs a couple milliseconds to get its act together, regardless of what the transition property was on the element at the time. &lt;/p&gt;

&lt;p&gt;Adding and then removing a class almost immediately is not, as it turns out, enough time.&lt;/p&gt;

&lt;p&gt;I messed around with transition timing and other CSS for awhile before giving up and trying JavaScript. The initial JS hack of using a &lt;code&gt;setTimeout( ... , 20)&lt;/code&gt; inside my existing setInterval loop worked... about 95% of the time. Setting the timeout lower would cause it to stutter as the transitions couldn't keep up, and setting the timeout higher would cause highly noticeable pauses in the animation. However, having weird magic numbers lying around and occasional visits from Blinky McBlinkerton weren't where I wanted to &lt;em&gt;leave&lt;/em&gt; it...&lt;/p&gt;

&lt;h2&gt;
  
  
  Part four: Reducing the juddering
&lt;/h2&gt;

&lt;p&gt;The first part I wanted to eliminate was that magic 20ms timeout. I googled for an eternity and came up with this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://css-tricks.com/restart-css-animation/#article-header-id-0" rel="noopener noreferrer"&gt;Trigger a reflow in between removing and adding the class name.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That explains this bit:&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;fade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;halt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hide&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lead-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;rainbow&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nx"&gt;i&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="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;ilen&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nx"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lead-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;rainbow&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;ilen&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- this one!&lt;/span&gt;

&lt;span class="nx"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;halt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hide&lt;/span&gt;&lt;span class="dl"&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 next weird thing I figured I'd plan ahead for was &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Reasons_for_delays_longer_than_specified" rel="noopener noreferrer"&gt;JS timer drift&lt;/a&gt;. I've seen this before when building schedules and clocks; one millisecond as specified is not &lt;em&gt;always&lt;/em&gt; one millisecond in reality, so any interval will inevitably drift further and further away from accuracy. Since I have the same timeout hardcoded into my SCSS and my JS, it would definitely look nicer if they could consistently line up. This could prevent further pauses, stutters, etc. due to timer drift.&lt;/p&gt;

&lt;p&gt;To do this, I use setTimeout instead of setInterval, and have the timeout call a function that calls another timeout (effectively creating an interval out of timeouts). Each timeout notes when it starts, and notes the "drift" from the last timeout, and corrects itself to attempt to more accurately hit a long-term target. This would definitely be useful if I were to pivot to something like &lt;code&gt;@keyframes&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  In conclusion:
&lt;/h1&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%2Fdata.whicdn.com%2Fimages%2F300811981%2Flarge.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%2Fdata.whicdn.com%2Fimages%2F300811981%2Flarge.png" alt="Thomas the tank engine side-eyeing the distance, captioned "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is unnecessarily complicated and runs like molasses in winter. Just make a gif or something.&lt;/p&gt;

&lt;p&gt;(ETA: Follow-up &lt;a href="https://dev.to/tchaflich/how-to-actually-animate-a-text-gradient-in-css-3a33"&gt;here&lt;/a&gt;. If for some reason you want to &lt;em&gt;actually&lt;/em&gt; do this...)&lt;/p&gt;

&lt;p&gt;But I did it, CSS overlords. I've beaten you. &lt;em&gt;I've won.&lt;/em&gt;&lt;/p&gt;

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