<?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: Trezy</title>
    <description>The latest articles on DEV Community by Trezy (@trezy).</description>
    <link>https://dev.to/trezy</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%2F172857%2F49a210ec-f635-43bb-ab1f-2172e54c0b7f.png</url>
      <title>DEV Community: Trezy</title>
      <link>https://dev.to/trezy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/trezy"/>
    <language>en</language>
    <item>
      <title>Melody: A New Way to RegEx</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Wed, 06 Apr 2022 00:15:36 +0000</pubDate>
      <link>https://dev.to/trezy/melody-a-new-way-to-regex-3f6i</link>
      <guid>https://dev.to/trezy/melody-a-new-way-to-regex-3f6i</guid>
      <description>&lt;p&gt;Today, &lt;a href="https://github.com/yoav-lavi"&gt;yoav-lavi&lt;/a&gt; announced &lt;a href="https://github.com/yoav-lavi/melody"&gt;Melody&lt;/a&gt;, a language that compiles down to ECMAScript RegEx. Now, I write &lt;em&gt;a lot&lt;/em&gt; of RegEx, so this project immediately piqued my interest.&lt;/p&gt;

&lt;p&gt;Since the project was only released a couple days ago, it's lacking several important features. For example, you can't...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;set flags (&lt;code&gt;i&lt;/code&gt; for case insensitivity, &lt;code&gt;u&lt;/code&gt; for unicode support, &lt;code&gt;g&lt;/code&gt; for global search, etc)&lt;/li&gt;
&lt;li&gt;negate ranges (e.g. &lt;code&gt;/[^A]/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;create arbitrary multi-ranges (e.g. &lt;code&gt;/[a-c1-3]/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;pass in variables (JavaScript, not RegEx)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All that said, the syntax is pretty slick. Here's a simple example from the docs for finding a hashtag in a string:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the RegEx that's output:&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="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;(?:&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax is interesting, but I'd argue that if you didn't know RegEx then you'd find the Melody version to be &lt;strong&gt;infinitely more readable.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Interesting Syntax
&lt;/h2&gt;

&lt;p&gt;Let's talk about some of the ways Melody makes RegEx more human readable and less like using blood to draw runes into the dirt for the purposes of enacting an arcane incantation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Symbols
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://yoav-lavi.github.io/melody/book/syntax.html#symbols"&gt;Symbols&lt;/a&gt; are Melody's way of simplifying a lot of common RegEx tasks. For example, if you want to capture any normal Latin character in any case, you might write &lt;code&gt;[a-zA-Z]&lt;/code&gt;. With Melody, though, you can use the &lt;code&gt;&amp;lt;alphabetic&amp;gt;&lt;/code&gt; symbol! There are ~16 symbols as of this writing, but here are some of my favorites so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;char&amp;gt;&lt;/code&gt;&lt;/strong&gt;
An alternative to the wildcard (&lt;code&gt;.&lt;/code&gt;) character, which matches &lt;em&gt;anything&lt;/em&gt;. &lt;code&gt;&amp;lt;char&amp;gt;&lt;/code&gt; takes all the guess work out of figuring out if &lt;code&gt;\\\.&lt;/code&gt; is a wildcard or a literal period character. 🙃&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;word&amp;gt;&lt;/code&gt;&lt;/strong&gt;
RegEx escape codes are &lt;em&gt;extremely&lt;/em&gt; useful, but it's not always clear what they're doing. The &lt;code&gt;&amp;lt;word&amp;gt;&lt;/code&gt; symbol matches any word character. This is the same as the &lt;code&gt;\w&lt;/code&gt; escape code in RegEx.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;alphanumeric&amp;gt;&lt;/code&gt;&lt;/strong&gt;
Matches any Latin character (&lt;code&gt;A-Z&lt;/code&gt;) in any case (&lt;code&gt;a-z&lt;/code&gt;), as well as numbers (&lt;code&gt;0-9&lt;/code&gt;). This is the same as using &lt;code&gt;[a-zA-Z0-9]&lt;/code&gt; in RegEx.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Special Symbols
&lt;/h4&gt;

&lt;p&gt;As of this writing, there are two special symbols: &lt;code&gt;&amp;lt;start&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;end&amp;gt;&lt;/code&gt;. These symbols correlate to the &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; characters, respectively. They're used to indicate that the search must start at the beginning or the end of the string, or if the search should be all-inclusive (when using both symbols).&lt;/p&gt;

&lt;h3&gt;
  
  
  Quantifiers
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://yoav-lavi.github.io/melody/book/syntax.html#quantifiers"&gt;Quantifiers&lt;/a&gt; allow us to, uh... well, they allow us to &lt;em&gt;quantify&lt;/em&gt; our expressions. For example, you might use something like this to check for a UUID with RegEx:&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="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&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="o"&gt;-&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&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="o"&gt;-&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&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="o"&gt;-&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;{8}&lt;/code&gt;, &lt;code&gt;{4}&lt;/code&gt;, and &lt;code&gt;{12}&lt;/code&gt; are all quantifiers. They indicate that you want exactly 8, 4, and 12 respectively of the preceding search. With Melody, this would be handled with the &lt;code&gt;... of ...&lt;/code&gt; quantifier:&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="o"&gt;&amp;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;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="o"&gt;&amp;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;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="o"&gt;&amp;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;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="o"&gt;&amp;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;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need a number of characters within a certain range, you can use &lt;code&gt;{min,max}&lt;/code&gt;. For example, &lt;code&gt;\d{1,2}&lt;/code&gt; would indicate that you want between 1 and 2 digits. Melody provides the &lt;code&gt;... to ... of ...&lt;/code&gt; quantifier:&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="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Melody also provides alternatives for the &lt;code&gt;*&lt;/code&gt; (zero or more), &lt;code&gt;+&lt;/code&gt; (one or more), and &lt;code&gt;?&lt;/code&gt; (zero or one) quantifiers:&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;// \d*&lt;/span&gt;
&lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// \d+&lt;/span&gt;
&lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// \d?&lt;/span&gt;
&lt;span class="nx"&gt;option&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Character Ranges
&lt;/h3&gt;

&lt;p&gt;When searching for something within a known character set you need to use a character range (hexadecimal, for example, would be &lt;code&gt;[0-9a-f]&lt;/code&gt;). Declaring ranges is handled by the &lt;code&gt;... to ...&lt;/code&gt; expression.&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;// [a-f]&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// [1-5]&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Groups
&lt;/h3&gt;

&lt;p&gt;One of the most vital features of RegEx is groups! Capturing and non-capturing groups make it possible to create extremely complex searches. Melody enables these &lt;code&gt;capture&lt;/code&gt;, &lt;code&gt;match&lt;/code&gt;, and &lt;code&gt;either&lt;/code&gt; groups.&lt;/p&gt;

&lt;p&gt;To capture the major, minor, and patch versions of a &lt;a href="https://semver.org"&gt;semver&lt;/a&gt; string:&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;capture&lt;/span&gt; &lt;span class="nx"&gt;major&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;capture&lt;/span&gt; &lt;span class="nx"&gt;minor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;capture&lt;/span&gt; &lt;span class="nx"&gt;patch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="o"&gt;&amp;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;If you need to match a search without capturing it, you can use &lt;code&gt;match&lt;/code&gt;. If you need to join multiple &lt;code&gt;match&lt;/code&gt; statements together, you can use &lt;code&gt;either&lt;/code&gt;. Here we'll use both to handle the lack of multi-ranges to match a 2-digit hexadecimal value:&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;2&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;either&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  So Much More!
&lt;/h3&gt;

&lt;p&gt;Melody supports lots of other features, so make sure to &lt;a href="https://yoav-lavi.github.io/melody/book"&gt;check out the docs&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting Melody Thru Its Paces
&lt;/h2&gt;

&lt;p&gt;The basic examples are cool and all, but I wanted to convert some of my real world RegExes to Melody to see if the readability argument still holds up.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Simple Test
&lt;/h3&gt;

&lt;p&gt;While working on my game (&lt;a href="https://trezy.itch.io/debug"&gt;debug&lt;/a&gt;) recently I wrote a RegEx to grab the name, vendor ID, and product ID from a gamepad. Here's what the original version I wrote looked 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="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="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;((?:&lt;/span&gt;&lt;span class="nx"&gt;standard&lt;/span&gt; &lt;span class="nx"&gt;gamepad&lt;/span&gt; &lt;span class="p"&gt;)?&lt;/span&gt;&lt;span class="nx"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only issue I have with converting this to Melody is that Melody doesn't support flags, so my &lt;code&gt;u&lt;/code&gt; (unicode) and &lt;code&gt;i&lt;/code&gt; (case insensitivity) flags won't translate. For now I can handle that on the string before passing it to Melody's RegEx, but it's deffo a sizable shortfall to keep in mind.&lt;/p&gt;

&lt;p&gt;Without further ado, here is my original RegEx converted to Melody syntax:&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;capture&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;lazy&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;space&lt;/span&gt;&lt;span class="o"&gt;&amp;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;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;option&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;standard gamepad &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vendor: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;capture&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;space&lt;/span&gt;&lt;span class="o"&gt;&amp;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;product: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;capture&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a lot more verbose than the original RegEx, but that's what we want! The resulting Melody version is definitely more &lt;em&gt;human&lt;/em&gt; readable than the original RegEx, though if you already know how to read RegEx then it's debatable whether or not the Melody version is more readable.&lt;/p&gt;

&lt;p&gt;For good measure, though, let's do a side-by-side of the original RegEx alongside the output from Melody:&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;// Original&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="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;((?:&lt;/span&gt;&lt;span class="nx"&gt;standard&lt;/span&gt; &lt;span class="nx"&gt;gamepad&lt;/span&gt; &lt;span class="p"&gt;)?&lt;/span&gt;&lt;span class="nx"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;

&lt;span class="c1"&gt;// Melody&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="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;((?:&lt;/span&gt;&lt;span class="nx"&gt;standard&lt;/span&gt; &lt;span class="nx"&gt;gamepad&lt;/span&gt; &lt;span class="p"&gt;)?&lt;/span&gt;&lt;span class="nx"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;((?:&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&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;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;((?:&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&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="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The weirdest thing I've noticed is that Melody tends to add more non-capturing groups than necessary. For example, the only difference between the original and the Melody output is that the &lt;code&gt;\w&lt;/code&gt; escape codes are being wrapped in an extra non-capturing group. That's totally unnecessary and I've &lt;a href="https://github.com/yoav-lavi/melody/issues/70"&gt;made an issue&lt;/a&gt; on the repo for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's Get More Complex
&lt;/h3&gt;

&lt;p&gt;Last year I ran across an absurd Password Validation challenge. You can see my solution in action on &lt;a href="https://regexr.com/4esbn"&gt;RegExr.com&lt;/a&gt;, but here's the actual RegEx I came up with:&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="nx"&gt;A&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Z&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&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;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;z&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;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;z&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&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;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;z&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;A&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Z&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&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;A&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Z&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&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;A&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Z&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;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;z&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;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;z&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;A&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Z&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time I go back and try to read it... 🤢&lt;/p&gt;

&lt;p&gt;The fact that this RegEx is so impossible to read is &lt;em&gt;exactly why&lt;/em&gt; I thought it would be a great test of readability for Melody. Let's take a look at what the Melody version 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="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;either&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;either&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;either&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;either&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;any&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's... a lot to chew on. However, it is &lt;em&gt;undeniably&lt;/em&gt; easier to read than the original RegEx! The one caveat about the output is that it still suffers from the issue I mentioned in the last example with the unnecessary non-capturing groups. Otherwise, the output is perfect! ❤️&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Melody seems like it'll be an &lt;em&gt;excellent&lt;/em&gt; addition to the JavaScript ecosystem! It's got a ways to go, but I'm personally excited to watch how it matures.&lt;/p&gt;

&lt;p&gt;In case &lt;a href="https://github.com/yoav-lavi"&gt;Yoav&lt;/a&gt; is reading this, lemme tell you what I'd &lt;em&gt;looove&lt;/em&gt; to see: I can write my RegEx by creating a &lt;code&gt;.melody&lt;/code&gt; file, then I can &lt;code&gt;import myRegex from './my-regex.melody'&lt;/code&gt; and use &lt;code&gt;myRegex&lt;/code&gt; directly in place of a regular RegEx! There's a Babel plugin that allows writing Melody within template strings, but it'd be amazing to be able to write it in completely separate files and have it imported via a custom Webpack loader or Rollup plugin. HMU if you wanna pair on that project. 🥳&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>regex</category>
    </item>
    <item>
      <title>Loading Images with Web Workers</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Mon, 10 Jun 2019 20:32:49 +0000</pubDate>
      <link>https://dev.to/trezy/loading-images-with-web-workers-49ap</link>
      <guid>https://dev.to/trezy/loading-images-with-web-workers-49ap</guid>
      <description>&lt;p&gt;Web workers are magical. They allow for multi-threading in JavaScript, a language that has been single-threaded &lt;em&gt;since the beginning&lt;/em&gt;. Their practical applications range from heavy number crunching to managing the retrieval and dissemination of asynchronous data, to loading images (as I'll discuss in this article).&lt;/p&gt;

&lt;p&gt;I'm actually preparing for an upcoming talk about web workers, and according to a good friend of mine...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Of course Trezy's talk is about web workers. If he wasn't already married to Meg, the man would marry a web worker.&lt;br&gt;
— @xlexious&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I mean, I suppose I like them a bit. WHAT OF IT‽&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would we want to load images with web workers?
&lt;/h2&gt;

&lt;p&gt;Moving image loading off of the UI thread and into a worker is a really great opportunity for image-heavy sites and one of my favorite web worker implementations. It prevents image downloads from blocking rendering and it can speed up your site significantly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fun fact:&lt;/em&gt; &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags actually block your application load. If you have 100 images on your page, the browser will download all 100 of them before it renders your page.&lt;/p&gt;

&lt;p&gt;Let's talk a little bit about implementing web workers in a couple of different environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  The standard, vanilla implementation
&lt;/h3&gt;

&lt;p&gt;To start a web worker in your average JavaScript app, you need to have it in its own file. Let's assume that we're working on my website, &lt;a href="https://trezy.com"&gt;https://trezy.com&lt;/a&gt;. We'll name our worker file &lt;code&gt;image-loader.worker.js&lt;/code&gt; and it'll be available at &lt;code&gt;https://trezy.com/workers/image-loader.worker.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We'll start with a very simple web worker that will log out whatever data it receives:&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="cm"&gt;/*
 * image-loader.worker.js
 */&lt;/span&gt;

&lt;span class="c1"&gt;// The `message` event is fired in a web worker any time `worker.postMessage(&amp;lt;data&amp;gt;)` is called.&lt;/span&gt;
&lt;span class="c1"&gt;// `event.data` represents the data being passed into a worker via `worker.postMessage(&amp;lt;data&amp;gt;)`.&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Worker received:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To start using it in our main JavaScript file, we'll do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
 * main.js
 */&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ImageLoaderWorker&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;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/workers/image-loader.worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;ImageLoaderWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world!&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;If we load all of this up, we should see &lt;code&gt;Hello world!&lt;/code&gt; in the console.&lt;br&gt;
🎉 Woot! 🥳&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's Get Into It
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Update your markup
&lt;/h3&gt;

&lt;p&gt;With your worker implementation all figured out, we can now start implementing our image loader. I'll start with the HTML that we're going to plan on working from:&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;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;data-src=&lt;/span&gt;&lt;span class="s"&gt;"/images/image1.png"&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;data-src=&lt;/span&gt;&lt;span class="s"&gt;"/images/image2.png"&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;data-src=&lt;/span&gt;&lt;span class="s"&gt;"/images/image3.png"&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;data-src=&lt;/span&gt;&lt;span class="s"&gt;"/images/image4.png"&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;data-src=&lt;/span&gt;&lt;span class="s"&gt;"/images/image5.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Uuuuuuuh, hang on. That's not what &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags look like!&lt;br&gt;
— You, just now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Very astute observation, you! Normally you would use the &lt;code&gt;src&lt;/code&gt; property of an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element to tell it where to download the image file from, but here we're using &lt;code&gt;data-src&lt;/code&gt;. This is because when the browser encounters an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element with a &lt;code&gt;src&lt;/code&gt; attribute, it will immediately start downloading the image. Since we want that job to be offloaded to our web worker, we're using &lt;code&gt;data-src&lt;/code&gt; to prevent the browser from handling the download on the UI thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Pass the image URLs to our web worker
&lt;/h3&gt;

&lt;p&gt;In our &lt;code&gt;main.js&lt;/code&gt; file, we'll need to retrieve all of the relevant &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; elements so we can pass their URLs to our web worker:&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="cm"&gt;/*
 * main.js
 */&lt;/span&gt;

&lt;span class="c1"&gt;// Load up the web worker&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ImageLoaderWorker&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;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/workers/image-loader.worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Get all of the `&amp;lt;img&amp;gt;` elements that have a `data-src` property&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imgElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img[data-src]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Loop over the image elements and pass their URLs to the web worker&lt;/span&gt;
&lt;span class="nx"&gt;imgElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageElement&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;imageElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;ImageLoaderWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Download the images
&lt;/h3&gt;

&lt;p&gt;Excellent! Now that our web worker has received a bunch of image URLs, let's figure out how to process them. This gets a bit complex in web workers for a couple of reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You don't have access to the DOM API.&lt;/strong&gt; A lot of non-web worker image downloader implementations create a new image element and set the &lt;code&gt;src&lt;/code&gt; attribute on it, initiating the download, then replace the original &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; with the new one. This won't work for us because there's no way to create DOM elements inside of a web worker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Images don't have a native JavasScript format.&lt;/strong&gt; Images are made up of binary data, so we need to convert that data into something that we can use in JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;del&gt;&lt;strong&gt;You can only communicate with the UI thread using strings.&lt;/strong&gt;&lt;/del&gt; I've been corrected. This was the case in the days of yore, but no longer! 😁&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So how can we get the image downloaded, converted from binary format to something JavaScript can use, and then passed back to the UI thread? This is where &lt;code&gt;fetch&lt;/code&gt; and the &lt;code&gt;FileReader&lt;/code&gt; API come in.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;fetch&lt;/code&gt; is for more than just JSON
&lt;/h4&gt;

&lt;p&gt;You're probably used to seeing &lt;code&gt;fetch&lt;/code&gt; used to grab data from some API, then calling &lt;code&gt;response.json()&lt;/code&gt; to get the JSON body of the response as an object. However, &lt;code&gt;.json()&lt;/code&gt; isn't the only option here. There's also &lt;code&gt;.text()&lt;/code&gt;, &lt;code&gt;.formData()&lt;/code&gt;, &lt;code&gt;.arrayBuffer()&lt;/code&gt;, and the one that matters to us for this exercise, &lt;code&gt;.blob()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob"&gt;&lt;code&gt;Blob&lt;/code&gt;&lt;/a&gt; can be used to represent virtually anything, including data that doesn't have a native JavaScript format like images! They're perfect for what we're trying to do here. With that in mind, let's update our web worker to receive the image URLs and download them as &lt;code&gt;Blob&lt;/code&gt;s:&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="cm"&gt;/*
 * image-loader.worker.js
 */&lt;/span&gt;

&lt;span class="c1"&gt;// I'm making the event handler `async` to make my life easier. If&lt;/span&gt;
&lt;span class="c1"&gt;// you're not compiling your code, you may want to use the Promise-based&lt;/span&gt;
&lt;span class="c1"&gt;// API of `fetch`&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Grab the imageURL from the event - we'll use this both to download&lt;/span&gt;
  &lt;span class="c1"&gt;// the image and to identify which image elements to update back in the&lt;/span&gt;
  &lt;span class="c1"&gt;// UI thread&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;

  &lt;span class="c1"&gt;// First, we'll fetch the image file&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Once the file has been fetched, we'll convert it to a `Blob`&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileBlob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blob&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;Alright, we're making progress! We've updated our images so they don't download automatically, we've grabbed their URLs and passed them to the worker, and we've downloaded the images to the browser!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Return the image data to the UI thread
&lt;/h3&gt;

&lt;p&gt;Now that we've got the image as a blob, we need to send it back to the UI thread to be rendered. If we send the string back alone then the UI thread won't know where to render it. Instead, we'll send back an object that tells the UI thread what to render &lt;em&gt;and&lt;/em&gt; where:&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="cm"&gt;/*
 * image-loader.worker.js
 */&lt;/span&gt;

&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Send the image data to the UI thread!&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;imageURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;blob&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;Our worker file is done! The final step is to handle what we've received in the UI thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Render that image!
&lt;/h3&gt;

&lt;p&gt;We're &lt;strong&gt;so&lt;/strong&gt; close to being finished! The last thing we need to do is update our main.js file to receive and handle the image data that's returned from the web worker.&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="cm"&gt;/*
 * main.js
 */&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ImageLoaderWorker&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;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/workers/image-loader.worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imgElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img[data-src]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Once again, it's possible that messages could be returned before the&lt;/span&gt;
&lt;span class="c1"&gt;// listener is attached, so we need to attach the listener before we pass&lt;/span&gt;
&lt;span class="c1"&gt;// image URLs to the web worker&lt;/span&gt;
&lt;span class="nx"&gt;ImageLoaderWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Grab the message data from the event&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;

  &lt;span class="c1"&gt;// Get the original element for this image&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`img[data-src='&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageURL&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="c1"&gt;// We can use the `Blob` as an image source! We just need to convert it&lt;/span&gt;
  &lt;span class="c1"&gt;// to an object URL first&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objectURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Once the image is loaded, we'll want to do some extra cleanup&lt;/span&gt;
  &lt;span class="nx"&gt;imageElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Let's remove the original `data-src` attribute to make sure we don't&lt;/span&gt;
    &lt;span class="c1"&gt;// accidentally pass this image to the worker again in the future&lt;/span&gt;
    &lt;span class="nx"&gt;imageElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// We'll also revoke the object URL now that it's been used to prevent the&lt;/span&gt;
    &lt;span class="c1"&gt;// browser from maintaining unnecessary references&lt;/span&gt;
    &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;revokeObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objectURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;imageElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;objectURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;imgElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageElement&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;imageElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;ImageLoaderWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageURL&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;Check out the &lt;a href="https://s.trezy.sh/image-worker-main"&gt;Codepen demo&lt;/a&gt; with everything working together:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  BONUS: Implementing web workers with Webpack
&lt;/h2&gt;

&lt;p&gt;If you're using Webpack to compile all of your code, there's another nifty option to load up your web workers: &lt;a href="https://github.com/webpack-contrib/worker-loader"&gt;&lt;code&gt;worker-loader&lt;/code&gt;&lt;/a&gt;. This loader allows you to import your web worker into a file and initialize it as if it were a regular class.&lt;/p&gt;

&lt;p&gt;I think it feels a little more natural this way, too. Without changing the content of &lt;code&gt;image-loader.worker.js&lt;/code&gt;, this is what an implementation would look like if you have &lt;code&gt;worker-loader&lt;/code&gt; set up in your Webpack config:&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="cm"&gt;/*
 * main.js
 */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ImageLoaderWorker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./workers/image-loader.worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageLoader&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;ImageLoaderWorker&lt;/span&gt;

&lt;span class="nx"&gt;imageLoader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world!&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;Just as in our vanilla implementation, we should see &lt;code&gt;Hello world!&lt;/code&gt; logged out in the console.&lt;/p&gt;

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

&lt;p&gt;And we're done! Offloading image downloading to web workers is a great exercise in using several different browser APIs, but more importantly, it's an awesome way to speed up your website rendering.&lt;/p&gt;

&lt;p&gt;Make sure to drop off your questions and suggestions in the comments below. Tell me your favorite web worker uses, and most importantly, let me know if I missed something awesome in my examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;13 November, 2019&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added the &lt;code&gt;URL.revokeObjectURL(objectURL)&lt;/code&gt; call based on &lt;a class="mentioned-user" href="https://dev.to/monochromer"&gt;@monochromer&lt;/a&gt;'s &lt;a href="https://dev.to/monochromer/comment/hlgh"&gt;comment&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Fixed several typos.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>html</category>
      <category>webworkers</category>
    </item>
    <item>
      <title>From the Devtools to the Clipboard</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:29:55 +0000</pubDate>
      <link>https://dev.to/trezy/from-devtools-to-the-clipboard-10ch</link>
      <guid>https://dev.to/trezy/from-devtools-to-the-clipboard-10ch</guid>
      <description>&lt;h2&gt;
  
  
  You CAN jam stuff into your clipboard from the devtools!
&lt;/h2&gt;

&lt;p&gt;Have you ever spent far too long writing a clever little script in the browser’s devtools to get some information from a page? Maybe you’re trying to generate a list of recurring characters from the Marvel Cinematic Universe (MCU) with their names and secret identities from a Wikipedia page…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1kZ4CVA6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3szspgl6xjarwganxy9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1kZ4CVA6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3szspgl6xjarwganxy9e.png" alt="That wasn’t too bad…" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or maybe you’re trying to get a JSON representation of all of the MCU movies sorted by total profit…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zIdfc6rd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4hovmh42ugz7x19u2hwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zIdfc6rd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4hovmh42ugz7x19u2hwx.png" alt="Okay, that one took a little longer…" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or maybe you’re a &lt;strong&gt;true masochist&lt;/strong&gt;, and you want to extract the Game of Thrones (GoT) character and actor names from the body of the GoT wiki page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U9y5FLSO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ujr630gysoe9z3p93xwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U9y5FLSO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ujr630gysoe9z3p93xwb.png" alt="SERIOUSLY, WHY WOULDN’T YOU PUT THIS DATA IN A TABLE‽" width="880" height="550"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Anyway.
&lt;/h2&gt;

&lt;p&gt;The norm here is to log the data into the console as JSON, then manually select all of the text with your cursor. Not only is this a nightmarish task with large datasets, it also has the potential to have incomplete data. Long strings (especially data URIs) get collapsed with an ellipse (…) by the dev tools. If you want to copy even small data URIs, this approach will leave you — and I’m putting this delicately — &lt;em&gt;completely boned.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, how do we do it better?
&lt;/h2&gt;

&lt;p&gt;With the &lt;code&gt;copy()&lt;/code&gt; function! It just so happens the the devtools for Chrome, Firefox, and Safari (couldn’t test with Edge) all provide the &lt;code&gt;copy()&lt;/code&gt; function for jamming anything you need into the clipboard!&lt;/p&gt;

&lt;p&gt;✨🧙🏻‍♂️ IT’S MAGIC! 🧙🏻‍♂️✨&lt;/p&gt;

&lt;p&gt;If you want to jam an object full of data into your clipboard, it’s as simple as stringifying the data and using &lt;code&gt;copy()&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;bigDataSet&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="p"&gt;]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bigDataSetAsJSON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bigDataSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bigDataSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if you paste anywhere, you’ll find that your clipboard is chock full of JSON beautifulness.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Protip:&lt;/em&gt; If you want your data to be styled (with spaces, line breaks, etc) the &lt;code&gt;JSON.stringify()&lt;/code&gt; method has you covered. For example, if you want the output to use 2 spaces as indentation:&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bigDataSet&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information on what all you can pass into &lt;code&gt;JSON.stringify()&lt;/code&gt;, check out the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify"&gt;docs on MDN&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wow, Trezy! You sure are smart and amazing!
&lt;/h2&gt;

&lt;p&gt;Oh, I know. I appreciate you saying as much, though. If you want to fiddle with any of the code in the examples at the beginning of the article, you can find them &lt;a href="https://hastebin.com/okihububep.js"&gt;here&lt;/a&gt;, &lt;a href="https://hastebin.com/eyuqosuwik.js"&gt;here&lt;/a&gt;, and &lt;a href="https://hastebin.com/jarivurozu.js"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Why Is Browser Caching So Hard?</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:29:05 +0000</pubDate>
      <link>https://dev.to/trezy/why-is-browser-caching-so-hard-12d0</link>
      <guid>https://dev.to/trezy/why-is-browser-caching-so-hard-12d0</guid>
      <description>&lt;h2&gt;
  
  
  Browser caching is one of the best ways to take care of your users while also speeding up your website… so why is it so hard?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This article was originally published on 19 October, 2014 at &lt;a href="https://trezy.com/blog/why-is-browser-caching-so-hard"&gt;Trezy.com&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Browser caching is a magical thing. Every time you visit a website, the files that make up that site are downloaded to your computer by your browser, which then uses those files to render it for you. This takes time and valuable bandwidth, especially on slower connections. The next time you visit that same site, however, the files needed to render it are already downloaded to your computer. Your browser will use the files it already has to render the site, preventing you from having to waste your bandwidth and wait for the files to download.&lt;/p&gt;

&lt;p&gt;Now, this is what happens in a wonderful, magical fairy tale land where all web developers do the right thing and make sure the browser caching is set up on their site. Unfortunately, this is rarely the case. In the spirit of making up statistics, I estimate that somewhere between 30–90% of websites don’t just leverage browser caching, they’re actively working against it.&lt;br&gt;
😞&lt;/p&gt;

&lt;p&gt;See, there are a couple of ways to implement browser caching. You can use what’s called a &lt;code&gt;cache-control&lt;/code&gt; header, which tells the browser how long it can hold on to the file. If you look at my own website, you can see that the Google Analytics script I’m downloading from Google has this header set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KECpPi4P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2zx6rh0vi0aepov91lej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KECpPi4P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2zx6rh0vi0aepov91lej.png" alt="The cache-control header has a max-age of 7200 seconds, or 2 hours." width="880" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two hours isn’t bad. If I revisit my site sometime within the next two hours, my browser will still use the version of that file that I just downloaded. The cool part is that since it’s being served by Google instead of by my server, that file will be cached for every website that uses it, including mine!&lt;/p&gt;

&lt;p&gt;However, if Google updates that file within the next 2 hours, I won’t get those changes.&lt;br&gt;
😞😞&lt;/p&gt;

&lt;p&gt;This is also a great example of where a lot of websites use a technique called &lt;strong&gt;cache busting.&lt;/strong&gt; Cache busting is where you fool the browser into thinking something like this Google Analytics script is a different file than it previously downloaded, guaranteeing the user &lt;strong&gt;always&lt;/strong&gt; gets the latest version of the file. Developers achieve this by adding something like &lt;code&gt;?timestamp=2017-10-19T13:04:29.423Z&lt;/code&gt; to the end of the filename. It’s just a parameter that uses the current date and time, so the browser always thinks that this file is different and, thus, always downloads a new version. Now, every time I go to that site I’ll have to download a new copy of that file.&lt;br&gt;
😞😞😞&lt;/p&gt;
&lt;h2&gt;
  
  
  So… is there a better way?
&lt;/h2&gt;

&lt;p&gt;Remember when I said there are a &lt;strong&gt;couple&lt;/strong&gt; of ways to implement browser caching? Let’s talk about that second one, which is called ETags. ETags are something that the server generates and sends along when a browser tries to retrieve a file for the first time. Here’s an example of a fresh request for one of the files served from my website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5VAQH3dP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nxvcfv7pmijen7yx9mvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5VAQH3dP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nxvcfv7pmijen7yx9mvw.png" alt="Notice there is no expires header. The cache-control header has a max-age of 0, which somewhat unintuitively means feel free to keep this file forever." width="880" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is my logo, which has an &lt;code&gt;etag&lt;/code&gt; header set. This header contains a calculated hash of the file that I’m downloading. The server created that hash for me and sent it up with the file. Now let’s take a look at the second time I request that file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ePjDqHtk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/g3xrc58yax7wnw7c6cs2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ePjDqHtk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/g3xrc58yax7wnw7c6cs2.png" alt="The ETags match!" width="880" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the browser received an &lt;code&gt;etag&lt;/code&gt; header when it first downloaded this file, it made sure to send that ETag back to the server in the &lt;code&gt;if-none-match&lt;/code&gt; header. The server will compare that ETag against what it calculates for its version of the file. If they &lt;em&gt;don’t&lt;/em&gt; match, the server will send a new copy of the file to the browser.&lt;/p&gt;

&lt;p&gt;However, if they &lt;em&gt;do&lt;/em&gt; match it won’t send back a file at all. Instead it will send back a &lt;code&gt;304 Not Modified&lt;/code&gt; response, telling the browser nothing has changed. The Trezy.com server has just saved me time and bandwidth. Just how much has it actually saved me, though?&lt;/p&gt;

&lt;p&gt;On a fresh visit to &lt;a href="https://trezy.com"&gt;Trezy.com&lt;/a&gt;, the website downloads &lt;em&gt;781KB of files&lt;/em&gt; and takes around &lt;em&gt;1.34 seconds to finish&lt;/em&gt;. That’s just for my very tiny website. For other websites that you visit regularly, you can imagine that those numbers will be much larger.&lt;/p&gt;

&lt;p&gt;On a second, cache-friendly visit to my website, though, it only downloads &lt;em&gt;46.1KB of files&lt;/em&gt; and takes &lt;em&gt;1.05 seconds to finish&lt;/em&gt;. That’s a &lt;em&gt;94% savings&lt;/em&gt; in bandwidth, and &lt;em&gt;22% savings&lt;/em&gt; in response times. Again, this is just on my very, very tiny website. Imagine what those savings could look like on a larger website like Facebook or Twitter!&lt;br&gt;
🤔&lt;/p&gt;


&lt;h2&gt;
  
  
  Let’s take a look at some implementation
&lt;/h2&gt;

&lt;p&gt;We’ll look at the very simple implementation of ETags I used for my website, which runs on a &lt;a href="https://koajs.com"&gt;Koa.js&lt;/a&gt; server. Below is the core of what &lt;code&gt;koa-etag&lt;/code&gt; does. It takes care of making sure that your server’s response have ETags calculated and attached to the responses.&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;function&lt;/span&gt; &lt;span class="nx"&gt;etag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;etag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="c1"&gt;// `getResponseEntity` checks to see if the response has a body, and&lt;/span&gt;
      &lt;span class="c1"&gt;// stringifies it depending on what kind of body it has (JSON, HTML, &lt;/span&gt;
      &lt;span class="c1"&gt;// image, etc)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getResponseEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

      &lt;span class="c1"&gt;// `setEtag` calculates the ETag from the response body if it exists,&lt;/span&gt;
      &lt;span class="c1"&gt;// then sets that ETag as a header&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setEtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&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 isn’t all we need to do, though. The response from the server will still contain the contents of the rest and it will respond with a &lt;code&gt;200 OK&lt;/code&gt;, telling the browser that it’s basically getting a new file. Here’s the missing piece of the puzzle.&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;function&lt;/span&gt; &lt;span class="nx"&gt;conditional&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;conditional&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fresh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;304&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright, what’s going on here? &lt;code&gt;ctx.fresh&lt;/code&gt; is a Koa.js-specific property, but it’s basically checking if the old and new ETags match. This middleware, &lt;code&gt;koa-conditonal-get&lt;/code&gt;, uses this property to determine how to proceed. If they do match, the information the browser has is &lt;code&gt;fresh&lt;/code&gt; and we don’t need to send anything new along, so we’ll set the status to that nifty little &lt;code&gt;304 Not Modified&lt;/code&gt; and delete the response body, eliminating the need to send who knows how much gobbledy-gook across the wire. If the ETags don’t meet up to Will Smith’s standards, we’ll need to send along the new content.&lt;/p&gt;




&lt;h2&gt;
  
  
  Make it real!
&lt;/h2&gt;

&lt;p&gt;If you work on one of the 30–90% of websites that don’t implement browser caching, there’s no better time than now to fix it! This is a stupid simple implementation of ETags that may not cut the mustard for a lot of systems, but it’s a great start. It’s not just for websites, either! APIs can leverage ETags to make developer’s lives easier, too. If you have arguments about scalability, I’ll just go ahead and point out to you, Mr. or Mrs. Smarty Pants, that Github implements ETags in their API, so there.&lt;br&gt;
😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Stop Using ngOptions</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:28:22 +0000</pubDate>
      <link>https://dev.to/trezy/stop-using-ngoptions-pa9</link>
      <guid>https://dev.to/trezy/stop-using-ngoptions-pa9</guid>
      <description>&lt;p&gt;&lt;strong&gt;This article was originally published on 02 September, 2015 at &lt;a href="https://codepen.io/trezy/post/stop-using-ngoptions"&gt;Codepen.io&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ngOptions&lt;/code&gt; is awful. It’s hard write and even harder to decypher. If you’re looking at an &lt;code&gt;ngOptions&lt;/code&gt; expressions that &lt;em&gt;somebody else wrote?&lt;/em&gt; God help you. Luckily, creating &lt;code&gt;select&lt;/code&gt; elements in Angular can be so, so much easier. Try this 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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;selectedState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;availableStates&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;selectedState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;‘’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;availableStates&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Alabama&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;AL&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Wisconsin&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;WI&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="s2"&gt;`ng-model`&lt;/span&gt; &lt;span class="nx"&gt;represents&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;home&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;our&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt; &lt;span class="nx"&gt;ng&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;selectedState&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;””&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Select&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/option&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;states&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
    &lt;span class="nx"&gt;ng&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;selectedState&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
    &lt;span class="nx"&gt;ng&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;repeat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;availableStates&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/option&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/select&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It makes sense — as far as Angular goes — right?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;option[value] is what will be set in the model if the option is selected.
option[ng-selected] sets this option as selected if selectedState is set to a state code.
option[ng-repeat] loops through the states to create an option element for each one.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now let’s look at ng-options:&lt;/p&gt;

&lt;p&gt;
  ng-model=”selectedState”&lt;br&gt;
  ng-options=”state.name as state.code for state in availableStates”&amp;gt;&lt;br&gt;
  &amp;lt;!-- Default selection --&amp;gt;&lt;br&gt;
  Select a state&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;(╯°□°)╯︵ ʎʇıןıqɐuıɐʇuıɐɯ&lt;/p&gt;

&lt;p&gt;I’ll admit, it’s way shorter but even if I wrote them I can’t figure out what these things mean when I go back to look at them. Okay, let’s break it down anyway. For academic purposes, right?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;… as … basically says, “Use state.name as a facade for state.code.” That’s kinda cool, as it lets you use an object or an array or a goat or whatever the hell you want for the value and sets the facade as the displayed value. What’s not cool is that you’ll have to debug what the value actually is if things aren’t working the way you’d expect because the value in the markup will be nothing but a single digit. FUUUUUUUUUUUUUU
… in … is your standard looping construct. It’s the same thing as ngRepeat.
thing¹ for thing² may look familiar if you Coffeescript. Here it’s probably the most confusing part for me, though it’s not nearly as bad now that I’m breaking this down. It’s just saying do thing¹ for each thing².
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I struggled for a long time trying to figure out how ngOptions worked. Then I struggled for a long time trying to figure out how to do it without ngOptions because it’s impossible to read. Do yourself a favor and follow Occam’s Razor.&lt;br&gt;
On Performance&lt;/p&gt;

&lt;p&gt;A coworker pointed out that using ngOptions is superior to ngRepeat because of it’s performance benefits. ngOptions creates a single scope which encapsulates all of your options. ngRepeat creates a new scope for each option element. That’s true. Creating a new scope for each state — resulting in 50 new scopes — is definitely a performance hit. But if you’re using Angular, you obviously don’t care about performance anyway. So. There’s that.&lt;/p&gt;

&lt;p&gt;:trollface:&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>angular</category>
    </item>
    <item>
      <title>On Handlebars and Template Tags</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:26:57 +0000</pubDate>
      <link>https://dev.to/trezy/on-handlebars-and-template-tags-19ic</link>
      <guid>https://dev.to/trezy/on-handlebars-and-template-tags-19ic</guid>
      <description>&lt;p&gt;&lt;strong&gt;This article was originally published on 17 June, 2014 at &lt;a href="https://codepen.io/trezy/post/on-handlebars-and-template-tags"&gt;Codepen.io&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://handlebarsjs.com/"&gt;Handlebars&lt;/a&gt; is &lt;strong&gt;awesome&lt;/strong&gt;. I can separate my template logic from my application logic? Yes, please. When I try to use Handlebars in my local editor, though, it vomits all over those ugly &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags. Fortunately there’s an awesome, future-friendly, spec-compliant solution — the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tags are super cool in a lot of ways. From the &lt;a href="http://www.html5rocks.com/en/tutorials/webcomponents/template/"&gt;HTML5 Rocks article&lt;/a&gt;, here are the pillars of &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tags:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Its content is effectively inert until activated. Essentially, your markup is hidden DOM and does not render.&lt;/li&gt;
&lt;li&gt;Any content within a template won’t have side effects. Script doesn’t run, images don’t load, audio doesn’t play… until the template is used.&lt;/li&gt;
&lt;li&gt;Content is considered not to be in the document. Using &lt;code&gt;document.getElementById()&lt;/code&gt; or &lt;code&gt;querySelector()&lt;/code&gt; in the main page won’t return child nodes of a template.&lt;/li&gt;
&lt;li&gt;Templates can be placed anywhere inside of &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;, or &lt;code&gt;&amp;lt;frameset&amp;gt;&lt;/code&gt; and can contain any type of content which is allowed in those elements. Note that “anywhere” means that &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; can safely be used in places that the HTML parser disallows…all but content model children. It can also be placed as a child of &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&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;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;”cells-to-repeat”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why isn’t this being used elsewhere?
&lt;/h2&gt;

&lt;p&gt;That’s a great question. I can only speculate but I’d reckon it has something to do with the recency / lack of support. &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; is supported in most browsers, though &lt;a href="http://caniuse.com/#search=template"&gt;Can I Use&lt;/a&gt; tells us that we’re lacking support in Internet Explorer (big surprise), Safari 7, and Blackberry. Luckily, we can add &lt;a href="http://jsfiddle.net/brianblakely/h3EmY/"&gt;this shim&lt;/a&gt; if we need to make it work everywhere. You can read more about the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag and how to use it in &lt;a href="http://www.html5rocks.com/en/tutorials/webcomponents/template/"&gt;this tutorial on HTML5 Rocks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the coolest thing, though — current Handlebars users will actually have to write &lt;strong&gt;less&lt;/strong&gt; code. Check it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Handlebars recommended template block syntax --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;”text/x-handlebars-template”&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;”article-template”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/article&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…just swap the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags for &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tags:&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="c"&gt;&amp;lt;!-- The exact same thing using template tags --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;”articleTemplate”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;{{title}}&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    {{content}}
  &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And blammo, you’re using awesome new HTML5 tech. Your editor and I will love you for it. 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  The catch
&lt;/h2&gt;

&lt;p&gt;As &lt;a href="http://codepen.io/joao/"&gt;joao&lt;/a&gt; points out in the &lt;a href="https://codepen.io/trezy/post/on-handlebars-and-template-tags#post-comments"&gt;Codepen comments&lt;/a&gt;, not everything is hunky dory. Take a look at this code:&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;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;”tableTemplate”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
    {{#each}}
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{content}}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    {{/each}}
  &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks legit, right? Unfortunately it breaks in the browser. The parser still requires the code inside the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag to be valid HTML which means you can’t have any content in a table unless it’s also inside a cell (&lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt;). You can, however, create your table cells / rows in a template tag and use them in a table:&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;table&amp;gt;&amp;lt;/table&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;”tableTemplate”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  {{#each}}
    &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;{{content}}&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  {{/each}}
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s not ideal and I would definitely prefer a better DOM API for it. Still, this stuff is super cool and I’ll be using it all over the place. If you take advantage of it, let me know! I’ll leave you with my implementation of &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tags and Handlebars:&lt;/p&gt;

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

</description>
      <category>html</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>On Dropdown Menu Transitions</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:26:20 +0000</pubDate>
      <link>https://dev.to/trezy/on-dropdown-menu-transitions-2bp2</link>
      <guid>https://dev.to/trezy/on-dropdown-menu-transitions-2bp2</guid>
      <description>&lt;p&gt;&lt;strong&gt;This article was originally published on 01 March, 2014 at &lt;a href="https://trezy.com/blog/on-dropdown-menu-transitions"&gt;Trezy.com&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The CSS transition property allows for a lot of really cool effects in your design but it has definitely caused me to bang my head against the desk a few times. Here are some details about the transition property that aren’t very well documented.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer:&lt;/em&gt; At the time of this writing transitions still require browser prefixes to work for Firefox (&lt;code&gt;-moz-&lt;/code&gt;), Opera (&lt;code&gt;-o-&lt;/code&gt;), and Webkit (&lt;code&gt;-webkit-&lt;/code&gt;). I have omitted them from the code examples here for readability, but they will be required if you intend to use these techniques.&lt;/p&gt;

&lt;h2&gt;
  
  
  The long and the short of it
&lt;/h2&gt;

&lt;p&gt;The transition can be broken into several different properties or used in its shorthand form. You can even mix and match depending on what you prefer. The different transition properties that exist are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/CSS/transition"&gt;&lt;code&gt;transition&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/CSS/transition-property"&gt;&lt;code&gt;transition-property&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/CSS/transition-duration"&gt;&lt;code&gt;transition-duration&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/CSS/transition-timing-function"&gt;&lt;code&gt;transition-timing-function&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/CSS/transition-delay"&gt;&lt;code&gt;transition-delay&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of the longhand properties also have their own shorthand form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#2f2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#090&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;transition-property&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;transition-duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;transition-timing-function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nl"&gt;transition-delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&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;Keep in mind that you don’t have to have multiple values for each property. If we were to change &lt;code&gt;transition-duration: 1s, .5s;&lt;/code&gt; to &lt;code&gt;transition-duration: 1s;&lt;/code&gt; then both transitions would use the same duration value. Personally, I prefer the shorthand property because it looks cleaner and it takes less code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;transition-property&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;transition-duration&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;transition-timing-function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;transition-delay&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;timing-function&lt;/code&gt; and &lt;code&gt;delay&lt;/code&gt; are both optional in the shorthand version. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#2f2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#090&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;transition-property&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;background-color&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&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;Both of these blocks of code will create the same functionality so it’s entirely a matter of preference. A final thing of note for &lt;code&gt;transition-property&lt;/code&gt; is that if you don’t change anything between states other than the properties you want animated, you can use &lt;code&gt;all&lt;/code&gt; in place of a list of properties.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transitions swing both ways
&lt;/h2&gt;

&lt;p&gt;It wasn’t until I read &lt;a href="http://www.impressivewebs.com/mimic-onmouseout-css3-transitions/"&gt;this article&lt;/a&gt; from Louis Lazarus that I realized I could use different transitions for different states. If a transition is applied to just one state of an object like in the code examples above it will activate on &lt;code&gt;:hover&lt;/code&gt; (or whatever state you choose) and reverse when the state changes back. However, if each state has a different transition property, it will be applied to the incoming transition. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.menu&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ddd&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;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&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;'Hover me to see the menu'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nc"&gt;.menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#88b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;-webkit-transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;max-height&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;max-width&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;0s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="nc"&gt;.menu&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="nc"&gt;.menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;999px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;-webkit-transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;max-height&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;0s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;max-width&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt; &lt;span class="m"&gt;.5s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;999px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this example when you mouse over the &lt;code&gt;.menu&lt;/code&gt;’s parent div its first transition will come from the &lt;code&gt;div:hover .menu&lt;/code&gt; rule. First, it will grow vertically, then it will grow horizontally. When you mouse off the parent div (or the menu) the &lt;code&gt;.menu&lt;/code&gt; will take it’s transition from the &lt;code&gt;div .menu&lt;/code&gt; rule, first shrinking horizontally, then growing vertically. It’s a little bit confusing but super cool!&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s all in the timing
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;timing-function&lt;/code&gt;s will be familiar to flash developers and video editors that customize the easing on their transitions, timing, and other effects, but they’re likely a foreign concept to most web designers. These functions are already well-described on &lt;a href="https://developer.mozilla.org/en-US/docs/CSS/timing-function"&gt;MDN&lt;/a&gt; and in the &lt;a href="http://dev.w3.org/csswg/css-transitions/#transition-timing-function"&gt;W3C spec&lt;/a&gt; so I’ll just give a brief description of each them here.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ease&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the default setting for &lt;code&gt;timing-function&lt;/code&gt; so unless you’re using the longhand &lt;code&gt;transition-timing-function&lt;/code&gt; with multiple properties, declaring it is unnecessary. It will ease both the in and out points of the animation with a slightly sharper curve on the in than the out. Basically it’s faster in the middle than at the beginning or the end, and the beginning accelerates a little faster than the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ease-in&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is similar to &lt;code&gt;ease&lt;/code&gt; but it has a longer in point curve (slower acceleration) and an abrupt stop.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ease-out&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The opposite of &lt;code&gt;ease-in&lt;/code&gt;, this has a longer out point curve (slower… slowing?). Basically it starts abruptly and slows down as it gets closer to the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ease-in-out&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;I thought the existence of this one was odd since we already have the basic &lt;code&gt;ease&lt;/code&gt; function. However, there is a slight difference. &lt;code&gt;ease-in-out&lt;/code&gt; actually has an equal in and out curve, whereas &lt;code&gt;ease&lt;/code&gt; has a slightly sharper in curve. The actual animation will have an equally slow beginning and end.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;linear&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This function has a straight line from beginning to end. This means it will have an unchanging speed with an abrupt start and stop.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;step-start&lt;/code&gt; / &lt;code&gt;step-end&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;What the purpose of these two functions is, I have no idea. I am sure that they have their uses somewhere. With &lt;code&gt;step-start&lt;/code&gt;, it will make the switch for the transition at the beginning of the duration, then does nothing until the end of the duration. The &lt;code&gt;step-end&lt;/code&gt; function does the opposite, waiting for the end of the duration, then applying the changes suddenly. These are not smooth transitions at all but rather changes with delays built in.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;steps(number_of_steps, direction)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Much more useful than the previous step functions, &lt;code&gt;steps()&lt;/code&gt; allows you to spread your animation across several abrupt changes for the duration of your transition. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When hovering over this link it would immediately grow incrementally from 100px to 200px instead of moving through a smooth transition. These are literally immediate transitions, similar to if there were no transition at all. The &lt;code&gt;direction&lt;/code&gt; (in this case &lt;code&gt;start&lt;/code&gt;) is the same as the suffixes for &lt;code&gt;step-start&lt;/code&gt; and &lt;code&gt;step-end&lt;/code&gt;, determining whether the changes begin at the beginning or end of each step. The default value for &lt;code&gt;direction&lt;/code&gt; is &lt;code&gt;end&lt;/code&gt; but the parameter is not optional so &lt;code&gt;steps(2)&lt;/code&gt; will not work.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;cubic-bezier(x1, y1, x2, y2)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the mother of all &lt;code&gt;timing-function&lt;/code&gt;s, giving you ultimate control over the timing of your transitions. All of the other functions except for &lt;code&gt;steps()&lt;/code&gt; can be defined using &lt;code&gt;cubic-bezier()&lt;/code&gt;. However, it can be extremely complicated, so I’ll leave you to your own devices here. I highly recommend checking out the &lt;a href="https://developer.mozilla.org/en-US/docs/CSS/timing-function#The_cubic-bezier%28%29_class_of_timing-functions"&gt;MDN&lt;/a&gt; article about it for a really brilliant explanation.&lt;/p&gt;

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

&lt;p&gt;Talk about dissemination of information, these dogs are cooked! And by dogs I mean fingers. Not that I have huge fingers or anything, just… are you calling me fat? Anywho, leave a comment if you have any questions or if you figure out some super awesome combination of transitions.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>On Advanced Box Shadows</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:25:31 +0000</pubDate>
      <link>https://dev.to/trezy/on-advanced-box-shadows-51cf</link>
      <guid>https://dev.to/trezy/on-advanced-box-shadows-51cf</guid>
      <description>&lt;p&gt;&lt;strong&gt;This article was originally published on 03 December, 2013 at &lt;a href="https://trezy.com/blog/on-advanced-box-shadows"&gt;Trezy.com&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;box-shadow&lt;/code&gt; is arguably one of the coolest things to come out of CSS3. However I’ve been creating shadows in Adobe Fireworks and Photoshop for years so I feel like I’m too constrained by CSS3’s &lt;code&gt;box-shadow&lt;/code&gt; implementation. In an effort to expand my boxy horizons, I set out on a quest to create some cooler shadows.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer:&lt;/em&gt; At the time of this writing filters and transforms still require browser prefixes to work, though filters will only work in Webkit browsers. I have omitted these prefixes from the code examples here for readability but they will be required if you intend to use these techniques.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rocking out with box-shadow
&lt;/h2&gt;

&lt;p&gt;My first attempt at making my shadows more dynamic still uses &lt;code&gt;box-shadow&lt;/code&gt; but it extends its use to create a new effect. My main goal was to avoid using any extra elements, so all we need is a div and we’ll leverage pseudo elements to do the rest of the work.&lt;/p&gt;

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

&lt;p&gt;What we’ve done is created two transparent pseudo elements behind our main element. These two pseudo elements then have &lt;code&gt;box-shadow&lt;/code&gt; applied. This is done so that we can use 2D transforms to angle them, creating a 3D looking &lt;code&gt;box-shadow&lt;/code&gt; for their parent element.&lt;/p&gt;

&lt;p&gt;We also used the &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;bottom&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt;, and &lt;code&gt;right&lt;/code&gt; properties to keep the shadow from spilling out from the sides of the parent element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Box-shadow… without box-shadow?
&lt;/h2&gt;

&lt;p&gt;I was pretty happy with the previous idea, but it didn’t look as awesome as I hoped. My next idea was to create the same effect using gradients.&lt;/p&gt;

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

&lt;p&gt;This time we’re still using our pseudo elements but instead of giving them &lt;code&gt;box-shadows&lt;/code&gt;, we’ll give them gradients. We also used a new CSS3 property called &lt;code&gt;filter&lt;/code&gt;. Make sure to check out all the nifty things it can do &lt;a href="https://html5-demos.appspot.com/static/css/filters/index.html"&gt;here&lt;/a&gt;. We just use the blur to soften the edges and make it look more like a shadow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Oooooh… that’s way prettier.
&lt;/h2&gt;

&lt;p&gt;While I was working on this project I ran across a site with an even cooler style of drop-shadow that pointed inward rather than outward:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://demo.truethemes.net/Karma-Wordpress/"&gt;Karma&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All I really had to do was flip my last idea and we were good to go!&lt;/p&gt;

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

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

&lt;p&gt;If you use any of these drop shadows, post a link in the comments! Also, if you come up with any alternative ideas or issues that should be noted, let me know.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>On Saving Characters</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:24:26 +0000</pubDate>
      <link>https://dev.to/trezy/on-saving-characters-2240</link>
      <guid>https://dev.to/trezy/on-saving-characters-2240</guid>
      <description>&lt;h2&gt;
  
  
  Recently I discovered something mind-blowing that I feel like I should have known for years.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This article was originally published on 06 May, 2013 at &lt;a href="https://trezy.com/blog/on-saving-characters"&gt;Trezy.com&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I write my sans-serif font-family stack in my CSS file I normally use this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://fonts.google.com/specimen/Ubuntu"&gt;Ubuntu&lt;/a&gt; is one of my favorite fonts which I import from &lt;a href="https://fonts.google.com"&gt;Google Fonts&lt;/a&gt; but you can replace it with whatever custom font you want. Since I prefer Helvetica over Arial, it's the next font on the list which I'm hoping they have preinstalled. If not the stack falls back to Arial, then the default &lt;code&gt;sans-serif&lt;/code&gt; system font.&lt;/p&gt;

&lt;p&gt;Now I've been writing my font stack this way for several years (sans the custom font) completely oblivious to the ridiculously obvious fact that half of the stack isn't necessary. The &lt;code&gt;sans-serif&lt;/code&gt; piece of the stack asks for the system's preferred &lt;code&gt;sans-serif&lt;/code&gt; font which, by default, is Arial on Windows and Helvetica on Mac. If I'm not concerned about the user having changed their default &lt;code&gt;sans-serif&lt;/code&gt; font, I can cut 16 characters (not including spaces) out of my font stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I realized this a couple days ago, I subjected myself to an hour of staring at terrible websites as punishment for my ignorance. After recuperating from the debacle I decided to take a closer look at my new font stack. The only issue I have with it is that I don't trust my Windows users to not have changed their default system font to &lt;a href="https://bancomicsans.com/main/"&gt;Comic Sans&lt;/a&gt; or &lt;a href="https://trezy.com/blog/christmas-time-with-papyrus"&gt;Papyrus&lt;/a&gt;. Fortunately, Windows will fallback to Arial if you declare Helvetica and it's not installed! When it's all said and done our font stack should like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not a performance saver and it's not going to impress anybody - in fact you may look like an idiot if you admit to not having known this already - but it's a nice piece of info to have when writing your font stacks.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>On Variables, Calculations, and New Units</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:21:41 +0000</pubDate>
      <link>https://dev.to/trezy/on-variables-calculations-and-new-units-4gn0</link>
      <guid>https://dev.to/trezy/on-variables-calculations-and-new-units-4gn0</guid>
      <description>&lt;p&gt;&lt;strong&gt;This article was originally published on 15 December, 2012 at &lt;a href="https://trezy.com/blog/on-variables-calculations-and-new-units"&gt;Trezy.com&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer:&lt;/em&gt; Alright, don't get too excited. This stuff isn't backwards-compatible &lt;em&gt;at all&lt;/em&gt;. However, there are fallback solutions and it's pretty darn cool that it's actually being spec'd.&lt;/p&gt;

&lt;p&gt;Web designers were begging for CSS to add variables and calculations for years before &lt;a href="https://lesscss.org"&gt;LESS&lt;/a&gt; and &lt;a href="https://sass-lang.org"&gt;SASS&lt;/a&gt; came along, giving us the ability to use these shiny new toys to our heart's content. However, SASS and LESS output can sometimes bloat your CSS sheets and while it's pretty fun to play with, it's a pain to have to recompile your CSS after every change. Fortunately, the W3C has come in like the proverbial nanny and started giving them a spit shine to make them all fresh and new again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Variables
&lt;/h2&gt;

&lt;p&gt;Mmmmmmmmm, variables. We've used them in almost every language but CSS… Until now. Admittedly, CSS variables are quite a long way off. They're still in a W3C Level 1 module so you won't be able to play with them for a while unless you want to get into the &lt;a href="https://nightly.webkit.org"&gt;Webkit nightly builds&lt;/a&gt;. Still, it's fun to think about all of the amazing things we're going to be doing with them in a year…&lt;/p&gt;

&lt;p&gt;Here's what variables might look like in CSS3. Keep in mind that since it's still Level 1, it's subject to change. To declare a variable, you'll create it inside an element. All of the examples are declaring them in the &lt;code&gt;:root{}&lt;/code&gt; using the &lt;code&gt;var&lt;/code&gt; prefix like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="py"&gt;var-mainColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0c0&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 can then call the variables later on in the code by using the &lt;code&gt;var()&lt;/code&gt; syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainColor&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;My main use for this in CSS has been dealing with branding colors. I can set all of the branding colors in the top of the stylesheet and use the variables throughout code, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="py"&gt;var-primaryColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0d56a6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="py"&gt;var-secondaryColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4186d3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="py"&gt;var-tertiaryColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#689ad3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;header&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primaryColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;nav&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secondaryColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;article&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tertiaryColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="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="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nb"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primaryColor&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secondaryColor&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tertiaryColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;
   &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this point on if I want to change the color scheme I can just change the colors in my &lt;code&gt;:root&lt;/code&gt; element and they'll change across the entire website! I do hope, however, that before the spec is released we get the ability to create full property set variables that work like SASS mixins. The ability to do something like this would be stupendous:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;var&lt;/span&gt; &lt;span class="nt"&gt;gradient&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;color1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;color2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;color3&lt;/span&gt;&lt;span class="o"&gt;)&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="n"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nb"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color1&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color2&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="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color3&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="nt"&gt;article&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="err"&gt;gradient(#0d56a6,&lt;/span&gt; &lt;span class="err"&gt;#4186d3,&lt;/span&gt; &lt;span class="err"&gt;#689ad3);&lt;/span&gt;
 &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#000&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="http://dev.w3.org/csswg/css-variables/"&gt;W3C Module&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Calculations
&lt;/h2&gt;

&lt;p&gt;Calculations are in a W3C Level 3 module, meaning they're pretty close to making it into the CSS3 full spec. If all goes well, we'll be able to consider them totally safe to use come next June. However, we can already play with them in the latest version of Chrome, Firefox, Opera, and Safari, as well as IE9/10.&lt;/p&gt;

&lt;p&gt;So why are calculations so exciting? How about this horizontal centering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;960px&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;-2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;960px&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://developer.mozilla.org/en-US/docs/CSS/calc"&gt;MDN Page&lt;/a&gt; | &lt;a href="https://developer.mozilla.org/en-US/docs/CSS/calc"&gt;W3C Module&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Units
&lt;/h2&gt;

&lt;p&gt;There are some really snazzy new units coming with CSS3 but the ones I'm most excited about are &lt;code&gt;rem&lt;/code&gt;, &lt;code&gt;vw&lt;/code&gt;, &lt;code&gt;vh&lt;/code&gt;, &lt;code&gt;vmin&lt;/code&gt;, and &lt;code&gt;vmax&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  rem
&lt;/h3&gt;

&lt;p&gt;We're all aware of the &lt;code&gt;em&lt;/code&gt; which we're encouraged to use for the sake of magnified page viewing. However, I've avoided them for quite sometime because they're a major pain in the ass to try to calculate. I don't like having to figure out what my em value is based on it's parent's calculated value which is based on it's parent's calculated value which is based on it's parent's calculated value which is… It just sucks. The &lt;code&gt;rem&lt;/code&gt;, however, is here to save the day! The &lt;code&gt;rem&lt;/code&gt; is similar to the &lt;code&gt;em&lt;/code&gt; except that it's always relative to the &lt;code&gt;em&lt;/code&gt; value of the root of the page. Take this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.box1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.box1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.box2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.box3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.box3&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;.box4&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;.box2&lt;/code&gt; will have a font-size of 80px (2em of 20px = 40px, then 2em of 2em of 20px = 80px) but &lt;code&gt;.box4&lt;/code&gt; will have a font-size of 20px (.box3 would be 3rem of 20px = 60px, &lt;code&gt;.box4&lt;/code&gt; if 1rem of 20px = 20px). It's actually even more complicated than that, but this is the general way to figure everything up. &lt;code&gt;rem&lt;/code&gt;s are much easier to use then &lt;code&gt;em&lt;/code&gt;s, hands down.&lt;/p&gt;

&lt;h3&gt;
  
  
  vw and vh
&lt;/h3&gt;

&lt;p&gt;Even more awesome are the units that calculate based on the size of the viewport! &lt;code&gt;vw&lt;/code&gt; and &lt;code&gt;vh&lt;/code&gt; are percentages of the viewport width and height, respectively. Each &lt;code&gt;vw&lt;/code&gt;/&lt;code&gt;vh&lt;/code&gt; is 1% of the viewport size, so think about this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;nav&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;100vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this you can create a navbar with 5 elements that is always the same size as the viewport! The &lt;code&gt;min-width&lt;/code&gt; also makes sure that the links will never be too small so you can stack them or turn them into a vertical menu for super tiny screens.&lt;/p&gt;

&lt;h3&gt;
  
  
  vmin and vmax
&lt;/h3&gt;

&lt;p&gt;These guys are always relative to the larger or smaller size between the &lt;code&gt;vh&lt;/code&gt; and &lt;code&gt;vw&lt;/code&gt;. In other words, if the width of the viewport is smaller than the height (maybe its a smartphone in portrait mode) then the &lt;code&gt;vmin&lt;/code&gt; will be relative to the width and the &lt;code&gt;vmax&lt;/code&gt; will be relative to the height.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.w3.org/TR/css3-values/"&gt;W3C Module&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>HTML Elements: Menu vs. Nav</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Tue, 04 Jun 2019 03:20:50 +0000</pubDate>
      <link>https://dev.to/trezy/html-elements-menu-vs-nav-306a</link>
      <guid>https://dev.to/trezy/html-elements-menu-vs-nav-306a</guid>
      <description>&lt;h2&gt;
  
  
  …or Why the Hamburger Icon is Awesome.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This article was originally published on 16 April, 2015 at &lt;a href="https://codepen.io/trezy/post/menu-vs-nav-or-why-the-hamburger-icon-is-awesome"&gt;Codepen.io&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've read plenty of anti-hamburger icon posts that came out after Mike Stern's rant at WWDC '14. The issue I take with those articles - and Mike's rant, for that matter - is that they aren't addressing the icon. They're addressing the menu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hamburger Icon vs. Hamburger Menu
&lt;/h2&gt;

&lt;p&gt;The hamburger icon - three vertically stacked horizontal bars - is most often the iconography selected for a button that opens an action menu. The terms used to refer to that menu are vast in number and so I'll not attempt to list them all but I can at least give you the most common: drawer, sidebar, or - least commonly - a hamburger menu. The hamburger icon typically does what you would expect based on it's design. The hamburger menu, however, can be virtually anything from a list of pages on a website to a multi-tiered tree of navigation allowing you to traverse your overly complicated email labeling system.&lt;/p&gt;

&lt;p&gt;The issue is that the icon is the one that's getting a bad rep as if it did something wrong when that could be no further from the truth. The icon does exactly what you would expect it to - open a visual representation of itself. Typically, however, the menu is the one causing all the ruckus. WTF, mang?&lt;/p&gt;

&lt;p&gt;W.&lt;br&gt;
T.&lt;br&gt;
&lt;strong&gt;F.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Menu vs. Nav
&lt;/h2&gt;

&lt;p&gt;To explain why the menu is causing so much fuss I feel like I need to clear up a terrible ambiguity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Menus
&lt;/h3&gt;

&lt;p&gt;Menus are, in their most basic form, intended to facilitate action. When you right-click on a selection and you see &lt;code&gt;cut&lt;/code&gt;, &lt;code&gt;copy&lt;/code&gt;, and &lt;code&gt;paste&lt;/code&gt;? That's a menu. &lt;code&gt;Save&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; buttons? Those should be in a menu. HTML5 even added a &lt;code&gt;&amp;lt;menu&amp;gt;&lt;/code&gt; tag with some super sweet features built into it. Check out this pen for an example of my typical usage of the element.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navs
&lt;/h3&gt;

&lt;p&gt;Navs are (I would hope obviously) intended for navigation. If I click a button or link in a &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; element then I should be taken to an entirely new page. It should be like a wondrous adventure to a new, far off land where unicorns roam free and everybody is eating s'mores and pooping rainbows. The most actionable thing you should do when I click on a link is prompt me about unsaved changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Any Of This Matter?
&lt;/h2&gt;

&lt;p&gt;The main argument that Mike and the rest of the anti-hamburger movement makes is that it's bad UX when the menu pops out and covers up the rest of your perfect, delicately designed interface. That's totally legit. If I have to cover up whatever I'm doing to cut the paragraph I just selected? You better believe I'm gonna find a better text editor.&lt;/p&gt;

&lt;p&gt;However, if this is the navigation I'll be using to take myself to Magic Unicornland™ then I already have intentions of leaving the page. Eff that stupid interface of yours, I just want to get where I'm going.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Point
&lt;/h2&gt;

&lt;p&gt;I've been hemming and hawing but for why? It's because the hamburger icon? That guy is my bro. I always turn to him when I don't have enough unicorns in my life. Menus? They're my bros, too, they just aren't used correctly as often as they should be.&lt;/p&gt;

</description>
      <category>html</category>
      <category>webdev</category>
      <category>ux</category>
    </item>
    <item>
      <title>On CSS Tooltips</title>
      <dc:creator>Trezy</dc:creator>
      <pubDate>Mon, 03 Jun 2019 20:52:06 +0000</pubDate>
      <link>https://dev.to/trezy/on-css-tooltips-1foi</link>
      <guid>https://dev.to/trezy/on-css-tooltips-1foi</guid>
      <description>&lt;p&gt;&lt;strong&gt;This article was originally published on 05 October, 2012 at &lt;a href="https://trezy.com/blog/on-css-tooltips"&gt;Trezy.com&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pure CSS tooltips have been a thing for a while now but all of the solutions I've found have had limitations. After reading through Louis Lazaris's article &lt;a href="http://www.impressivewebs.com/pure-css-tool-tips/"&gt;Pure CSS Tool Tips Revisited&lt;/a&gt; over at &lt;a href="https://impressivewebs.com"&gt;ImpressiveWebs&lt;/a&gt;, I decided to make a few modifications of my own to his design.&lt;/p&gt;

&lt;p&gt;Check Out the Demo&lt;/p&gt;

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

&lt;p&gt;Louis's design broke some of the boundaries but still had some limitations. These were my goals:&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiline
&lt;/h3&gt;

&lt;p&gt;Louis makes the argument that tooltips are only supposed to contain a small amount of information, eliminating the need for multiline tooltips. I agree with him to an extent, but I still think there are cases in which you would want a multiline tooltip. In my example, I am creating an error message rather than your average tooltip. I wanted my first line to be only the error type, then all of the following lines would contain the error message.&lt;/p&gt;

&lt;h3&gt;
  
  
  IE8 Compatible
&lt;/h3&gt;

&lt;p&gt;This was a big one since the company I'm doing this project for requires it. Fortunately we only have to support IE8, Firefox, and Webkit. Keep in mind, however, that this also means I don't know how this code will react in IE7 and below.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Extra HTML
&lt;/h3&gt;

&lt;p&gt;Some other pure CSS tooltip solutions use extra elements, like placeholder spans or divs. I wanted to be able to pull in all of the information I needed without any extra elements. I bend the extra HTML rule a little bit since we do use an element's attributes to populate the tooltip but I think I can still live with myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;If you check out the pen, you may notice the custom &lt;code&gt;data-&lt;/code&gt; attributes on the link. The &lt;code&gt;data-tooltip&lt;/code&gt; attribute is binary, meaning it's either set or it's not, just like &lt;code&gt;required&lt;/code&gt;. I'll be using jQuery to create and populate the other two attributes in the final project but for now we'll just use some bunk data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pseudo-classes and Uncommon Attributes
&lt;/h3&gt;

&lt;p&gt;Most pseudo-classes describe some state of an element, i.e. &lt;code&gt;:hover&lt;/code&gt; applies when the element is being hovered, &lt;code&gt;:focus&lt;/code&gt; applies to form elements that are in focus, &lt;code&gt;:disabled&lt;/code&gt; applies to elements that are disabled, etc. However, &lt;code&gt;:before&lt;/code&gt; and &lt;code&gt;:after&lt;/code&gt; are a little different. They are used to prepend and append, respectively, content to an element. For example you could use &lt;code&gt;.emailAddress:before&lt;/code&gt; to append a label to the internal node of every element with a class of &lt;code&gt;emailAddress&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You have probably seen most of this CSS before, though we're using a couple of pretty uncommon attributes. The &lt;code&gt;content&lt;/code&gt; attribute only works with the &lt;code&gt;:before&lt;/code&gt; and &lt;code&gt;:after&lt;/code&gt; pseudo-classes. It determines what to prepend/append to the element. In this case we're using a pretty cool argument called &lt;code&gt;attr(x)&lt;/code&gt;. It allows you to use the value from any attribute applied to the element as the content of the prepended/appended element. In our case we used the custom &lt;code&gt;data-&lt;/code&gt; attributes we set earlier.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;white-space&lt;/code&gt; is another strange one. It's used to determine how white space (spaces and returns) should be handled inside of an element. We used &lt;code&gt;white-space:pre-wrap;&lt;/code&gt; so that the spaces inside the &lt;code&gt;content&lt;/code&gt; attribute would be preserved, specifically the &lt;code&gt;\A&lt;/code&gt; which is a Unicode carriage return, pretty much the only way to ensure that the line breaks where we want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Positioning
&lt;/h3&gt;

&lt;p&gt;This was the most important point to allowing multiline tooltips. Some previous solutions have used percentage positioning, some used pixel positioning, but they all used the &lt;code&gt;top&lt;/code&gt; and &lt;code&gt;left&lt;/code&gt; attributes. However these always break if you have more than one line so they are often used with &lt;code&gt;white-space:nowrap;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead of positioning negatively based on the top position of the element like Louis did, I set the top position of the tooltip to zero so it would line up with the top of the element, then gave the tooltip a &lt;code&gt;margin-top&lt;/code&gt;. In my example, I'm placing the tooltip on a link so I set the bottom margin to 1em, ensuring the margin would always be the same height as my text. This may need to be adjusted depending on your line-height.&lt;/p&gt;

&lt;p&gt;If you're not positioning the tooltip on a line of text then you can also set your margin to match the height of a static height element, or use some jQuery magic to adjust it.&lt;/p&gt;

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

&lt;p&gt;The rest of this code is pretty standard stuff. One other peculiar thing we're doing here is using the &lt;code&gt;:before&lt;/code&gt; to create the arrow on the bottom of the tooltip. &lt;a href="http://www.impressivewebs.com/pure-css-tool-tips/"&gt;Louis's article&lt;/a&gt; explains that part a bit and there are plenty of other tutorials on creating shapes using divs and borders so I won't cover that.&lt;/p&gt;

&lt;p&gt;I've tested this in all of the necessary browsers (IE8+, Firefox, and Google Chrome) and haven't seen any issues yet. If you run into an issue or have a recommendation for making it even better, let me know in the comments! I'll do another tutorial in the future about how to make this guy extensible using jQuery. 😉&lt;/p&gt;

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