<?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: Jon Kantner</title>
    <description>The latest articles on DEV Community by Jon Kantner (@jonkantner).</description>
    <link>https://dev.to/jonkantner</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%2F465341%2F5bfc25e4-97a5-4c70-8103-6e355df84f52.jpg</url>
      <title>DEV Community: Jon Kantner</title>
      <link>https://dev.to/jonkantner</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonkantner"/>
    <language>en</language>
    <item>
      <title>Fitting Canvas Snow In a Tweet</title>
      <dc:creator>Jon Kantner</dc:creator>
      <pubDate>Mon, 08 Feb 2021 17:31:29 +0000</pubDate>
      <link>https://dev.to/jonkantner/canvas-snow-in-a-tweet-2433</link>
      <guid>https://dev.to/jonkantner/canvas-snow-in-a-tweet-2433</guid>
      <description>&lt;p&gt;Last year before Christmas, I created this snowfall animation in 257 bytes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhbbi8c3tfoqenb9ahj88.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhbbi8c3tfoqenb9ahj88.gif" alt="Output of the code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s not just the JavaScript portion but the entire source, and it fits well in Twitter’s 280-character limit. If you haven’t already checked out my 278-byte &lt;a href="https://dev.to/jonkantner/fitting-flappy-bird-into-a-tweet-484h"&gt;Flappy Bird&lt;/a&gt;, I’ll demystify this snowfall in a similar fashion.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;Here’s the whole code with line breaks, tabs, and spaces for better readability.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body onload="
    c = C.getContext('2d');
    R = Math.random;
    H = 164;
    F = [];
    f = 99;
    while (f--)
        F[f] = {
            y: R() * H,
            s: R()
        };
    setInterval(`
        c.fillRect(x = 0,0,300,H);
        for (f of F) {
        c.font = 28 * f.s + 'q a';
        f.y = f.y % H + f.s;
        c.fillText('*',x,f.y);
        x += 3;
        c.fillStyle = x &amp;gt; 294 ? '#000' : '#fff'
        }
    `,9)
"&amp;gt;
&amp;lt;canvas id=C&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a single letter for every variable is essential for writing minimal code. In addition, JavaScript minifiers often do this and should be to help reduce script size when talking web performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tags and Attributes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body onload=""&amp;gt;
&amp;lt;canvas id=C&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the HTML we’ll ever need here is an opening &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; tag. Since no other elements will follow, we can omit the closing tags. As a result, we save 16 bytes (7 for &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt; and 9 for &lt;code&gt;&amp;lt;/canvas&amp;gt;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Since JavaScript lets us to use element IDs as variables, I used only &lt;code&gt;C&lt;/code&gt; here for the canvas. Although attributes of one value may not require quotes, we still need them for the body’s &lt;code&gt;onload&lt;/code&gt; because having &lt;code&gt;'2d'&lt;/code&gt; in &lt;code&gt;.getContext('2d')&lt;/code&gt; as a value in quotes, the browser will treat all else before and after it as separate attribute-value pairs. Then some &lt;code&gt;=&lt;/code&gt;s will become invalid HTML syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context, Main Variables, and Snowflake Array
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c = C.getContext('2d');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned earlier, we can use the canvas ID like a variable; using &lt;code&gt;document.getElementById('C')&lt;/code&gt; or &lt;code&gt;document.querySelector('#C')&lt;/code&gt; would just rack up the expense.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;R = Math.random;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we’re using &lt;code&gt;Math.random()&lt;/code&gt; more than once for randomizing the starting snowflake positions, we can assign &lt;code&gt;R&lt;/code&gt; the function. Then we’d save 10 bytes per use of &lt;code&gt;R()&lt;/code&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H = 164;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;H&lt;/code&gt; is the height of the canvas (150) plus enough space (14) past the bottom so that when snowflakes are moved back to the top, it doesn’t look like they magically disappear.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;F = [];
f = 99;
while (f--)
    F[f] = {
        y: R() * H,
        s: R()
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last chunk of code before the &lt;code&gt;setInterval()&lt;/code&gt; is where we generate 99 snowflakes as well as determine their starting y-positions (&lt;code&gt;y&lt;/code&gt;) and speeds (&lt;code&gt;s&lt;/code&gt;). For the random values, we use our byte-saving &lt;code&gt;R()&lt;/code&gt; function. Rather than using a &lt;code&gt;for&lt;/code&gt; loop of any kind and &lt;code&gt;.push()&lt;/code&gt; to supply the &lt;code&gt;F&lt;/code&gt; array, we can use fewer bytes with a &lt;code&gt;while&lt;/code&gt; loop with a counter starting at 99. Then we can append each snowflake object using &lt;code&gt;F[f]=&lt;/code&gt;, which is 3 bytes cheaper than &lt;code&gt;F.push()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Animation Loop
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setInterval(`
    c.fillRect(x = 0,0,300,H);
    for (f of F) {
        c.font = 28 * f.s + 'q a';
        f.y = f.y % H + f.s;
        c.fillText('*',x,f.y);
        x += 3;
        c.fillStyle = x &amp;gt; 296 ? '#000' : '#fff'
    }
`,9)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;setInterval()&lt;/code&gt; here is where all the logic and drawing happens. Although I don’t recommend doing it anyway due to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval#parameters" rel="noopener noreferrer"&gt;security concerns&lt;/a&gt;, you can supply the whole function as a string or template literal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c.fillRect(x = 0,0,300,H);
for (f of F) {
    . . .
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While filling the screen black by default for the first statement, we set &lt;code&gt;x&lt;/code&gt; equal to 0 for the x-position of the first snowflake. In the &lt;code&gt;for...of&lt;/code&gt; loop contents we’re about to explore, the &lt;code&gt;x&lt;/code&gt; will come in handy for horizontally placing the snowflakes without using too many bytes, and we’ll see how later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c.font = 28 * f.s + 'q a';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first statement in the &lt;code&gt;for...of&lt;/code&gt; loop, we set a maximum font size of &lt;code&gt;28q&lt;/code&gt;. I normally don’t use the &lt;code&gt;q&lt;/code&gt; unit, but it happens to be great for code golfing because every other unit is at least a character longer. Then multiplying the font size by snowflake speed (&lt;code&gt;f.s&lt;/code&gt;), we’ll get the visual depth we want. The smaller the snowflake, the further away and slower in movement it’ll appear. By the way as you’ve seen earlier in the whole chunk of code, the asterisk (*) will be the snowflake. Then as part of getting the desired shape, we can use &lt;code&gt;a&lt;/code&gt; as a single-letter fake font family that will be rendered as the browser default. If we were to leave it out in attempt to save 2 more bytes, however, the snowflakes would wind up as dots.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f.y = f.y % H + f.s;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next statement moves each snowflake downward. By using &lt;code&gt;f.y % H&lt;/code&gt;, each snowflake will be kept in its 0-164 range when its &lt;code&gt;y&lt;/code&gt; finally exceeds &lt;code&gt;H&lt;/code&gt; through adding &lt;code&gt;f.s&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c.fillText('*',x,f.y);
x += 3;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once having the needed position, we throw in the snowflake itself. After that we evenly space out all 99 snowflakes as possible across the canvas by dividing the default canvas width of 300 by 99 and rounding the result, which will be 3. That’s what we use to increment &lt;code&gt;x&lt;/code&gt;. The reason we did not give snowflakes their own &lt;code&gt;x&lt;/code&gt; property is that obviously more bytes will be wasted if we used &lt;code&gt;f.x&lt;/code&gt;. So that explains our use of &lt;code&gt;x&lt;/code&gt; in the &lt;code&gt;.fillRect()&lt;/code&gt; from earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c.fillStyle = x &amp;gt; 294 ? '#000' : '#fff'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last statement in the loop determines when to switch fills. Since the last snowflake will be located at &lt;code&gt;x&lt;/code&gt; = 294 ((&lt;code&gt;x&lt;/code&gt; increment of 3) × (99 snowflakes) - (&lt;code&gt;x&lt;/code&gt; increment of 3)), we can set the fill black for the background when &lt;code&gt;x&lt;/code&gt; is finally greater than it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setInterval(`
    . . .
`,9)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally for the sake of cutting bytes, a single-digit interval of 9 milliseconds sets a comfortable animation speed.&lt;/p&gt;

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

&lt;p&gt;There you have it, a wintery scene in about a quarter of a kilobyte! The key parts of this have been:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Turning a built-in JavaScript function &lt;code&gt;Math.random&lt;/code&gt; into a single letter if using more than once&lt;/li&gt;
&lt;li&gt;Changing how we may normally populate arrays&lt;/li&gt;
&lt;li&gt;Not using a certain property if a pattern can be determined without it (&lt;code&gt;x&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Tolerating defaults&lt;/li&gt;
&lt;/ul&gt;

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

</description>
      <category>html</category>
      <category>javascript</category>
      <category>codegolf</category>
      <category>twitter</category>
    </item>
    <item>
      <title>How to Create Simple Skeuomorphic Buttons in CSS</title>
      <dc:creator>Jon Kantner</dc:creator>
      <pubDate>Thu, 24 Sep 2020 16:14:20 +0000</pubDate>
      <link>https://dev.to/jonkantner/how-to-create-simple-skeuomorphic-buttons-in-css-3gf4</link>
      <guid>https://dev.to/jonkantner/how-to-create-simple-skeuomorphic-buttons-in-css-3gf4</guid>
      <description>&lt;p&gt;If you’re a fan of skeuomorphism, then this tutorial on creating buttons in that style is for you. Skeuomorphic buttons you find in the wild can take all sorts of forms, but we’ll create a basic one similar to what I’ve used in &lt;a href="https://codepen.io/jkantner/pen/xxVPbeB" rel="noopener noreferrer"&gt;this Pen&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Normal State
&lt;/h2&gt;

&lt;p&gt;To start off with the initial button state, here’s the HTML you’ll need:&lt;/p&gt;

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

&amp;lt;button&amp;gt;
    &amp;lt;span tabindex="-1"&amp;gt;Button&amp;lt;/span&amp;gt;
&amp;lt;/button&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;The reason for the &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; with that &lt;code&gt;tabindex&lt;/code&gt; is for pulling off the keyboard-only focus later. We could use &lt;code&gt;:focus-visible&lt;/code&gt; in CSS here, but just for deeper browser support we’ll adopt &lt;a href="https://www.kizu.ru/keyboard-only-focus/" rel="noopener noreferrer"&gt;Roman Komarov’s approach&lt;/a&gt; as already used.&lt;/p&gt;

&lt;p&gt;For better organization and productivity, we’ll do all styling in Sass (SCSS syntax). Then we start with a flat-colored button without any states as well as two variables for the button background and text color (&lt;code&gt;$btnColor&lt;/code&gt;, &lt;code&gt;$btnTextColor&lt;/code&gt;).&lt;/p&gt;

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

body {
    background: #c7cad1;
}
button {
    $btnColor: #0053d0;
    $btnTextColor: #fff;
    background: $btnColor;
    border: 0 {
        radius: 0.375em;
    };
    color: $btnTextColor;
    cursor: pointer;
    font: 24px/1.5 sans-serif;
    margin: 1.5em auto;
    padding: 0.5em 1em;
    -webkit-tap-highlight-color: transparent;
    &amp;amp;, span {
        display: block;
    }
}


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

&lt;/div&gt;

&lt;p&gt;There are a couple key things here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Having a slightly dark enough page background for the body (or whatever the parent element should be) will allow all edges of the button hole to be seen.&lt;/li&gt;
&lt;li&gt;We clear the &lt;code&gt;-webkit-tap-highlight-color&lt;/code&gt; to avoid the brief dark highlight on Apple devices.&lt;/li&gt;
&lt;li&gt;Both the button and text span should be &lt;code&gt;display: block&lt;/code&gt; to allow transitions near the end.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far, here’s what we have:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzqb1w8hw9db19ibk3siy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzqb1w8hw9db19ibk3siy.png" alt="Solid blue button with the text “Button”"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we apply the look. We’ll need more variables after &lt;code&gt;$btnTextColor&lt;/code&gt; for the button edge, edge of the button hole, drop shadow color, dark edges, lighter edges, and a dark edge adopting more of the button color.&lt;/p&gt;

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

button {
    . . .
    $btnEdge: 0.2em;
    $btnHoleEdge: 0.1em;
    $dropShadowColor: rgba(0,0,0,0.47);
    $darkEdgeColor: rgba(0,0,0,0.27);
    $lightEdgeColor: rgba(255,255,255,0.27);
    $coloredDarkEdgeColor: darken($btnColor,10%);
    . . .
}


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

&lt;/div&gt;

&lt;p&gt;Next, anywhere before &lt;code&gt;&amp;amp;, span { }&lt;/code&gt;, the order of box shadows for drawing a bulk of the button will be as follows:&lt;/p&gt;

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

button {
    . . .
    box-shadow:
        // drop shadow
        $btnEdge $btnEdge 0.5em $dropShadowColor,
        // top, left, and right edges of hole
        0 (-$btnHoleEdge) 0 $btnHoleEdge $darkEdgeColor,
        // bottom edge of hole
        0 $btnHoleEdge 0 $btnHoleEdge $lightEdgeColor,
        // right edge of button
        (-$btnEdge) 0 $btnEdge $coloredDarkEdgeColor inset,
        // top edge of button
        0 $btnEdge $btnEdge $lightEdgeColor inset,
        // left edge of button
        $btnEdge 0 $btnEdge $lightEdgeColor inset,
        // bottom edge of button
        0 (-$btnEdge) $btnEdge $coloredDarkEdgeColor inset;
    . . .
}


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

&lt;/div&gt;

&lt;p&gt;Where we draw or color the shadows depends on where the direction of light is. In this case, it’ll come from the top left. Therefore, the shadow shall be cast 0.2em to the right and from the top. To explain how everything should be shaded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We use &lt;code&gt;$darkEdgeColor&lt;/code&gt; to add slightly dark transparency to hole edges that should receive hardly any light, which would be the top, left, and right.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$lightEdgeColor&lt;/code&gt; is for adding transparent white to the hole and button edges receiving more light (note: because the drop shadow initially covers it, we’ll see the full effect only when the button is pressed).&lt;/li&gt;
&lt;li&gt;For a little more color on the button edges receiving minimal light, we apply &lt;code&gt;$coloredDarkEdgeColor&lt;/code&gt; rather than &lt;code&gt;$darkEdgeColor&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The texture is kicking in now, but there’s more to go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdflj1utsmlgq6a7dbeia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdflj1utsmlgq6a7dbeia.png" alt="Button now having a drop shadow, blurred lighter blue top and left edges and darker blue right and bottom edges, inside a hole with all dark gray edges except for a light gray bottom edge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s spice it up by adding slight shading from top to bottom as well as a small reflection at the top to the current background.&lt;/p&gt;

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

button {
    . . .
    background:
        // top-to-bottom shading
        linear-gradient(rgba(0,0,0,0),rgba(0,0,0,0.13)),
        // reflection at top
        radial-gradient(90% 7% at 50% 8%,rgba(255,255,255,0.47) 25%,rgba(255,255,255,0) 50%),
        $btnColor;
}


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

&lt;/div&gt;

&lt;p&gt;When you look at an object from a certain angle, sometimes you can barely see a visible transition of shades. Take this picture of a plastic for example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3eykbbx7lzux3yv79mpm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3eykbbx7lzux3yv79mpm.gif" alt="Cursor moving up and down on a red cube to show transition from lighter to dark"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running along the side of it with macOS’s Digital Color Meter (or you can click around a similar image with the eyedropper in your favorite image editing tool), you can see the gradual shift in hex from red to a darker red (roughly #eb0011 to #d5000e). That’s the purpose of the first gradient. Depending on the material, you may see some reflection at top edges, which the second gradient illustrates.&lt;/p&gt;

&lt;p&gt;The last thing to add to the button’s initial state is this text shadow before &lt;code&gt;&amp;amp;, span { }&lt;/code&gt;:&lt;/p&gt;

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

button {
    . . .
    text-shadow: 0 0 $btnEdge fade-out($btnTextColor,0.53);
    . . .
}


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

&lt;/div&gt;

&lt;p&gt;The text won’t look so sharp if we provide a slight blur having the same value as &lt;code&gt;$btnEdge&lt;/code&gt; and the same color but about half the opacity.&lt;/p&gt;

&lt;p&gt;Looking at what we have now, we’re ready to move forward with the button states!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuu5ks4xpg3iwliaxm7xc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuu5ks4xpg3iwliaxm7xc.png" alt="Thin lighter blue radial gradient at top of button, transparent to transparent black linear gradient from top to bottom, slight text shadow added to button text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;:active&lt;/code&gt; State
&lt;/h2&gt;

&lt;p&gt;To begin with our down state, we need an additional variable &lt;code&gt;$coloredDarkerEdgeColor&lt;/code&gt; with a slightly darker blue.&lt;/p&gt;

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

button {
    . . .
    $coloredDarkerEdgeColor: darken($btnColor,20%);
    . . .
}


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

&lt;/div&gt;

&lt;p&gt;The darker blue edges of the button ought to become darker while pressed to show the lack of light between button and hole edges.&lt;/p&gt;

&lt;p&gt;Then we apply the same stack of shadows with some parameter changes for &lt;code&gt;:active&lt;/code&gt; as well as some scaling down for the button text span:&lt;/p&gt;

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

button {
    . . .
    &amp;amp;:active {
        box-shadow:
            // pull shadow inward
            0 0 0 $dropShadowColor,
            // edges of hole stay the same
            0 (-$btnHoleEdge) 0 $btnHoleEdge $darkEdgeColor,
            0 $btnHoleEdge 0 $btnHoleEdge $lightEdgeColor,
            // darker right shadow with a bit of blue to result from button being deep into hole
            (-$btnEdge) 0 $btnEdge $coloredDarkerEdgeColor inset,
            // similar shadow at top and left
            0 $btnEdge $btnEdge $darkEdgeColor inset,
            $btnEdge 0 $btnEdge $darkEdgeColor inset,
            // same as 4th shadow but coming from bottom
            0 (-$btnEdge) $btnEdge $coloredDarkerEdgeColor inset;
        span {
            transform: scale(0.95);
        }
    }
}


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

&lt;/div&gt;

&lt;p&gt;To sum up what happens at this point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We change the x- and y-positions to 0 to pull that drop shadow inward.&lt;/li&gt;
&lt;li&gt;Because nothing should happen to them, we leave the next two box shadows for the edges of the hole alone.&lt;/li&gt;
&lt;li&gt;The fourth and last shadows is where we apply the darker blue using &lt;code&gt;$coloredDarkerEdgeColor&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The lighter shadows before the last shall use the direct opposite color, which would be &lt;code&gt;$darkEdgeColor&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;At the same time, the button text &lt;code&gt;transform&lt;/code&gt; will give a top-down 3D perspective.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we’ve done here in a nutshell is an optical illusion since it’s merely a change of a couple box shadows and scaling of text.&lt;/p&gt;

&lt;p&gt;Now what the button needs is some animation. Let’s add 0.1-second &lt;code&gt;box-shadow&lt;/code&gt; and &lt;code&gt;transform&lt;/code&gt; transitions to the button and span as well as &lt;code&gt;will-change: transform&lt;/code&gt; to the span, which will stop the button from jerking up and down.&lt;/p&gt;

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

button {
    . . .
    transition-property: box-shadow;
    &amp;amp;, span {
        display: block;
        transition: {
            duration: 0.1s;
            timing-function: linear; 
        }
    }
    span {
        transition-property: transform;
        will-change: transform;
    }
    . . .
}


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

&lt;/div&gt;

&lt;p&gt;After all that, we have the effect we’re looking for; however, it looks weird to see that native focus ring encircle the button or the text, whether you tab into it or click it. Tackling that will be the final step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3moojddv8jrk6vycao7u.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3moojddv8jrk6vycao7u.gif" alt="Fully functional button with native focus rings around the button and text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;:focus&lt;/code&gt; State
&lt;/h2&gt;

&lt;p&gt;Since neither the button nor its text should have that native outline for &lt;code&gt;:focus&lt;/code&gt;, let’s take that away with &lt;code&gt;outline: none&lt;/code&gt;.&lt;/p&gt;

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

button {
    . . .
    &amp;amp;, span {
        . . .
        &amp;amp;:focus {
            outline: none;
        }
    }
    . . .
}


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

&lt;/div&gt;

&lt;p&gt;For a new focus style, we must consider what would best fit the button. If the button were a LED, a change of background color would certainly fit perhaps as well as an extra box shadow with the button color. For a plastic button like this one, a change of text color as well as its shadow works best. So that calls for one more variable (&lt;code&gt;$btnTextFocusColor&lt;/code&gt;), and we’ll use a lighter shade of the button color. Right after our &lt;code&gt;:active&lt;/code&gt; selector is where we’ll apply the &lt;code&gt;:focus&lt;/code&gt;.&lt;/p&gt;

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

button {
    . . .
    $btnTextFocusColor: lighten($btnColor,40%);
    . . .
    &amp;amp;:focus {
        color: $btnTextFocusColor;
        text-shadow: 0 0 $btnEdge fade-out($btnTextFocusColor,0.53);
    }
}


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

&lt;/div&gt;

&lt;p&gt;And now we have a complete button! If you click it now, those annoying focus rings won’t be there. Plus, the new focus shouldn’t persist. That’s because the span containing the button text covers it. That way, it’ll look more natural clicking or tapping that button. Therefore, it should be via keyboard only the text changes color just to indicate where the user is tabbing.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/jkantner/embed/vYGzWZv?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;All in all, realistic-looking buttons like these or even other form controls don’t require a complicated HTML structure. Although we didn’t use them here, you can even take advantage of using &lt;code&gt;:before&lt;/code&gt; and &lt;code&gt;:after&lt;/code&gt; if you feel more elements are needed just as I did in &lt;a href="https://codepen.io/jkantner/pen/VwaBomY" rel="noopener noreferrer"&gt;this LED switch&lt;/a&gt;, which were for the rotating part. By learning to effectively stack gradients and box shadows, you can pull off a lot of detail in the fewest DOM elements possible.&lt;/p&gt;

</description>
      <category>css</category>
      <category>sass</category>
      <category>scss</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Fitting Flappy Bird Into a Tweet</title>
      <dc:creator>Jon Kantner</dc:creator>
      <pubDate>Wed, 09 Sep 2020 13:30:16 +0000</pubDate>
      <link>https://dev.to/jonkantner/fitting-flappy-bird-into-a-tweet-484h</link>
      <guid>https://dev.to/jonkantner/fitting-flappy-bird-into-a-tweet-484h</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: I originally published this article on December 21, 2017 on a site I shut down as part of a purge.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5MJr-qNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/fpyjyisxalhy1uq0sf58.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5MJr-qNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/fpyjyisxalhy1uq0sf58.gif" alt="Gameplay of 278-byte Flappy Bird" width="300" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since Twitter recently &lt;a href="https://twitter.com/Twitter/status/928004549478047744"&gt;extended the character limit&lt;/a&gt; to 280, I’ve challenged myself to write programs or patterns within 280 bytes such as a tweet-sized Flappy Bird (game by dotGEARS about flying a bird through pipes without touching them) I’ll share in this post. I once thought about writing functional apps under 140, but there was just too little room to do anything significant.&lt;/p&gt;

&lt;p&gt;The inspiration came from studying posts on a Twitter-like site called &lt;a href="https://www.dwitter.net/"&gt;Dwitter&lt;/a&gt; where you share 140-byte snippets of functions for canvas animations. I also studied some &lt;a href="https://www.quaxio.com/tron/"&gt;2012 challenge&lt;/a&gt; to write a Tron in the fewest bytes possible.&lt;/p&gt;

&lt;p&gt;This practice of writing minimal code is known as “code golfing“ because using the least bytes to write a functional program is like using the least strokes to complete a hole in regular golf.&lt;/p&gt;

&lt;p&gt;I’ll walk through how I made a 278-byte, black-and-white version of the once viral Flappy Bird using HTML and JavaScript. Due to the amount of minimum logic needed for the number of game mechanics (e.g. flapping, collision with pipes), there wasn’t enough room to make everything 100% accurate with the current JavaScript features available. The goal was rather to fit as many of those mechanics 280 characters could hold.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;Here’s the entire source code, and I added some line breaks and tabs so that you can easily see its parts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body id=B onload="
    c=C.getContext('2d');
    o=[90,-92,98];
    y=0;
    x=225;
    s=0;
    setInterval('
        c.fillRect(0,0,W=150,W);
        for(i in o)
            c.clearRect(+i?x:37,o[i],+i?14:9,+i?W:9);
        b=o[0];
        b&amp;lt;W-9&amp;amp;&amp;amp;(x&amp;lt;23||x&amp;gt;46||58&amp;lt;b&amp;amp;&amp;amp;b&amp;lt;89)?
            (y+=.04,x&amp;lt;-13?(x=W,++s):--x,o[0]+=y):B.innerHTML=s
    ',9)
"&amp;gt;
&amp;lt;canvas id=C onclick=y=-1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I kept all variable names and IDs at a single-letter because it’s a great strategy for writing minimal code. Pretty small and weird, isn’t it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Tags and Attributes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body id=B onload=""&amp;gt;
&amp;lt;canvas id=C onclick=y=-1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The skeleton of the game consists of only opening &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; tags. It may normally be a good habit to close these, but it doesn’t really matter here because there are no other elements coming after the canvas. Therefore, we can save 16 bytes by not including &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;/canvas&amp;gt;&lt;/code&gt; (7 + 9)!&lt;/p&gt;

&lt;p&gt;Then we have IDs &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt;. Luckily, JavaScript allows us to use IDs assigned to elements as variable names. In that case, we can use &lt;code&gt;B&lt;/code&gt; for displaying the score on game over and &lt;code&gt;C&lt;/code&gt; for accessing the canvas.&lt;/p&gt;

&lt;p&gt;The main game code goes in the &lt;code&gt;onload&lt;/code&gt; event listening attribute and then an onclick with a variable change to explain later.&lt;/p&gt;

&lt;p&gt;All of these attributes except &lt;code&gt;onload&lt;/code&gt; don’t have quotes. Since three need only one value, we save 6 bytes by not including the quotes. The case for &lt;code&gt;onload&lt;/code&gt; is different because it’ll contain a &lt;code&gt;for...in&lt;/code&gt; loop with two spaces, and the browser will mistake &lt;code&gt;for(i&lt;/code&gt; plus code before it, &lt;code&gt;in&lt;/code&gt;, and &lt;code&gt;o)&lt;/code&gt; plus code after it as attributes if quotes aren’t surrounding them. Furthermore, the browser will treat &amp;gt; before the 46 as the end of the opening &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag and then think everything after 58 is an another opening tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oC1LwpSh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/tzb6wkw34drule9xwi5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oC1LwpSh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/tzb6wkw34drule9xwi5e.png" alt="onload without quotes" width="550" height="165"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;What the browser will see if &lt;code&gt;onload&lt;/code&gt; is unquoted&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Context and Main Variables
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c=C.getContext('2d');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For the canvas context, I simply used the canvas ID like a variable instead of using &lt;code&gt;document.getElementById("C")&lt;/code&gt; or &lt;code&gt;document.querySelector("#C")&lt;/code&gt;. Either way it saves 27 bytes (28 – 1 for &lt;code&gt;C&lt;/code&gt;)!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;o=[90,-92,98];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;o&lt;/code&gt; holds the Y positions of the bird (90) and pipes (-92 and 98).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;y=0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;y&lt;/code&gt; is the additional Y distance added to the bird, and this is constantly increased later in the code. When the player clicks the canvas, this value goes back to -1, and that is what you see in the element’s &lt;code&gt;onclick&lt;/code&gt;. This helps the bird flap because &lt;code&gt;y&lt;/code&gt; being negative moves it upward. When &lt;code&gt;y&lt;/code&gt; is over zero, then the bird starts falling again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x=225;
s=0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;x&lt;/code&gt; is the X position of the pipes, which starts offscreen at 225 pixels, and s is the score.&lt;/p&gt;

&lt;p&gt;By the way, you may have noticed that I used neither &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;, nor &lt;code&gt;const&lt;/code&gt; to declare these variables. Without those keywords, variables are treated as &lt;code&gt;var&lt;/code&gt; by default as long as strict mode (&lt;code&gt;"use strict"&lt;/code&gt;) isn’t enabled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Game Functionality
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setInterval('
    c.fillRect(0,0,W=150,W);
    for(i in o)
        c.clearRect(+i?x:37,o[i],+i?14:9,+i?W:9);
    b=o[0];
    b&amp;lt;W-9&amp;amp;&amp;amp;(x&amp;lt;23||x&amp;gt;46||58&amp;lt;b&amp;amp;&amp;amp;b&amp;lt;89)?
        (y+=.04,x&amp;lt;-13?(x=W,++s):--x,o[0]+=y):B.innerHTML=s
',9)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;setInterval()&lt;/code&gt; contains the core of the game logic. Since this function can accept code in a string as the first argument, we can save bytes using &lt;code&gt;' '&lt;/code&gt; instead of &lt;code&gt;function(){}&lt;/code&gt; or &lt;code&gt;()=&amp;gt;{}&lt;/code&gt;. Be advised, however, that the syntax is a security hole according to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval#Parameters"&gt;Mozilla&lt;/a&gt;. It may not matter for little games like what I’m explaining here, but please don’t consider the syntax for reducing code in production!&lt;/p&gt;

&lt;h3&gt;
  
  
  Drawing the Screen
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c.fillRect(0,0,W=150,W);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;fillRect()&lt;/code&gt; is for the background, and you can immediately throw in a new variable &lt;code&gt;W&lt;/code&gt; as the width and height parameters. This is valid as long as you’ve defined it in the first place, and it even becomes available within the scope of &lt;code&gt;setInterval()&lt;/code&gt;. Occupying the whole default canvas height at 150×150 is fine; the screen is easiest to see, and it’s closest to being portrait like the original Flappy Bird.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for(i in o)
    c.clearRect(+i?x:37,o[i],+i?14:9,+i?W:9);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;for...in&lt;/code&gt; loop that follows draws the bird and pipes. Using &lt;code&gt;for...in&lt;/code&gt; to loop through an array is a lot simpler than the classic &lt;code&gt;for(i = 0; i &amp;lt; n; ++i)&lt;/code&gt; boilerplate.&lt;/p&gt;

&lt;p&gt;To use only one &lt;code&gt;clearRect()&lt;/code&gt; and the smallest arguments to draw the bird or pipes, I took advantage of the way JavaScript handles single-variable expressions. If a variable equals 0 and you check if it’s &lt;code&gt;true&lt;/code&gt;, it returns &lt;code&gt;false&lt;/code&gt;. That’s because JavaScript first thinks 0 is a boolean. Since the counter in a &lt;code&gt;for...in&lt;/code&gt; loop is initially a string though, you must convert it to a number by placing a + before it in order to get the desired result. Then for &lt;code&gt;clearRect()&lt;/code&gt; to draw the bird when &lt;code&gt;i&lt;/code&gt; is 0, &lt;code&gt;i&lt;/code&gt; must return &lt;code&gt;false&lt;/code&gt;, or else &lt;code&gt;clearRect()&lt;/code&gt; draws a pipe.&lt;/p&gt;

&lt;p&gt;If you’re wondering why &lt;code&gt;fillRect()&lt;/code&gt; and &lt;code&gt;clearRect()&lt;/code&gt; are where I used them, it’s because if I swapped their roles, &lt;code&gt;clearRect()&lt;/code&gt; wouldn’t be able to erase the pipes when offscreen. For instance:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uYeAS7bN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/idsmyzwrngn4vgssgeke.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uYeAS7bN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/idsmyzwrngn4vgssgeke.gif" alt="Playing game with fillRect() and clearRect() swapped" width="240" height="150"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Note: Slightly cropped to focus on pipe “trail”&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Collision Detection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;b=o[0];
b&amp;lt;W-9&amp;amp;&amp;amp;(x&amp;lt;23||x&amp;gt;46||58&amp;lt;b&amp;amp;&amp;amp;b&amp;lt;89)?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I set the conditions for avoiding the pipes and ground, but first I used b for a copy of the bird’s Y position. Normally I’d use &lt;code&gt;o[0]&lt;/code&gt;, but it saves a few bytes to use a shorter reference to an array item. Then here are the conditions broken down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;b&amp;lt;W-9&lt;/code&gt;: The top of the bird must not be 9 less the canvas height, which is touching the ground.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;x&amp;lt;23&lt;/code&gt;: The left side of pipes must be more than their diameter (14) behind the X position of the bird (37). To keep this short, I wrote the result of 23.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;x&amp;gt;46&lt;/code&gt;: If the previous condition is &lt;code&gt;false&lt;/code&gt;, then check if the pipes are ahead of the bird plus its width (37 + 9 = 46).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;58&amp;lt;b&amp;amp;&amp;amp;b&amp;lt;89&lt;/code&gt;: Then if &lt;code&gt;false&lt;/code&gt; again, compare the top of the bird to the visible horizontal sides both pipes. Because the top of the first pipe is offscreen at -92, add the pipe height, which is the same value as the screen width &lt;code&gt;W&lt;/code&gt; (-92 + 150 = 58). That’s the first value in this condition for the bird to avoid game over. The other value 89 is the top of the second pipe minus the bird height (98 – 9 = 89).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My original plan for the last comparison was to use &lt;code&gt;o[1]+W&amp;lt;b&amp;amp;&amp;amp;b&amp;lt;o[2]&lt;/code&gt;. That way, I could use &lt;code&gt;Math.random()&lt;/code&gt; somewhere to generate different pipe positions and not use magic numbers for the same ones, yet it requires me to sacrifice scoring or collision detection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Object Movement
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(y+=.04,x&amp;lt;-13?(x=W,++s):--x,o[0]+=y):B.innerHTML=s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As long as the bird is in play, every variable adjustment in this part of the ternary operation influences the bird and pipes. Using commas, you can put multiple statements in one expression as long as that expression is enclosed by &lt;code&gt;( )&lt;/code&gt;. An error will occur, however, if you slip in semicolons or keywords like &lt;code&gt;if&lt;/code&gt; or &lt;code&gt;else&lt;/code&gt;. For example, the console will complain about an unexpected token for &lt;code&gt;y+=.04,if(x&amp;lt;-13)x=W,++s;else--x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the first expression, the extra distance y is increased slightly by .04 and then compounded on the bird as shown by &lt;code&gt;o[0]+=y&lt;/code&gt;. As I noted before, this is part of the flapping and at the same time simulates gravity. If I were to decrease this increment, the bird would fall more slowly as if on the moon. If greater, it would fall faster thus making it harder to keep midair.&lt;/p&gt;

&lt;p&gt;Then an inner ternary operation &lt;code&gt;x&amp;lt;-13?(x=W,++s):--x&lt;/code&gt; controls the pipes. When the &lt;code&gt;x&lt;/code&gt; position of the pipes is less than the pipe diameter negated plus one (-14 + 1 = -13), then they are moved back to the right edge of the screen at W, the screen width. At the same time, the player scores a point (as &lt;code&gt;++s&lt;/code&gt; shows). In the original game though you score points for just passing a set of pipes. To make it look that way in this version, I set the &lt;code&gt;y&lt;/code&gt; increment so that the bird shouldn’t be able to hit the ground before the pipe exits. If these changes aren’t to happen yet otherwise, the pipes should keep moving left.&lt;/p&gt;

&lt;p&gt;Finally in the second expression for &lt;code&gt;b&amp;lt;W-9...&lt;/code&gt;, the entire canvas is replaced with the player’s score on game over.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interval
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setInterval('
    . . .
',9)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last part to cover is the interval. To run animations very smoothly at least 60 fps, &lt;code&gt;1000/60&lt;/code&gt; is typically the value to use. We could simplify it to 16.6667 then round to 17, but the bird and pipes would move too slowly. To fix that, we could change y from .04 to a higher value and &lt;code&gt;--x&lt;/code&gt; to maybe &lt;code&gt;x-=2&lt;/code&gt;, but that would cost some extra bytes. Because I wanted to reduce bytes wherever I could, I used a single digit value of 9, which would still set a comfortable game speed.&lt;/p&gt;

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

&lt;p&gt;Writing such a tiny program has taught me to find ways to write less code. All in all, these sort of programs are created for fun and in code golfing competitions. Plus, you can learn from golfing how to better minify or compress your code for reduced load time! Just be mindful of what might lead to bugs or errors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/jkantner/pen/zPewbZ"&gt;Play the 278-byte Flappy Bird on CodePen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to play&lt;/strong&gt;: Click the canvas to flap. Avoid the pipes. Click Run to replay.&lt;/p&gt;

</description>
      <category>html</category>
      <category>javascript</category>
      <category>codegolf</category>
      <category>twitter</category>
    </item>
    <item>
      <title>Trick for Resizable and Responsive CSS Images</title>
      <dc:creator>Jon Kantner</dc:creator>
      <pubDate>Wed, 09 Sep 2020 13:21:07 +0000</pubDate>
      <link>https://dev.to/jonkantner/trick-for-resizable-and-responsive-css-images-35bf</link>
      <guid>https://dev.to/jonkantner/trick-for-resizable-and-responsive-css-images-35bf</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: I originally published this article on May 28, 2017 on a site I shut down as part of a purge.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every once in a while in CodePen’s Popular or Picked section, you’ll come across a Pen name containing #dailycssimages. These Pens are vector images created using only HTML elements and CSS. These images usually consist of absolutely positioned elements formed using a variety of properties including &lt;code&gt;border-radius&lt;/code&gt;, &lt;code&gt;box-shadow&lt;/code&gt;, and sometimes &lt;code&gt;clip-path&lt;/code&gt;. For plenty of examples, just do a &lt;a href="https://codepen.io/search/pens/?depth=everything&amp;amp;limit=all&amp;amp;order=popularity&amp;amp;page=1&amp;amp;q=daily+css+images&amp;amp;show_forks=false"&gt;search&lt;/a&gt; for the hashtag. I have been drawing some myself including this &lt;a href="https://codepen.io/jkantner/pen/QdJMmr"&gt;Longcat&lt;/a&gt; and &lt;a href="https://codepen.io/jkantner/pen/eZPooe"&gt;radar animation&lt;/a&gt;. Yet, I’ve always wondered if there was a way to make them resizable or responsive.&lt;/p&gt;

&lt;p&gt;I haven’t found too many examples of responsive CSS images in the wild. If responsive somewhat, you’ll find at least a few media queries in the code to define smaller or larger sizes. Just like responsive &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; elements, CSS images made responsive should gradually and proportionally increase or decrease in size if you resize the browser window. Moreover, it would save so much time if we could resize them manually like choosing a new width or height value for a certain &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element (in CSS that is) and using auto for the other dimension. We may have &lt;code&gt;scale()&lt;/code&gt; of the &lt;code&gt;transform&lt;/code&gt; property, but the space the image occupies won’t be adjusted along with the image if used.&lt;/p&gt;

&lt;p&gt;After endless tinkering, I finally found a way that seemed to be less complicated than I thought. I would like to share it with you, but please be advised, however, that it’s &lt;strong&gt;experimental&lt;/strong&gt; only. There are few browser-related situations where it malfunctions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create or Find any Image
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fA8O_M7r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/4opot3u99c3duulenac3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fA8O_M7r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/4opot3u99c3duulenac3.png" alt="CSS teddy bear" width="260" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first step is to draw everything like usual or grab an existing image. For this demo, we’ll use the teddy bear I drew above. Here’s its HTML and CSS:&lt;/p&gt;

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

&lt;p&gt;Before we start pulling off the trick, verify that the parent container has a defined width and height. They must use an absolute unit (px, pt, pc, in, cm, or mm) in order to maintain a constant side-to-side ratio. Any selectors of child elements using absolute units must use the same type as that of the parent. In this case, &lt;code&gt;.teddy&lt;/code&gt; is our parent container at 260px × 330px, and we have left the %s under &lt;code&gt;.right-ear,..., .foot&lt;/code&gt; and &lt;code&gt;.foot&lt;/code&gt; alone since they weren’t absolute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying the Trick
&lt;/h2&gt;

&lt;p&gt;Once we’re satisfied with the code, let’s add a font size to the container using a &lt;code&gt;calc()&lt;/code&gt; expression. It shall divide a new width or height of the image by the original one. Just don’t add the unit to the original one because the divisor in &lt;code&gt;calc()&lt;/code&gt; division must be a number. For our example we’ll choose a new width of 50vmin (for responsiveness) and divide it by the original width 260 (px dropped).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.teddy {
    font-size: calc(50vmin / 260);
    . . .
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could also use an expression that adds or subtracts different units as well like (300px + 5vw) as long as we keep everything before the slash and 260 in parentheses. %s used here though applies to font size only and yields different results in every browser.&lt;/p&gt;

&lt;p&gt;After setting the font size, we replace every absolute unit out side of the &lt;code&gt;calc()&lt;/code&gt; with em (you can speed up this process using your text editor’s Find and Replace tool). In this example we used px and replaced each px with em.&lt;/p&gt;

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

&lt;p&gt;Finally, resize the window to see how the image increases or decreases in size proportionally!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--njOnyXs9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/p059a2h2g9q9nga2kc2r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--njOnyXs9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/p059a2h2g9q9nga2kc2r.gif" alt="CSS teddy bear made responsive" width="600" height="450"&gt;&lt;/a&gt;&lt;br&gt;
(&lt;a href="https://codepen.io/jkantner/pen/dWLeQZ"&gt;Demo&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;If you got something awfully strange, refactor your code so that every element is inside one main container element with an absolute width and height. Ensure that you used a single type of absolute unit, too. If you feel you did everything correctly and the image still appears larger than it should, I’ll discuss why that happens in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;Whether this successfully worked or not, there are still two caveats to be aware of:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Minimum Font Size Setting
&lt;/h3&gt;

&lt;p&gt;If your image ended up being unusually large, here’s why: the browser has a setting for minimum font size, and it will force the result of the &lt;code&gt;calc()&lt;/code&gt; we used to that font size if under. For instance, if the resulting font size is 2px and the minimum is 6px, then it remains at 6px. This will make every em 6px each thus causing the image to be ridiculously large. I discovered this by accident when for no reason I played with Chrome’s font settings. Since the default minimum font size is 1px and we did not touch that setting for this demo, we could use super small font size for resizing a CSS image in the way desired.&lt;/p&gt;

&lt;p&gt;Additionally, according to some &lt;a href="http://www.fyianlai.com/2012/01/google-chrome-minimum-font-size-issue/"&gt;post&lt;/a&gt; about minimum font size in Chrome by Ian Lai, we would have been able to fix the minimum font size issue in every browser using the &lt;code&gt;text-size-adjust&lt;/code&gt; property. Unfortunately, desktop browser support has been dropped a few years a ago (possibly due to accessibility issues).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;calc()&lt;/code&gt; with Viewport Units in Safari
&lt;/h3&gt;

&lt;p&gt;The other caveat is that if you provide a new length using vw, vh, vmin, or vmax, Safari will only calculate it on load and not on window resize. This happens to be a bug with using viewport units in &lt;code&gt;calc()&lt;/code&gt; for font size, and there currently aren’t any workarounds I know of.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The magic behind this is all in the font size and em. Since 1em is equal to the font size of the current element, font size will redefine what one unit of the image would be if we switched the units for everything else from that unit to em. If the font size were 10px for instance, every pixel of the image will be 10 times larger. Then, an image originally 50px wide would become 500px.&lt;/p&gt;

&lt;p&gt;To show how we can choose a new width or height and get what we want though, we use &lt;code&gt;calc(new_length / original_length)&lt;/code&gt; (remember, drop the unit for the original length!). Plus, it really doesn’t matter which absolute unit we choose to work with as long as we’re being consistent.&lt;/p&gt;

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

&lt;p&gt;In a nutshell, we can enable CSS images to be proportionally resizable and responsive by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using &lt;code&gt;calc(new_length / original_length)&lt;/code&gt; for the parent container’s font size&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swapping every absolute unit outside the &lt;code&gt;calc()&lt;/code&gt; with em&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Although there’s still some experimenting to do for improving the safety of use in production, this has been a huge step towards making pure CSS images as flexible as &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; elements and SVGs. This approach for responsive CSS images is the best I’ve found so far, and I hope you’ll enjoy trying it out!&lt;/p&gt;

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