<?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: Adrian Bece</title>
    <description>The latest articles on DEV Community by Adrian Bece (@adrianbdesigns).</description>
    <link>https://dev.to/adrianbdesigns</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%2F91468%2Fcdda7312-9dc4-4b73-98ed-fb0c3d55a624.jpg</url>
      <title>DEV Community: Adrian Bece</title>
      <link>https://dev.to/adrianbdesigns</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adrianbdesigns"/>
    <language>en</language>
    <item>
      <title>clay.css - micro CSS util for creating claymorphic UI</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 10 Jan 2022 10:55:33 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/claycss-micro-css-util-for-creating-claymorphic-ui-cmc</link>
      <guid>https://dev.to/adrianbdesigns/claycss-micro-css-util-for-creating-claymorphic-ui-cmc</guid>
      <description>&lt;h1&gt;
  
  
  clay.css
&lt;/h1&gt;

&lt;p&gt;Extensible and configurable micro CSS util class and SASS mixin for adding claymorphism styles to your components.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/codeAdrian/clay.css" rel="noopener noreferrer"&gt;repository&lt;/a&gt; and the &lt;a href="https://codeadrian.github.io/clay.css/" rel="noopener noreferrer"&gt;demo page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FcodeAdrian%2Fclay.css%2Fgh-pages%2Fassets%2Fsocial.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FcodeAdrian%2Fclay.css%2Fgh-pages%2Fassets%2Fsocial.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About
&lt;/h2&gt;

&lt;p&gt;Claymorphism is a fresh new concept. The name was coined by &lt;a href="https://hype4.academy/articles/design/claymorphism-in-user-interfaces" rel="noopener noreferrer"&gt;Michał Malewicz&lt;/a&gt; and the designers are excited to explore the possibilities of this approach to UI design.&lt;/p&gt;

&lt;p&gt;It features inflated fluffy 3D elements which look charming and introduce a much more vibrant look compared to the usual flat designs.&lt;/p&gt;

&lt;p&gt;What sets claymorphism apart from neumorphism is that it floats above the background instead of being connected to it, eliminating accessibility issues and design restrictions of the latter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CDN
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link
  rel="stylesheet"
  href="https://unpkg.com/claymorphism-css/dist/clay.css"
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NPM
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i claymorphism-css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add claymorphism-css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manual
&lt;/h3&gt;

&lt;p&gt;Download and add the &lt;code&gt;dist/clay.css&lt;/code&gt; or &lt;code&gt;dist/clay.scss&lt;/code&gt; manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;This is a minimal, single class CSS util that applies only basic claymorphism styles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Background&lt;/li&gt;
&lt;li&gt;Border radius&lt;/li&gt;
&lt;li&gt;One outset shadow&lt;/li&gt;
&lt;li&gt;Two inset shadows
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"clay"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Fluffy ipsum dolor sit amet consectetur...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FcodeAdrian%2Fclay.css%2Fmaster%2Fdocs%2Fexample1.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%2Fraw.githubusercontent.com%2FcodeAdrian%2Fclay.css%2Fmaster%2Fdocs%2Fexample1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This CSS class allows you to easily change the claymorphic styles via CSS properies. These changes and additional styles should be applied with the extending class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"clay card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Fluffy ipsum dolor sit amet consectetur...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* Modify clay.css properties */&lt;/span&gt;
  &lt;span class="py"&gt;--clay-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f76d6d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--clay-border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;48px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;/* Extended styles */&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;#f1f1f1&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;48px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FcodeAdrian%2Fclay.css%2Fmaster%2Fdocs%2Fexample2.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%2Fraw.githubusercontent.com%2FcodeAdrian%2Fclay.css%2Fmaster%2Fdocs%2Fexample2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Options (CSS Variables)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--clay-background
--clay-border-radius
--clay-shadow-outset
--clay-shadow-inset-primary
--clay-shadow-inset-secondary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodeadrian.github.io%2Fclay.css%2Fassets%2Fdiagram-min.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%2Fcodeadrian.github.io%2Fclay.css%2Fassets%2Fdiagram-min.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SASS Mixin
&lt;/h2&gt;

&lt;p&gt;SASS mixin allows you more flexibility in applying claymorphism styles to your components. For example, this way you can easily add styles to pseudo-elements or pseudo-selectors or use the mixin in other SASS mixins or functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import "claymorphism-css/dist/clay.scss";

@import @include clay(
  $background: [value],
  $border-radius: [value],
  $shadow-outset: [value],
  $shadow-inset-primary: [value],
  $shadow-inset-secondary: [value]
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Demo page
&lt;/h2&gt;

&lt;p&gt;Check out the &lt;a href="https://codeadrian.github.io/clay.css/" rel="noopener noreferrer"&gt;demo page&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>html</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Create animated navigation indicator with HTML, CSS and JS</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 11 Jan 2021 07:03:13 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/create-animated-navigation-indicator-with-html-css-and-js-300b</link>
      <guid>https://dev.to/adrianbdesigns/create-animated-navigation-indicator-with-html-css-and-js-300b</guid>
      <description>&lt;p&gt;I've never had the chance to use this kind of menu on my regular projects, so I decided to make one, just for fun. I was really happy with the final result, so I decided to share it with the community. Even though I created this one using React, I wanted to make one with vanilla JavaScript so you can use it on any project.&lt;/p&gt;

&lt;h1&gt;
  
  
  HTML setup
&lt;/h1&gt;

&lt;p&gt;Let's start off by creating a simple navigation markup with a simple list with a few links. We'll add &lt;code&gt;id&lt;/code&gt; attributes to the root &lt;code&gt;nav&lt;/code&gt; element and a &lt;code&gt;div&lt;/code&gt; element that we'll use as a pointer. We'll need a few classes for the nav, list, and pointer elements so we can style them.&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;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"js-nav"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"js-pointer"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav__pointer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav__list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Overview&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Goals&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Inspiration&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Profile&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;
&lt;h1&gt;
  
  
  CSS markup
&lt;/h1&gt;

&lt;p&gt;Let's add some styles. The following code snippet shows only required styles.&lt;/p&gt;

&lt;p&gt;We need to position &lt;code&gt;nav&lt;/code&gt; element relatively and add some padding. We'll need that value for JavaScript. We'll position &lt;code&gt;nav__pointer&lt;/code&gt; absolutely with a &lt;code&gt;z-index&lt;/code&gt; value that is lower than &lt;code&gt;nav__list&lt;/code&gt; so the indicator is positioned under the links.&lt;/p&gt;

&lt;p&gt;We need to position the links in a &lt;code&gt;4 * 1fr&lt;/code&gt; column grid so all link containers are equal width.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.nav&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.nav__pointer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.6em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&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;#bada55&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.8em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;0.25s&lt;/span&gt; &lt;span class="n"&gt;ease-in-out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.3em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;will-change&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;backface-visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.nav__list&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;z-index&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;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&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="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&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;h2&gt;
  
  
  JavaScript
&lt;/h2&gt;

&lt;p&gt;We need to select our navigation, indicator, and link elements with JavaScript. Remember that &lt;code&gt;1em&lt;/code&gt; value padding from CSS? We'll use half of that value so we can position the pointer appropriately.&lt;/p&gt;

&lt;p&gt;To avoid using magic numbers, we'll dynamically calculate the indicator's width depending on the number of columns in the grid (how many links there are).&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;CONTAINER_PADDING_HALF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.5em&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;calc(100% /&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&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="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;CONTAINER_PADDING_HALF&lt;/span&gt;&lt;span class="o"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For each selected link within the &lt;code&gt;nav&lt;/code&gt; element, we'll add a &lt;code&gt;data&lt;/code&gt; attribute that stores a percentage value based on the order. If the link is first in the list, it will have a &lt;code&gt;0%&lt;/code&gt; value, if it's a second, it will have a &lt;code&gt;100%&lt;/code&gt; value, etc. We'll use those values for transforms.&lt;/p&gt;

&lt;p&gt;We're also attaching a click event listener for each link.&lt;/p&gt;

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

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&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;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;movePointer&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 link click event handler is very simple - it only applies a CSS transform attribute to the navigation indicator. The value that is being applied depends on &lt;code&gt;data-order&lt;/code&gt; attribute that we've set. &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="nf"&gt;movePointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;translate3d(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,0,0)&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;Since the width of the indicator matches the width of the each navigation link in the grid, and we've positioned the indicator absolutely and to the start of the first link, we only have to apply transforms in &lt;code&gt;100%&lt;/code&gt; increments. First link will have the &lt;code&gt;0%&lt;/code&gt; value, second link will have the &lt;code&gt;100%&lt;/code&gt; value, third link will have the &lt;code&gt;200%&lt;/code&gt; value, etc.&lt;/p&gt;

&lt;p&gt;By using 3D CSS transforms, this animation will be GPU-powered and it will be smooth and performant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Result
&lt;/h2&gt;

&lt;p&gt;Here is the CodePen link to the final result.&lt;/p&gt;

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




&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-red.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>html</category>
      <category>css</category>
    </item>
    <item>
      <title>I've created an awesome painting app using React and Canvas API</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 28 Dec 2020 13:53:50 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/i-ve-created-an-awesome-painting-app-using-react-and-canvas-api-47o9</link>
      <guid>https://dev.to/adrianbdesigns/i-ve-created-an-awesome-painting-app-using-react-and-canvas-api-47o9</guid>
      <description>&lt;p&gt;I've just submitted this app for &lt;a href="https://codeadrian.hashnode.dev/magic-painter-christmas-hackathon-project" rel="noopener noreferrer"&gt;Hashnode Christmas hackathon&lt;/a&gt; so I wanted to talk about it here in more detail.&lt;/p&gt;

&lt;p&gt;I didn't have a chance to work with HTML canvas and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" rel="noopener noreferrer"&gt;Canvas API&lt;/a&gt;, so this hackathon gave me a nice reason to dive right into it.&lt;/p&gt;

&lt;p&gt;I also wanted to add something unique to make the result more &lt;strong&gt;magic&lt;/strong&gt;, so I added a dynamic color brush and dynamic width brush. Turns out that this effect indeed looks more magic and dream-like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;React (with custom React hooks)&lt;/li&gt;
&lt;li&gt;Canvas API&lt;/li&gt;
&lt;li&gt;Native color picker and range inputs&lt;/li&gt;
&lt;li&gt;Font awesome icons&lt;/li&gt;
&lt;li&gt;Netlify hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Intro screen
&lt;/h2&gt;

&lt;p&gt;Since I'm primarily a frontend developer and I want to pay special attention to design and details, I've wanted to create a nice splash screen for the app. I was inspired by the watercolor and paint set box designs.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1608976811117%2FCL16Du-xz.jpeg%3Fauto%3Dcompress" 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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1608976811117%2FCL16Du-xz.jpeg%3Fauto%3Dcompress"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I remember when I was buying paint sets for school, I was impressed by the images on the boxes. They showed a beautiful painting and were basically communicating "You can paint this beautiful image with this set". So I wanted to mimic that feeling with the splash screen.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1609005716018%2F8JIbmAfvi.png%3Fauto%3Dcompress" 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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1609005716018%2F8JIbmAfvi.png%3Fauto%3Dcompress"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you wonder how I managed to overlay a gradient on the heading text, here is a code snippet.&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;background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;linear-gradient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="err"&gt;90&lt;/span&gt;&lt;span class="nt"&gt;deg&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;hsl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt; &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%),&lt;/span&gt;
    &lt;span class="nt"&gt;hsl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;211&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt; &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%)&lt;/span&gt; &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt;
    &lt;span class="nt"&gt;hsl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;108&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt; &lt;span class="err"&gt;40&lt;/span&gt;&lt;span class="o"&gt;%)&lt;/span&gt;
  &lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="nt"&gt;-webkit-background-clip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nt"&gt;-webkit-text-fill-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;transparent&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Custom hook
&lt;/h2&gt;

&lt;p&gt;I've added the painting functionality with event listeners and Canvas API using a &lt;a href="https://github.com/codeAdrian/react-magic-painter/blob/main/src/hooks/usePainter.ts" rel="noopener noreferrer"&gt;custom hook&lt;/a&gt; that returns a bunch of states and functions that are required for switching brushes, setting up a Canvas ref, and keeping track of active states.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dynamic color and brush width
&lt;/h2&gt;

&lt;p&gt;This is where the magic happens. In the &lt;strong&gt;magic brush mode&lt;/strong&gt;, I'm shifting the Hue value of HSL color for each paint event. The resulting effect is a wonderful color gradient. I've also added controls to change the color gradient saturation and lightness for more options and moods.&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;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strokeStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`hsl(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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="nx"&gt;selectedSaturation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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="nx"&gt;selectedLightness&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;globalCompositeOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source-over&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;hue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&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;hue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;hue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1609006214515%2FiwOXw5iTu.gif%3Fauto%3Dformat%2Ccompress%26gif-q%3D60" 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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1609006214515%2FiwOXw5iTu.gif%3Fauto%3Dformat%2Ccompress%26gif-q%3D60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similar to the magic brush mode, I've also added a &lt;strong&gt;dynamic width&lt;/strong&gt; mode that changes brush size value up and down between the minimum and maximum value. When combined with the &lt;strong&gt;magic brush mode&lt;/strong&gt;, you can create some awesome art and effects.&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;dynamicLineWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&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;current&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="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="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;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt; &lt;span class="o"&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;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineWidth&lt;/span&gt;&lt;span class="o"&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;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineWidth&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1609006495646%2FQAxIniJc2.gif%3Fauto%3Dformat%2Ccompress%26gif-q%3D60" 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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1609006495646%2FQAxIniJc2.gif%3Fauto%3Dformat%2Ccompress%26gif-q%3D60"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  App demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://magic-painter.netlify.app/" rel="noopener noreferrer"&gt;https://magic-painter.netlify.app/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/codeAdrian" rel="noopener noreferrer"&gt;
        codeAdrian
      &lt;/a&gt; / &lt;a href="https://github.com/codeAdrian/react-magic-painter" rel="noopener noreferrer"&gt;
        react-magic-painter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Post the art you create with the app in the comments! :)
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this post on my hackathon project for Hashnode, check out my hackathon project for DEV x DigitalOcean&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adrianbdesigns" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F91468%2Fcdda7312-9dc4-4b73-98ed-fb0c3d55a624.jpg" alt="adrianbdesigns"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/adrianbdesigns/my-resolve-2021-do-hackathon-submission-91f" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;My Resolve 2021 - DO Hackathon submission&lt;/h2&gt;
      &lt;h3&gt;Adrian Bece ・ Jan 4 '21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#dohackathon&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#showdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;





&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-red.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Published my first NPM package - here's what I learned</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 16 Nov 2020 06:47:34 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/published-my-first-npm-package-here-s-what-i-learned-49j6</link>
      <guid>https://dev.to/adrianbdesigns/published-my-first-npm-package-here-s-what-i-learned-49j6</guid>
      <description>&lt;p&gt;Two weeks ago I've published my &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-omni-font-loader/" rel="noopener noreferrer"&gt;Gatsby plugin as an NPM package&lt;/a&gt;. In short, I've noticed that Gatsby's font loading plugins were deprecated, outdated, and lacking some features, so I've developed a plugin that I wanted to actively maintain if it gains traction. You can read more about that story in my previous post.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/prototyp" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1014%2F22219225-134b-498e-a18b-42f9ae9cd91d.jpg" alt="PROTOTYP"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F91468%2Fcdda7312-9dc4-4b73-98ed-fb0c3d55a624.jpg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/prototyp/load-fonts-asynchronously-handle-fout-with-my-gatsby-plugin-19e" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Load fonts asynchronously &amp;amp; handle FOUT with my Gatsby plugin&lt;/h2&gt;
      &lt;h3&gt;Adrian Bece for PROTOTYP ・ Nov 3 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#gatsby&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In those two weeks, my package received &lt;strong&gt;almost 800 downloads&lt;/strong&gt;. I've learned some lessons about publishing your own NPM packages and maintaining open source projects that I would like to share with you all in this post.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/codeAdrian" rel="noopener noreferrer"&gt;
        codeAdrian
      &lt;/a&gt; / &lt;a href="https://github.com/codeAdrian/gatsby-omni-font-loader" rel="noopener noreferrer"&gt;
        gatsby-omni-font-loader
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Font loader optimized for maximum performance. Removes render-blocking font resources and loads them asynchronusly. Handle FOUT &amp;amp; FOUC with font loading status watcher. Supports both local-hosted fonts and web fonts.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/8dae8f5aac69fb677a40f5f4155d18e4d1ae68f3029f1bcc1def230efa2fe0d8/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f64617a6474393764332f696d6167652f75706c6f61642f635f7363616c652c715f6175746f3a626573742c775f3230302f76313630363535383232332f6f6d6e692d6c6f676f2e6a7067"&gt;&lt;img src="https://camo.githubusercontent.com/8dae8f5aac69fb677a40f5f4155d18e4d1ae68f3029f1bcc1def230efa2fe0d8/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f64617a6474393764332f696d6167652f75706c6f61642f635f7363616c652c715f6175746f3a626573742c775f3230302f76313630363535383232332f6f6d6e692d6c6f676f2e6a7067" alt="Omni font loader logo"&gt;&lt;/a&gt;
&lt;br&gt;&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Gatsby Omni Font Loader v2&lt;/h1&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Simple way to add webfonts or custom fonts to Gatsby project&lt;/li&gt;
&lt;li&gt;Performant asynchronous font loading can be enabled&lt;/li&gt;
&lt;li&gt;Font loading listener can be enabled&lt;/li&gt;
&lt;li&gt;Flash Of Unstyled Text (FOUT) handling support&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/54c13c4777dcc9528f895e6722449ca520c9aaa33e861d39a25c57615dd501ea/68747470733a2f2f62616467656e2e6e65742f6769746875622f7461672f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/54c13c4777dcc9528f895e6722449ca520c9aaa33e861d39a25c57615dd501ea/68747470733a2f2f62616467656e2e6e65742f6769746875622f7461672f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f5b83464b7938005ce9d6700d82cd6cf137382f8dd6918b55255328ae47bc352/68747470733a2f2f62616467656e2e6e65742f6e706d2f64742f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/f5b83464b7938005ce9d6700d82cd6cf137382f8dd6918b55255328ae47bc352/68747470733a2f2f62616467656e2e6e65742f6e706d2f64742f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/d88d8d77fa79e828eea397f75a1ebd114d13488aeec4747477ffbd2274de95ed/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5052732d77656c636f6d652d627269676874677265656e2e737667"&gt;&lt;img src="https://camo.githubusercontent.com/d88d8d77fa79e828eea397f75a1ebd114d13488aeec4747477ffbd2274de95ed/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5052732d77656c636f6d652d627269676874677265656e2e737667"&gt;&lt;/a&gt;
&lt;br&gt;&lt;br&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/0199b1881fd04512e79ff3c2376142b1474e8f1fa3a58e5836c067542386fac1/68747470733a2f2f62616467656e2e6e65742f6769746875622f73746172732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/0199b1881fd04512e79ff3c2376142b1474e8f1fa3a58e5836c067542386fac1/68747470733a2f2f62616467656e2e6e65742f6769746875622f73746172732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/637bfc8960e1c94db38d265b8809325f09a7f0cba609b1b68c38c3105025a439/68747470733a2f2f62616467656e2e6e65742f6769746875622f6f70656e2d6973737565732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/637bfc8960e1c94db38d265b8809325f09a7f0cba609b1b68c38c3105025a439/68747470733a2f2f62616467656e2e6e65742f6769746875622f6f70656e2d6973737565732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/741cd101249003f318932bfa213c9159dd48f1c4d7250efdaeff992562da7311/68747470733a2f2f62616467656e2e6e65742f6769746875622f636c6f7365642d6973737565732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/741cd101249003f318932bfa213c9159dd48f1c4d7250efdaeff992562da7311/68747470733a2f2f62616467656e2e6e65742f6769746875622f636c6f7365642d6973737565732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/2af645cd88e5c3cf58e6beaaf3b1b39cfd6d978ddc7f53708def3f0b5854e504/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6173742d636f6d6d69742f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f616465722f6d61696e"&gt;&lt;img src="https://camo.githubusercontent.com/2af645cd88e5c3cf58e6beaaf3b1b39cfd6d978ddc7f53708def3f0b5854e504/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6173742d636f6d6d69742f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f616465722f6d61696e"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/9d49d2909879e36c50874a9125c32e71b789e148171db21b56e9674750a0e959/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6963656e73652f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/9d49d2909879e36c50874a9125c32e71b789e148171db21b56e9674750a0e959/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6963656e73652f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/63e0e92cf0fac34d0678ba15e79ec135d32bee57484f5f66d7137ebd8faed9e6/68747470733a2f2f62616467656e2e6e65742f7061636b61676570686f6269612f696e7374616c6c2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/63e0e92cf0fac34d0678ba15e79ec135d32bee57484f5f66d7137ebd8faed9e6/68747470733a2f2f62616467656e2e6e65742f7061636b61676570686f6269612f696e7374616c6c2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Supports web fonts &amp;amp; self-hosted fonts&lt;/li&gt;
&lt;li&gt;Preloads the files &amp;amp; preconnects to the URL&lt;/li&gt;
&lt;li&gt;Loads fonts asynchronously to avoid render blocking&lt;/li&gt;
&lt;li&gt;Implemented with &lt;a href="https://csswizardry.com/2020/05/the-fastest-google-fonts/" rel="nofollow noopener noreferrer"&gt;fast loading snippets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Loading status listener for avoiding FOUT&lt;/li&gt;
&lt;li&gt;Small size &amp;amp; minimal footprint&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;npm install gatsby-omni-font-loader react-helmet&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;&lt;code&gt;yarn add gatsby-omni-font-loader react-helmet&lt;/code&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Configuration&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Add the following snippet to &lt;code&gt;gatsby-config.js&lt;/code&gt; plugins array.&lt;/p&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c"&gt;/* Include plugin */&lt;/span&gt;
  &lt;span class="pl-c1"&gt;resolve&lt;/span&gt;: &lt;span class="pl-s"&gt;"gatsby-omni-font-loader"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c"&gt;/* Plugin options */&lt;/span&gt;
  &lt;span class="pl-c1"&gt;options&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt;

    &lt;span class="pl-c"&gt;/* Font loading mode */&lt;/span&gt;
    &lt;span class="pl-c1"&gt;mode&lt;/span&gt;: &lt;span class="pl-s"&gt;"async"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;

    &lt;span class="pl-c"&gt;/* Enable font loading listener to handle FOUT */&lt;/span&gt;
    &lt;span class="pl-c1"&gt;enableListener&lt;/span&gt;: &lt;span class="pl-c1"&gt;true&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;

    &lt;span class="pl-c"&gt;/* Preconnect URL-s. This example is for Google Fonts */&lt;/span&gt;
    &lt;span class="pl-c1"&gt;preconnect&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s"&gt;"https://fonts.gstatic.com"&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;

    &lt;span class="pl-c"&gt;/* Self-hosted fonts&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/codeAdrian/gatsby-omni-font-loader" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  Open-source mindset
&lt;/h1&gt;

&lt;p&gt;Have you developed something useful, reusable and that is well-made? Why not publish it as an NPM package?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consider open-sourcing and publishing the NPM package that you wish you had available out of the box&lt;/strong&gt;. Because there is a good chance there are quite a few more devs out there who might find the code useful.&lt;/p&gt;

&lt;p&gt;However, if you decide on publishing the package, you should also keep in mind that you should also maintain it. If the package gains traction with the community, you can expect a few issues to open up, feature requests, and pull requests.&lt;/p&gt;

&lt;p&gt;For now, let's keep the focus on publishing the package.&lt;/p&gt;

&lt;h1&gt;
  
  
  NPM best practices
&lt;/h1&gt;

&lt;p&gt;I've outlined some NPM best practices in the article I wrote about a year ago.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adrianbdesigns" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F91468%2Fcdda7312-9dc4-4b73-98ed-fb0c3d55a624.jpg" alt="adrianbdesigns"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/adrianbdesigns/checklist-for-choosing-an-optimal-npm-package-4dpm" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Checklist for choosing an optimal npm package&lt;/h2&gt;
      &lt;h3&gt;Adrian Bece ・ Aug 22 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#npm&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;What does it mean for your NPM package?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure that dependency packages are kept up to date to avoid vulnerabilities&lt;/li&gt;
&lt;li&gt;Address any issues that have been reported&lt;/li&gt;
&lt;li&gt;Engage with people posting issues, feature requests, questions, etc.&lt;/li&gt;
&lt;li&gt;Keep the package and the code optimized&lt;/li&gt;
&lt;li&gt;Let the community know why your package stands above its competition&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz4rtbwkudxpdq72b4x44.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%2Fz4rtbwkudxpdq72b4x44.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
GitHub alerts you if your repo contains any vulnerabilities



&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%2Ffn9cv6e04mgp2pzk1edu.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%2Ffn9cv6e04mgp2pzk1edu.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
It even creates automatic PRs for fixes



&lt;h1&gt;
  
  
  High-quality, informative docs
&lt;/h1&gt;

&lt;p&gt;You need to provide informative docs so the community knows what your NPM package does, why they need it, and how do they use it.&lt;/p&gt;

&lt;p&gt;Docs can be usually added with &lt;code&gt;README.md&lt;/code&gt; in the repo and they usually feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A short description of the package&lt;/li&gt;
&lt;li&gt;How to install it&lt;/li&gt;
&lt;li&gt;Simplest use-case&lt;/li&gt;
&lt;li&gt;Available options for configurations&lt;/li&gt;
&lt;li&gt;Examples and advance tips&lt;/li&gt;
&lt;li&gt;FAQ or troubleshooting (to avoid repeated questions or issues unrelated to your NPM package)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Bug reports &amp;amp; contribution
&lt;/h1&gt;

&lt;p&gt;As devs are downloading and using your npm package, it's unavoidable that they're either discover, have a feature request, send a pull request, or ask a question.&lt;/p&gt;

&lt;p&gt;Maintaining a healthy user-base and engaging with the users is the best way to keep your NPM package going and used. No one likes to see an NPM package that has 10 or more issues open and no responses for weeks. That will discourage users from using your package.&lt;/p&gt;

&lt;h1&gt;
  
  
  What to do if the package doesn't get any traction?
&lt;/h1&gt;

&lt;p&gt;At the time of writing this article, there are exactly 1,445,808 packages on NPM. So it's no surprise if your package doesn't get any traction or is not widely used. You can bet there are at least a dozen alternatives for whatever package you decide to develop, so having some stand-out feature is important.&lt;/p&gt;

&lt;p&gt;But what to do if the package doesn't get any traction? You can either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spread the word - share it on social media, dev forums and channels, write articles, improve docs, ask colleagues to try it out...&lt;/li&gt;
&lt;li&gt;Deprecate it&lt;/li&gt;
&lt;li&gt;Transfer ownership to someone else who is willing to continue your work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your package has dependencies, you don't want to leave it with vulnerabilities, so it's better to deprecate it if you decided not to continue maintaining it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Publishing an NPM package is not only a set-and-forget kind of thing. Your dependencies might be outdated which leads to security issues, and users might ask questions, report bugs, offer pull requests, etc.&lt;/p&gt;

&lt;p&gt;If you are publishing the package, make sure that you are ready to engage with your users from time to time, and to make sure that the dependencies are up to date.&lt;/p&gt;




&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-red.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>npm</category>
    </item>
    <item>
      <title>Made the switch to Discord from Slack or MS Teams? Want to hear your thoughts</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Sun, 15 Nov 2020 22:57:16 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/made-the-switch-to-discord-from-slack-or-ms-teams-want-to-hear-your-thoughts-3j0j</link>
      <guid>https://dev.to/adrianbdesigns/made-the-switch-to-discord-from-slack-or-ms-teams-want-to-hear-your-thoughts-3j0j</guid>
      <description>&lt;p&gt;Our team is considering moving from Slack to Discord and we want to know if anyone else has made the switch and how it affected their communications, productivity, performance, etc.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>help</category>
      <category>programming</category>
    </item>
    <item>
      <title>Load fonts asynchronously &amp; handle FOUT with my Gatsby plugin</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Tue, 03 Nov 2020 06:42:35 +0000</pubDate>
      <link>https://dev.to/prototyp/load-fonts-asynchronously-handle-fout-with-my-gatsby-plugin-19e</link>
      <guid>https://dev.to/prototyp/load-fonts-asynchronously-handle-fout-with-my-gatsby-plugin-19e</guid>
      <description>&lt;p&gt;In the past few weeks I was familiarizing myself with Gatsby and I was making a list of plugins that are good-to-have while working on a project. I went through the SEO plugins, SVG plugins, data source plugins, and finally, I wanted to check out some font loader plugins when I noticed something strange.&lt;/p&gt;

&lt;p&gt;Here are the top two Gatsby plugins for fonts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbrx26n7mtszd9ds2w3em.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbrx26n7mtszd9ds2w3em.PNG" alt="Alt Text" width="430" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

Top two font plugins for Gatsby




&lt;p&gt;And if we open any of those two, we are greeted by the following message and README .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkwa9qfvynohcsulgya71.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkwa9qfvynohcsulgya71.PNG" alt="Alt Text" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

Oh no... this isn't good




&lt;p&gt;&lt;strong&gt;Most-used plugins are abandoned, deprecated and not actively maintained&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Don't get me wrong, it's totally okay for authors and companies to back down from developing and maintaining an open-source repo. I think it would be better to transfer the ownership to someone who wants to continue the development beforehand rather than leaving it as is and archiving it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous font loading
&lt;/h2&gt;

&lt;p&gt;That missing support for the most-used plugins was my primary motivation to develop the font loader plugin, but what do font loaders even do?&lt;/p&gt;

&lt;p&gt;In short, &lt;strong&gt;font loaders help eliminate render-blocking resources&lt;/strong&gt;, in this case, fonts and their respective CSS files. I've gone into more detail about render-blocking resources in one of my previous articles.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/prototyp" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nRxnx9N5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Forganization%252Fprofile_image%252F1014%252F22219225-134b-498e-a18b-42f9ae9cd91d.jpg" alt="PROTOTYP" width="150" height="150"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V9WiJ0zi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F91468%252Fcdda7312-9dc4-4b73-98ed-fb0c3d55a624.jpg" alt="" width="150" height="150"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/prototyp/improving-website-performance-by-eliminating-render-blocking-css-and-javascript-28ei" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Improving website performance by eliminating render-blocking CSS and JavaScript&lt;/h2&gt;
      &lt;h3&gt;Adrian Bece for PROTOTYP ・ Aug 31 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;When a website document is loaded, it automatically starts downloading high-priority resources that are needed before displaying the page - CSS, JavaScript, images, iframe, videos, fonts... Depending on how we instruct the browser, we can load some of those resources after the page has been displayed (rendered). By doing this, we are displaying the content as fast as possible to the user and loading all non-critical resources afterward to speed up the loading process.&lt;/p&gt;

&lt;p&gt;This is especially true for web fonts, like Google fonts for example. During our page load, we are requesting a font CSS file from Google servers which also requests additional font files from Google CDN. Our page is not displayed until this chain of request resolves which can take some time depending on the CDN performance and user's internet connection.&lt;/p&gt;

&lt;p&gt;With asynchronous loading, we can give a low priority to the font file and CSS and load it after the page is displayed. Although this has improved site performance, we have created a minor visual issue - Flash of Unstyled Text (FOUT). &lt;/p&gt;

&lt;h2&gt;
  
  
  Flash Of Unstyled Text (FOUT)
&lt;/h2&gt;

&lt;p&gt;If the font is loaded after page content is displayed, we can see the moment the font changes between the fallback (default) font and the main web font that has been loaded asynchronously. This event is called &lt;strong&gt;Flash Of Unstyled Text&lt;/strong&gt; or &lt;strong&gt;FOUT&lt;/strong&gt;, for short. This change might even affect the page layout, size of some elements and even cause some visual bugs because the page is styled with web font in mind.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcblxyti7vjq5ms3t5lk9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcblxyti7vjq5ms3t5lk9.gif" alt="Alt Text" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

This isn't all that bad considering the performance gain, but it is very noticeable




&lt;p&gt;What we can do to make this effect much less noticeable is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose the fallback font that looks as closely as possible to the web font that is being loaded asynchronously &lt;/li&gt;
&lt;li&gt;Adjust font size, line height, letter spacing and word spacing to match the web font as closely as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After adjusting the fallback font CSS, we get the following result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkwjrk9kwln3ybqjsd352.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkwjrk9kwln3ybqjsd352.gif" alt="Alt Text" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

We've adjusted the style (line-height, letter spacing, word spacing) of fallback font and the change looks nicer




&lt;p&gt;You might be asking: &lt;strong&gt;how can we detect when the font has been download and applied to the document?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We'll have to use JavaScript to detect that event. In case of Gatsby, I've written &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-omni-font-loader/"&gt;a plugin&lt;/a&gt; that both loads the web font asynchronously and it listens to font load event and applies a CSS class to HTML body element to handle FOUT.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gatsby omni font loader plugin
&lt;/h2&gt;

&lt;p&gt;During the past week, I've been working on creating a Gatsby plugin that will use the &lt;a href="https://csswizardry.com/2020/05/the-fastest-google-fonts/"&gt;recommended way of loading fonts&lt;/a&gt; and enable devs to handle FOUT easily.&lt;/p&gt;

&lt;p&gt;And few days ago, I've published &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-omni-font-loader/"&gt;Gatsby Omni Font Loader&lt;/a&gt; that can work with both web fonts and self-hosted fonts, add preload and preconnect on SSR, add font asynchronously, and handle FOUT. All in one small, neat package.&lt;/p&gt;

&lt;p&gt;You can check out the &lt;a href="https://github.com/codeAdrian/gatsby-omni-font-loader"&gt;source code on Github&lt;/a&gt;. Feel free to submit issues, feature requests and pull requests. Support and contribution are very much appreciated!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/codeAdrian"&gt;
        codeAdrian
      &lt;/a&gt; / &lt;a href="https://github.com/codeAdrian/gatsby-omni-font-loader"&gt;
        gatsby-omni-font-loader
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Font loader optimized for maximum performance. Removes render-blocking font resources and loads them asynchronusly. Handle FOUT &amp;amp; FOUC with font loading status watcher. Supports both local-hosted fonts and web fonts.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/cd560c1984341cad2e82289ce08218e9c36d5cf9f0127f409fa9142fce7920bf/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f64617a6474393764332f696d6167652f75706c6f61642f635f7363616c652c715f6175746f3a626573742c775f3230302f76313630363535383232332f6f6d6e692d6c6f676f2e6a7067"&gt;&lt;img src="https://camo.githubusercontent.com/cd560c1984341cad2e82289ce08218e9c36d5cf9f0127f409fa9142fce7920bf/68747470733a2f2f7265732e636c6f7564696e6172792e636f6d2f64617a6474393764332f696d6167652f75706c6f61642f635f7363616c652c715f6175746f3a626573742c775f3230302f76313630363535383232332f6f6d6e692d6c6f676f2e6a7067" alt="Omni font loader logo"&gt;&lt;/a&gt;
&lt;br&gt;&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Gatsby Omni Font Loader v2&lt;/h1&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Simple way to add webfonts or custom fonts to Gatsby project&lt;/li&gt;
&lt;li&gt;Performant asynchronous font loading can be enabled&lt;/li&gt;
&lt;li&gt;Font loading listener can be enabled&lt;/li&gt;
&lt;li&gt;Flash Of Unstyled Text (FOUT) handling support&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/3f47f9da6641f1680e24169f1a5484d332b915b8ede71a5f79f97597aeefce5c/68747470733a2f2f62616467656e2e6e65742f6769746875622f7461672f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/3f47f9da6641f1680e24169f1a5484d332b915b8ede71a5f79f97597aeefce5c/68747470733a2f2f62616467656e2e6e65742f6769746875622f7461672f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/5242823bd7a94f36b0e2ee5d3fa61dc037c8bd0ed0e4b94f20b78695f4bb32e7/68747470733a2f2f62616467656e2e6e65742f6e706d2f64742f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/5242823bd7a94f36b0e2ee5d3fa61dc037c8bd0ed0e4b94f20b78695f4bb32e7/68747470733a2f2f62616467656e2e6e65742f6e706d2f64742f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/7f745fb7dd2a22f68fe03adcdb977963ada4c8265675e572c629b29b9b34af2b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5052732d77656c636f6d652d627269676874677265656e2e737667"&gt;&lt;img src="https://camo.githubusercontent.com/7f745fb7dd2a22f68fe03adcdb977963ada4c8265675e572c629b29b9b34af2b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5052732d77656c636f6d652d627269676874677265656e2e737667"&gt;&lt;/a&gt;
&lt;br&gt;&lt;br&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/dea03df67bccd33429108a136644d683f833776a3da7a21979b7e39aa20a634a/68747470733a2f2f62616467656e2e6e65742f6769746875622f73746172732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/dea03df67bccd33429108a136644d683f833776a3da7a21979b7e39aa20a634a/68747470733a2f2f62616467656e2e6e65742f6769746875622f73746172732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b79492c5a51ca3cfc3645f15e5986984462db27519b56bd51cfa726c58c1d77e/68747470733a2f2f62616467656e2e6e65742f6769746875622f6f70656e2d6973737565732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/b79492c5a51ca3cfc3645f15e5986984462db27519b56bd51cfa726c58c1d77e/68747470733a2f2f62616467656e2e6e65742f6769746875622f6f70656e2d6973737565732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a943bc78363b197ece6cef6876f21df7a9c78f1780a8ba0d0d9e90b915a53263/68747470733a2f2f62616467656e2e6e65742f6769746875622f636c6f7365642d6973737565732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/a943bc78363b197ece6cef6876f21df7a9c78f1780a8ba0d0d9e90b915a53263/68747470733a2f2f62616467656e2e6e65742f6769746875622f636c6f7365642d6973737565732f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/64b1142a66bdcd3dc48c7c7674b4bdb29e48164f5bc8d8fc077a8b61b7bec84a/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6173742d636f6d6d69742f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f616465722f6d61696e"&gt;&lt;img src="https://camo.githubusercontent.com/64b1142a66bdcd3dc48c7c7674b4bdb29e48164f5bc8d8fc077a8b61b7bec84a/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6173742d636f6d6d69742f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f616465722f6d61696e"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b5fe51dd638ca13f35cad82179cf6ae2df0b9d708b47effb3f66a30f097966bd/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6963656e73652f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/b5fe51dd638ca13f35cad82179cf6ae2df0b9d708b47effb3f66a30f097966bd/68747470733a2f2f62616467656e2e6e65742f6769746875622f6c6963656e73652f636f646541647269616e2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/e5db49857ebf94cb45fb5037414c2f756759576a0991bea64c6b052a3cd9a684/68747470733a2f2f62616467656e2e6e65742f7061636b61676570686f6269612f696e7374616c6c2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;img src="https://camo.githubusercontent.com/e5db49857ebf94cb45fb5037414c2f756759576a0991bea64c6b052a3cd9a684/68747470733a2f2f62616467656e2e6e65742f7061636b61676570686f6269612f696e7374616c6c2f6761747362792d6f6d6e692d666f6e742d6c6f61646572"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Supports web fonts &amp;amp; self-hosted fonts&lt;/li&gt;
&lt;li&gt;Preloads the files &amp;amp; preconnects to the URL&lt;/li&gt;
&lt;li&gt;Loads fonts asynchronously to avoid render blocking&lt;/li&gt;
&lt;li&gt;Implemented with &lt;a href="https://csswizardry.com/2020/05/the-fastest-google-fonts/" rel="nofollow"&gt;fast loading snippets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Loading status listener for avoiding FOUT&lt;/li&gt;
&lt;li&gt;Small size &amp;amp; minimal footprint&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;npm install gatsby-omni-font-loader react-helmet&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;&lt;code&gt;yarn add gatsby-omni-font-loader react-helmet&lt;/code&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Configuration&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Add the following snippet to &lt;code&gt;gatsby-config.js&lt;/code&gt; plugins array.&lt;/p&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c"&gt;/* Include plugin */&lt;/span&gt;
  &lt;span class="pl-c1"&gt;resolve&lt;/span&gt;: &lt;span class="pl-s"&gt;"gatsby-omni-font-loader"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c"&gt;/* Plugin options */&lt;/span&gt;
  &lt;span class="pl-c1"&gt;options&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt;

    &lt;span class="pl-c"&gt;/* Font loading mode */&lt;/span&gt;
    &lt;span class="pl-c1"&gt;mode&lt;/span&gt;: &lt;span class="pl-s"&gt;"async"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;

    &lt;span class="pl-c"&gt;/* Enable font loading listener to handle FOUT */&lt;/span&gt;
    &lt;span class="pl-c1"&gt;enableListener&lt;/span&gt;: &lt;span class="pl-c1"&gt;true&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;

    &lt;span class="pl-c"&gt;/* Preconnect URL-s. This example is for Google Fonts */&lt;/span&gt;
    &lt;span class="pl-c1"&gt;preconnect&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s"&gt;"https://fonts.gstatic.com"&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;

    &lt;span class="pl-c"&gt;/* Self-hosted fonts&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/codeAdrian/gatsby-omni-font-loader"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Start by installing the plugin with NPM or Yarn.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; gatsby-omni-font-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; gatsby-omni-font-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure the plugin
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;gatsby-config.js&lt;/code&gt; file, reference the &lt;code&gt;gatsby-omni-font-loader&lt;/code&gt; plugin in the &lt;code&gt;plugins&lt;/code&gt; array and configure it.&lt;/p&gt;

&lt;p&gt;Below is the sample config and explanation for each of the options available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* Include plugin */&lt;/span&gt;
  &lt;span class="nl"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gatsby-omni-font-loader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="cm"&gt;/* Plugin options */&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="cm"&gt;/* Enable font loading listener to handle FOUC */&lt;/span&gt;
    &lt;span class="nl"&gt;enableListener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="cm"&gt;/* Preconnect URL-s. This example is for Google Fonts */&lt;/span&gt;
    &lt;span class="nx"&gt;preconnect&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;https://fonts.gstatic.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="cm"&gt;/* Self-hosted fonts config. Add font files and font CSS files to "static" folder */&lt;/span&gt;
    &lt;span class="nx"&gt;custom&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="cm"&gt;/* Exact name of the font as defied in @font-face CSS rule */&lt;/span&gt;
        &lt;span class="na"&gt;name&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;Font Awesome 5 Brands&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Font Awesome 5 Free&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="cm"&gt;/* Path to the font CSS file inside the "static" folder with @font-face definition */&lt;/span&gt;
        &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/fonts/fontAwesome/css/all.min.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="cm"&gt;/* Web fonts. File link should point to font CSS file. */&lt;/span&gt;
    &lt;span class="nx"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="cm"&gt;/* Exact name of the font as defied in @font-face CSS rule */&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Staatliches&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="cm"&gt;/* URL to the font CSS file with @font-face definition */&lt;/span&gt;
        &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://fonts.googleapis.com/css2?family=Staatliches&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;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;
  
  
  Handling FOUT
&lt;/h3&gt;

&lt;p&gt;When &lt;code&gt;enableListener: true&lt;/code&gt; is set in plugin config in &lt;code&gt;gatsby-config.js&lt;/code&gt;, HTML classes are being added to &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element as the fonts are being loaded.&lt;/p&gt;

&lt;p&gt;HTML class name format will be in the following format&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wf-[font-family-name]--loaded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the &lt;a href="https://meowni.ca/font-style-matcher/"&gt;Font Style Matcher&lt;/a&gt; to adjust the perfect fallback font and fallback CSS config and use the styles from there.&lt;/p&gt;

&lt;p&gt;Here is the example of how body element will look like after all fonts are being loaded (depending on the config).&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&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"wf-font-awesome-5-brands--loaded wf-font-awesome-5-free--loaded wf-staatliches--loaded"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the CSS will look something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="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="s1"&gt;"Merriweather"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Georgia&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="c"&gt;/* default styles */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&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;.wf-merriweather--loaded&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c"&gt;/* fallback font (Georgia) CSS config */&lt;/span&gt;
 &lt;span class="c"&gt;/* line-height, letter spacing, font-size... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&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;.wf-merriweather--loaded&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c"&gt;/* fallback font (Georgia) CSS config */&lt;/span&gt; 
 &lt;span class="c"&gt;/* line-height, letter spacing, font-size... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.wf-merriweather--loaded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c"&gt;/* web font CSS config */&lt;/span&gt; 
 &lt;span class="c"&gt;/* line-height, letter spacing, font-size... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.wf-merriweather--loaded&lt;/span&gt; &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c"&gt;/* web font CSS config */&lt;/span&gt; 
 &lt;span class="c"&gt;/* line-height, letter spacing, font-size... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Igf3SR33--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.buymeacoffee.com/buttons/default-red.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

</description>
      <category>react</category>
      <category>gatsby</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Some Halloween CSS fun</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Wed, 28 Oct 2020 15:10:59 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/some-halloween-css-fun-4k0c</link>
      <guid>https://dev.to/adrianbdesigns/some-halloween-css-fun-4k0c</guid>
      <description>&lt;p&gt;Hello DEV community, I've created a fun little CSS file to add to your personal project. &lt;/p&gt;

&lt;p&gt;I won't show you what it is, but feel free to discover it for yourselves... if you dare.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/codeAdrian/tome-of-darkness"&gt;Tome of darkness&lt;/a&gt; is in your hands... what will you do?&lt;/p&gt;

</description>
      <category>css</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Let's do a frontend &amp; UX review - YR redesign</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 12 Oct 2020 05:52:32 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/let-s-do-a-frontend-ux-review-yr-redesign-7b1</link>
      <guid>https://dev.to/adrianbdesigns/let-s-do-a-frontend-ux-review-yr-redesign-7b1</guid>
      <description>&lt;p&gt;In this series I'm going to choose a random website, analyze the frontend code (performance &amp;amp; best practices) and UX, and present my findings. By taking a look at the issues on existing projects, we can improve our coding and UX skills and learn how to avoid issues in our own projects.&lt;/p&gt;

&lt;p&gt;I have more than 5 years of experience in frontend development, eCommerce and writing professional-grade frontend audits and I've learned a lot by doing audits.&lt;/p&gt;



&lt;small&gt;Users having trouble using your website? Or you just want someone to check if your website is up to par and following best practices? &lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ/e/7603" rel="noopener noreferrer"&gt;I can do a frontend and UX audit for your website&lt;/a&gt;. Limited slots available.&lt;/small&gt;

&lt;p&gt;This week, we'll be taking at the redesigned version of a popular worldwide weather forecast website, &lt;a href="https://www.yr.no/en" rel="noopener noreferrer"&gt;yr.no&lt;/a&gt; and compare it to the &lt;a href="https://www.yr.no/" rel="noopener noreferrer"&gt;current design&lt;/a&gt; and see how it fares. I've been using Yr website for years now and it's one of my go-to sites for checking weather forecast.&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%2Ftdfa3b6l7r011iaays8c.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%2Ftdfa3b6l7r011iaays8c.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Current YR website



&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%2Fk1wu4krojmlyka0va7vv.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%2Fk1wu4krojmlyka0va7vv.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Redesigned YR website



&lt;h2&gt;
  
  
  Mobile support
&lt;/h2&gt;

&lt;p&gt;Why is mobile support important? Responsive web design (RWD) has been around for years and desktop-oriented websites and services were eager to jump on RWD train.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet" rel="noopener noreferrer"&gt;Global Stats&lt;/a&gt; around 53% of users use mobile and tablet devices to browse the web. This is why it's important to offer a mobile-friendly site or you can use up to 50% of potential users.&lt;/p&gt;

&lt;p&gt;Considering the fact that &lt;strong&gt;users want the weather forecast data on-demand&lt;/strong&gt; and want to get that info quickly and painlessly, it's important to have a good mobile-friendly website (maybe a PWA). &lt;/p&gt;

&lt;p&gt;YR's current site is not mobile friendly. And we can see how it looks like from the screenshot. User has to zoom in and out and hope that website is touch-friendly out of the box. &lt;strong&gt;Users dislike inconvenience and they won't think twice before moving onto a competitor's website or service&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsdrdauaxbktqm3a5n818.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%2Fsdrdauaxbktqm3a5n818.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's compare the current website to the new, mobile-friendly website. Notice how it's easy to navigate it and view data.&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%2F4li9mnhfs9bprygdnofj.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%2F4li9mnhfs9bprygdnofj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Added mobile-friendly features are a definite win when it comes to the redesign. But the rest is far from perfect...&lt;/p&gt;

&lt;h2&gt;
  
  
  Streamlined or dumbed-down?
&lt;/h2&gt;

&lt;p&gt;What I found unpleasantly surprising is how redesign doesn't serve the content which is the main purpose of the website - design needs to simplify how users search and perceive the weather forecast information.&lt;/p&gt;

&lt;p&gt;For example, let's look at the weather forecast overview on the current page. Just scanning through the tables I can instantly see which forecast is related to which day and info is nicely presented in the table. Everything is clear from the first scan. &lt;strong&gt;Forecast information for individual days is located in separate tables&lt;/strong&gt; which makes info nicely grouped and presented.&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%2F1kcqhzidj4q420ozfjr6.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%2F1kcqhzidj4q420ozfjr6.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

Current website - Forecast overview




&lt;p&gt;As for the redesign... what is this? The information is not as clear as in the previous case. Each day is now presented in a separate table row, but we've lost quite a bit of info. &lt;/p&gt;

&lt;p&gt;Table is now difficult to read, due to the it being so wide and every data point is now merged into a single table (without any background colors guides for even rows).&lt;/p&gt;

&lt;p&gt;Instead having individual temperature, rain and wind info for each quarter of the day, now we have the combined information for the whole day. Only detailed infos for the times of the day is presented with weather icons. Table is too wide and users might find the info difficult to scan and parse - on desktop lot of eye movementis required and on mobile user needs to scroll the table horizontally.&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%2Fcksy5b8mt711muewv58h.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%2Fcksy5b8mt711muewv58h.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

Redesigned website - Forecast overview




&lt;p&gt;Same can be said for the graphs data. On the current YR site, graphs show temperature, rain, wind and weather forecast data for the next 48 hours in 1 hour intervals. It's easy to connect the date and time to each data value. If user is interested in detailed table-view of the data, they can scroll down.&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%2Fumocyc8go6at391o0hcb.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%2Fumocyc8go6at391o0hcb.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

Current website - graph data




&lt;p&gt;On the redesigned website, graph data is expanded to 7 day range and graph is both tall and wide, with no additional detailed data at the bottom. The graph is difficult to read and only when user hovers on the data point can get a more accurate info. &lt;strong&gt;Redesign made graph difficult to read and added an extra step in order to better perceive the data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F503u79zsin1z4r975iqs.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%2F503u79zsin1z4r975iqs.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

Redesigned website - graph data




&lt;h2&gt;
  
  
  Don't hide info in modals
&lt;/h2&gt;

&lt;p&gt;Redesign was done with some questionable design choices. Most apparent issue is how data is presented in a non-compact way - everything is stretch tall and wide. Graphs and tables take way up too much screen space on desktop and mobile and are difficult to read.&lt;/p&gt;

&lt;p&gt;What was the solution? Just make the user hover or click on the data point they interested and they'll get a dropdown or modal element with the details, respectively. &lt;strong&gt;Redesign produced an severe UX issue. Users are now required to click on data to better read and understand it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpilgnfnurzpa9xzo0xb3.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%2Fpilgnfnurzpa9xzo0xb3.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

Redesigned website - useful data hidden in annoying modals




&lt;p&gt;Current website, in my opinion, is not cluttered to warrant such a design choice - to hide everything in modals.&lt;/p&gt;

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

&lt;p&gt;This redesign is a classic case of "don't fix what isn't broken". With it, YR website lost its identity in the process of streamlining. The redesign needed to refresh the (a bit) outdated and add a responsive styles to make the website mobile-friendly. Instead, the redesign dumbed-down the website and made the data difficult to read and understand.&lt;/p&gt;

&lt;p&gt;If possbile YR design and dev tam should consider going back to the drawing board and create a design that will make both mobile and desktop website delightful to use. It's important to understand your users and create a web app that answers user's questions in a detailed and quick way - without additional clicks.&lt;/p&gt;



&lt;small&gt;This was just s small taste of professional audits that I do regularly. Don't make these kinds of mistakes when redesigning your website, &lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ/e/7603" rel="noopener noreferrer"&gt;let me help you take your website to the next level&lt;/a&gt;. Limited slots available.&lt;/small&gt;

&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-red.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>ux</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Let's do a frontend &amp; UX review - Dr. Martens</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 05 Oct 2020 06:00:13 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/let-s-do-a-frontend-ux-review-dr-martens-31dn</link>
      <guid>https://dev.to/adrianbdesigns/let-s-do-a-frontend-ux-review-dr-martens-31dn</guid>
      <description>&lt;p&gt;In this series I'm going to choose a random website, analyze the frontend code (performance &amp;amp; best practices) and UX, and present my findings. By taking a look at the issues on existing projects, we can improve our coding and UX skills and learn how to avoid issues in our own projects.&lt;/p&gt;

&lt;p&gt;I have more than 5 years of experience in frontend development, eCommerce and writing professional-grade frontend audits and I've learned a lot by doing audits.&lt;/p&gt;



&lt;small&gt;Users having trouble using your website? Or you just want someone to check if your website is up to par and following best practices? &lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ/e/7603" rel="noopener noreferrer"&gt;I can do a frontend and UX audit for your website&lt;/a&gt;. Limited slots available.&lt;/small&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%2Fyp5ctvz1dpdf3s4hdvte.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%2Fyp5ctvz1dpdf3s4hdvte.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, we'll be looking at &lt;a href="https://www.drmartens.com/" rel="noopener noreferrer"&gt;Dr. Martens&lt;/a&gt; website, because I like their shoes and it's an eCommerce site. What a perfect combination to start of the series! I'll go through select few things I've noticed while using the site.&lt;/p&gt;

&lt;p&gt;Let's begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Header &amp;amp; Navigation
&lt;/h2&gt;

&lt;p&gt;Header needs to showcase page branding (logo &amp;amp; colors) and should give users general idea about the content and what the brand is related to. Although Dr. Martens is a well-known brand, the header does a great job of giving users a general high-level overview of different products related to the brand (boots, shoes, laces, work boots, etc.).&lt;/p&gt;

&lt;p&gt;The only issue I've spotted with the header is that it takes too much space. This wouldn't be an issue if the header is not fixed and is always visible when user scrolls. On smaller mobile screens, header can take up to 25% of the screen space.&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%2Fme42nd7khqtx5d1cw1dt.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%2Fme42nd7khqtx5d1cw1dt.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigation is one of the most crucial elements on the website, so it's important for it to be implemented well. Unfortunately, navigation on desktop has a few UX issues. First of all, mega menu displays the moment user hovers on it, which causes an issue when user doesn't want to open the menu but hovers over it accidentally.&lt;/p&gt;

&lt;p&gt;Additionally, user needs to be careful not to switch mega menus when if they hover the mouse from the main category to the links on accident.&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%2Fnwlf4pn4g407p79ta4td.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%2Fnwlf4pn4g407p79ta4td.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Category page
&lt;/h2&gt;

&lt;p&gt;Product images are well done and they showcase products perfectly and I'm leaning more towards this layout of category page for Dr. Martens, rather than a classical 2-column layout with filters listed in the sidebar. Since filters are limited to a dozen or so options, it was a good decision to go with the filters dropdowns listed in a single row.&lt;/p&gt;

&lt;p&gt;Product cards themselves are sort of lacking. On desktop, color variations are displayed on hover, meanwhile the similar product cards on homepage have them displayed all the time. It would be useful to showcase color swatches in a single row, if possible.&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%2Fg0g74vivjh38djrkkj7h.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%2Fg0g74vivjh38djrkkj7h.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Product card on category page



&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%2F4rkwdo30amt85by1kmaa.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%2F4rkwdo30amt85by1kmaa.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Product card on homepage



&lt;p&gt;Additionally, product cards lack a hover (focused) style in order to show the user what is the link to the product and what is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Product page
&lt;/h2&gt;

&lt;p&gt;Product page layout looks alright for most cases.&lt;/p&gt;

&lt;p&gt;On product image swatch hover, I found it confusing for the main product image to change. Clicking on the image swatch takes user to entire different product page, so all changes and previews being done on the current page are not related to the image swatches. If user has selected a shoe size and changed the shoe color after that (link to new product), they lose their shoe size choice because they navigated away. This could be communicated better, although this needs to be solved with redesigning this section.&lt;/p&gt;

&lt;p&gt;Also, I've found a minor issue with the product description. The text container is too wide which makes text difficult to read on regular and wide desktop screens.&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%2F2gug2h0msq8gjvlyj6xp.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%2F2gug2h0msq8gjvlyj6xp.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Checkout
&lt;/h2&gt;

&lt;p&gt;Checkout UX is really well done. Header is simplified to keep customer's focus on the checkout form. This is tried and proven way to boost conversions.&lt;/p&gt;

&lt;p&gt;Checkout form is divided into several steps and there is only 1 input in the row which ensures readability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend performance
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2d86hcwzvhfwemr5qh72.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%2F2d86hcwzvhfwemr5qh72.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on the number of requests, devs should consider merging individual JS and CSS files to reduce the amount of requests. Lazy loading images should also be considered.&lt;/p&gt;

&lt;p&gt;Here are some of the performance issues I've encountered while using Dr. Martens site.&lt;/p&gt;

&lt;p&gt;Homepage document size is about 5Mb, which is a lot of data to load on the first load, especially on slower and unreliable internet connections.&lt;/p&gt;

&lt;p&gt;There is a flash of unstyled text (FOUT) happening on each page load, so fallback font is displayed until the main font loads. This can be solved with caching.&lt;/p&gt;

&lt;p&gt;Additionally, image lazy loading can be improved. Below the fold images can be lazy-loaded to improve loading. Images took up to 50% of website's download size, so more strict lazy loading may improve performance.&lt;/p&gt;

&lt;p&gt;Render-blocking resources can also be loaded in a better way to improve site render times.&lt;/p&gt;

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

&lt;p&gt;Dr. Marten's site has a beautiful design, but there are some fundamental UX issues with header and navigation that need to be fixed. Additionally, color variation functionality on product page needs to be presented in a different way. Cart and checkout are really well done - header and navigation elements are reduced to minimum to keep the user focused on the checkout flow, and checkout form inputs are placed in individual rows and divided into multiple steps which improves conversion rates.&lt;/p&gt;

&lt;p&gt;As for frontend, the site downloads lot of data on the first load (about 5Mb on the homepage) which can be improved by lazy loading images, using critical CSS &amp;amp; improve caching. FOUT when loading a page also looks out of place, which should be fixed by caching fonts or using better fallback fonts.&lt;/p&gt;



&lt;small&gt;This was just s small taste of professional audits that I do regularly. If you want me to do an audit for your website, &lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ/e/7603" rel="noopener noreferrer"&gt;check out the details here&lt;/a&gt;. Limited slots available.&lt;/small&gt;

&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-red.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>productivity</category>
      <category>ux</category>
    </item>
    <item>
      <title>Why you should always consider user intent and expectations when creating UI</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 21 Sep 2020 10:59:40 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/why-you-should-always-consider-user-intent-and-expectations-when-creating-ui-5251</link>
      <guid>https://dev.to/adrianbdesigns/why-you-should-always-consider-user-intent-and-expectations-when-creating-ui-5251</guid>
      <description>&lt;p&gt;When working on a frontend project, we usually get design, specs and user stories describing how UI elements should look and what what function should it have. We use those designs and specs to create the UI and then we launch the project.&lt;/p&gt;

&lt;p&gt;That is all well and good, but users usually won't be aware of the functionality of individual elements. They will either rely on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Their instincts and experience, i.e. their expectations&lt;/li&gt;
&lt;li&gt;Additional information surrounding the UI element&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If users sees a hamburger menu icon, they'll expect some sort of a main menu to appear when they tap on the icon. But if they see a "arrow down" icon next to the website logo, they won't be sure what will happen when they click on it. It could be a main menu, website switcher, language switcher, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fquefv1fgmwrza39fd7q4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fquefv1fgmwrza39fd7q4.PNG" alt="Alt Text" width="493" height="780"&gt;&lt;/a&gt;&lt;/p&gt;
There are more categories below "Libreria" (user needs to scroll), but user won't know that at first



&lt;h2&gt;
  
  
  Value of UX testing
&lt;/h2&gt;

&lt;p&gt;This is why UX testing is so valuable. Everyone on your team, including you will know how the website works from the first line of code to the last, and every functionality and interaction on the website will be clear because you created it, of course.&lt;/p&gt;

&lt;p&gt;Having someone take a look at your project that isn't closely familiar with it can yield valuable data and can help pinpoint bottlenecks and usability issues.&lt;/p&gt;




&lt;p&gt;I am currently offering the &lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ/e/7603"&gt;Frontend and UX audit service&lt;/a&gt;, so please do check it out if you are interested.&lt;/p&gt;



&lt;h2&gt;
  
  
  User intent
&lt;/h2&gt;

&lt;p&gt;We established that user has their own expectations on how UI should work based on their previous experience and how the UI itself is presented and if it's consistent.&lt;/p&gt;

&lt;p&gt;But what about their intentions on the site? Let's take a look at the example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd3el6b0swvhls8oqzqnv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd3el6b0swvhls8oqzqnv.gif" alt="Alt Text" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;User &lt;strong&gt;intents&lt;/strong&gt; to use the sidebar navigation (category filters under "Shop by" section) on the left after they used the search above the menu. User then moves their mouse downwards but the mega menu activates responds on &lt;strong&gt;accidental&lt;/strong&gt; hover and covers entire left navigation! User now has to close the mega menu so they can use the element they've &lt;strong&gt;intented&lt;/strong&gt; to use.&lt;/p&gt;

&lt;p&gt;So you can see how even when we create UI elements with specs and design in mind, we still have to take the bigger picture into consideration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How the element will interact with other elements on the page&lt;/li&gt;
&lt;li&gt;How will the UI element respond to proper user intent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically, we want to make sure that there are no accidents and surprises when interacting with the UI and we want to make sure that UI &lt;strong&gt;responds to user interaction only when user expects it.&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Consider another example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi3fjndlc78mtgc5597q2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi3fjndlc78mtgc5597q2.jpg" alt="Alt Text" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Red arrows mark the natural path user would take when moving the cursor from the menu to the link, but that would cause the menu to change to another submenu because it reacts on hover. Green arrow marks the safe path that developers created and know how to use. But that doesn't &lt;strong&gt;align with user experience and intent when using this UI element.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to avoid accidental interactions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use delay - adding &lt;code&gt;setTimeout&lt;/code&gt; and &lt;code&gt;clearTimeout&lt;/code&gt; with 200ms timeout value to mega menu would fix the issue. User wouldn't even notice this slight delay and user will feel like they have the full control over the &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider interactable area - interactive area might be too wide or narrow. Make sure that the dimensions where user can activate a hover functionality are optimal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure that there is enough information that leads the user down the proper flow and teaches them how to use the UI element&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Navigation that respects user intent and meets their expectations
&lt;/h2&gt;

&lt;p&gt;Here is the navigation I created that leverages the delay and optimized interactible area to make sure that navigation responds to user intent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5tcfrmqlr1zm6iazhgkt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5tcfrmqlr1zm6iazhgkt.gif" alt="Alt Text" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion &amp;amp; extra
&lt;/h2&gt;

&lt;p&gt;We've seen how user expectations and intent can reveal nasty UX issues on our website. These issues can go completely undetected if it's not being &lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ/e/7603"&gt;tested by someone&lt;/a&gt; who doesn't have a complete understanding of website functionality and code.&lt;/p&gt;

&lt;p&gt;We've also seen how we can take user intent into consideration and create UI elements with awesome UX that feels delightful to use.&lt;/p&gt;

&lt;p&gt;I would recommend reading &lt;a href="https://www.bookdepository.com/Dont-Make-Me-Think-Revisited-Steve-Krug/9780321965516?ref=grid-view&amp;amp;qid=1600685335065&amp;amp;sr=1-1"&gt;"Don't make me think" by Steve Krug&lt;/a&gt; to better understand user intent and web UX in general.&lt;/p&gt;




&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Igf3SR33--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.buymeacoffee.com/buttons/default-red.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to polyfill JavaScript fetch function for Internet Explorer</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 07 Sep 2020 07:54:10 +0000</pubDate>
      <link>https://dev.to/adrianbdesigns/how-to-polyfill-javascript-fetch-function-for-internet-explorer-g46</link>
      <guid>https://dev.to/adrianbdesigns/how-to-polyfill-javascript-fetch-function-for-internet-explorer-g46</guid>
      <description>&lt;p&gt;I love using &lt;code&gt;fetch&lt;/code&gt; API for my personal projects. When using Babel and working on React project, ES6 syntax gets transpiled and polyfilled automatically on build time. But what we need to do when we want to use &lt;code&gt;fetch&lt;/code&gt; API on a simple project that doesn't use Babel or Webpack? We need to manually polyfill it, and make sure the additional polyfills do not affect website performance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A polyfill is a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why use "fetch"?
&lt;/h2&gt;

&lt;p&gt;Before &lt;code&gt;fetch&lt;/code&gt; API was introduced, creating HTTP requests using &lt;code&gt;XMLHttpRequest&lt;/code&gt; was complicated and the syntax was not clean and straightforward.&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;xhr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;XMLHttpRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://path/to/api.endpoint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;xhr&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="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle response&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onprogress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle progress&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onerror&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle error&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Yeah, that is a lot of boilerplate code separated into multiple class methods and event handlers.&lt;/p&gt;

&lt;p&gt;There were also some JavaScript plugins and jQuery (ajax) functions that act as a wrapper around &lt;code&gt;XMLHttpRequest&lt;/code&gt; to simplify it and improve the syntax, but there were no official API improvements until ES6 &lt;code&gt;fetch&lt;/code&gt; API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetch API
&lt;/h2&gt;

&lt;p&gt;Fetch API allows us to make HTTP requests using much simpler and straightforward JavaScript syntax to send and receive data, and handle any event using  JavaScript promises.&lt;/p&gt;

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

&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://path/to/api.endpoint&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleFallback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Looks simple enough, right?&lt;/p&gt;

&lt;p&gt;This improved syntax made the whole functionality more accessible and developer-friendly. Although &lt;code&gt;fetch&lt;/code&gt; browser support sits at comfortable 95%, we can easily polyfill it so even more browsers support it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polyfilling fetch for Internet Explorer
&lt;/h2&gt;

&lt;p&gt;We don't want to just add the polyfill to project so it loads for all browsers (including those that support fetch natively). Let's load the polyfill dynamically so extra JavaScript is loaded only if it's required.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;fetch&lt;/code&gt; to work on Internet Explorer, we need to add two polyfills:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Promise polyfill - remember, &lt;code&gt;fetch&lt;/code&gt; uses promises&lt;/li&gt;
&lt;li&gt;Fetch polyfill&lt;/li&gt;
&lt;/ul&gt;

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

&lt;span class="c1"&gt;// Detect if user is on IE browser&lt;/span&gt;
 &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isIE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MSInputMethodContext&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;documentMode&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;isIE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// Create Promise polyfill script tag&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;promiseScript&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="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;promiseScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;promiseScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.jsdelivr.net/npm/promise-polyfill@8.1.3/dist/polyfill.min.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;// Create Fetch polyfill script tag&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;fetchScript&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="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;fetchScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;fetchScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.jsdelivr.net/npm/whatwg-fetch@3.4.0/dist/fetch.umd.min.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;// Add polyfills to head element&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;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promiseScript&lt;/span&gt;&lt;span class="p"&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;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchScript&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Wait for the polyfills to load and run the function. &lt;/span&gt;
      &lt;span class="c1"&gt;// We could have done this differently, &lt;/span&gt;
      &lt;span class="c1"&gt;// but I've found it to work well for my use-cases&lt;/span&gt;
        &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;window&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://path/to/api.endpoint&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleErrors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// If fetch is supported, just run the fetch function&lt;/span&gt;
        &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://path/to/api.endpoint&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleErrors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And that is it. If user is using Internet Explorer, &lt;code&gt;fetch&lt;/code&gt; function will be added to global &lt;code&gt;window&lt;/code&gt; object and be used as &lt;code&gt;window.fetch()&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;I've used this method to load articles from DEV on my &lt;a href="https://codeadrian.github.io/blog/" rel="noopener noreferrer"&gt;personal website&lt;/a&gt; using &lt;code&gt;fetch&lt;/code&gt; and it works as expected. This was really simple to implement and I was happy with the final results. I was also happy that I'm not loading the polyfills if they're not needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Also feel free to leave a comment on how I can improve my code to replace &lt;code&gt;setTimeout&lt;/code&gt; function and make sure that this part of the code waits until polyfill becomes available.&lt;/p&gt;




&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-red.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Improving website performance by eliminating render-blocking CSS and JavaScript</title>
      <dc:creator>Adrian Bece</dc:creator>
      <pubDate>Mon, 31 Aug 2020 07:20:20 +0000</pubDate>
      <link>https://dev.to/prototyp/improving-website-performance-by-eliminating-render-blocking-css-and-javascript-28ei</link>
      <guid>https://dev.to/prototyp/improving-website-performance-by-eliminating-render-blocking-css-and-javascript-28ei</guid>
      <description>&lt;p&gt;In my previous post, I've talked about how I boosted Lighthouse scores for &lt;a href="https://codeadrian.github.io/" rel="noopener noreferrer"&gt;my personal website&lt;/a&gt; by implementing native lazy loading with fallback.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/prototyp" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1014%2F22219225-134b-498e-a18b-42f9ae9cd91d.jpg" alt="PROTOTYP"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F91468%2Fcdda7312-9dc4-4b73-98ed-fb0c3d55a624.jpg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/prototyp/best-way-to-lazy-load-images-for-maximum-performance-27o1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Best way to lazy load images for maximum performance&lt;/h2&gt;
      &lt;h3&gt;Adrian Bece for PROTOTYP ・ Aug 24 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#html&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Another important improvement that boosted my performance and Lighthouse score was eliminating render-blocking resources.&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%2Fw4n411pbs6oiwk6uoc4b.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%2Fw4n411pbs6oiwk6uoc4b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Critical and non-critical resources
&lt;/h2&gt;

&lt;p&gt;When we usually build a project, we like to include everything we need right out of the box - all styles, JavaScript plugins, JavaScript code, fonts, images, etc. We usually do this to make sure that no async loading errors happen while we develop the project.&lt;/p&gt;

&lt;p&gt;The reality is that browser needs to load, parse and run everything we include when website loads, &lt;strong&gt;which can make the first paint (with no cached resources) unnecessarily slow&lt;/strong&gt;. It's called render-blocking because &lt;strong&gt;browser is wasting time and resources parsing the code that is unnecessary for the initial page load&lt;/strong&gt; and not displaying the page content.&lt;/p&gt;

&lt;p&gt;When we take a look at our resources (CSS, JavaScript, fonts, etc.) we can sort them into two categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Critical resources&lt;/strong&gt; - code that's critical to the page's core functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-critical resources&lt;/strong&gt; - code not being used in page's core functionality and a code that runs after the page is loaded or on user interaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's take a look how we to handle critical and non-critical CSS and JavaScript resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling critical CSS
&lt;/h2&gt;

&lt;p&gt;Critical CSS refers to the styles that are &lt;strong&gt;necessary for styling above the fold content&lt;/strong&gt;. Above the fold &lt;strong&gt;content that is visible to users when they first load the page&lt;/strong&gt; (top section of the page).&lt;/p&gt;

&lt;p&gt;In order to add critical CSS to the page, we need to remove those styles from the CSS stylesheet and add them directly to HTML in a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag inside a &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; element.&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;head&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;/* Add critical styles here */&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F840f35f4nwzg5piiypf2.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%2F840f35f4nwzg5piiypf2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Critical CSS on my personal site



&lt;p&gt;This approach may increase HTML document size a bit, but those changes are insignificant if you use compression algorithm like GZIP or Brotli for HTML delivery. &lt;/p&gt;

&lt;p&gt;Adding critical CSS directly to HTML document ensures that those styles and parsed and applied on the first paint (initial load).&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling non-critical CSS
&lt;/h2&gt;

&lt;p&gt;In order to make the critical CSS effective, we need to tell the browser how to handle non-critical CSS and display the page. It also allows us to use the website while the additional non-critical CSS loads. Depending on Internet connection speed, you might not even notice the additional styles being loaded.&lt;/p&gt;

&lt;p&gt;In order to handle non-critical CSS, we need to change how the CSS file which contains those styles loads. &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;head&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/path/to/styles.css"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"style"&lt;/span&gt; &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"this.onload=null;this.rel='stylesheet'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;noscript&amp;gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/path/to/styles.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This may look like a hack at first, but this is a really smart and efficient way of loading CSS in an efficient way with proper fallback:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;link rel="preload" as="style"&lt;/code&gt; loads the CSS file in a non-render-blocking way.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onload="this.onload=null;this.rel='stylesheet'"&lt;/code&gt; makes sure that CSS file is parsed and loaded after the site loads and the &lt;code&gt;onload&lt;/code&gt; function is deleted.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;noscript&lt;/code&gt; fallback makes sure that the CSS loads the standard way if JavaScript is not available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh0jixg77rlm1ols7etqt.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%2Fh0jixg77rlm1ols7etqt.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Non-critical styles being loaded on a below-the-fold content. Notice how some (critical) styles are already applied (grey background) before the rest is loaded (non-critical)



&lt;p&gt;It's also important to note that &lt;strong&gt;we can load Google Fonts stylesheets in the same efficient way!&lt;/strong&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;link&lt;/span&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&amp;amp;display=swap"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"style"&lt;/span&gt; &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"this.onload=null;this.rel='stylesheet'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;noscript&amp;gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&amp;amp;display=swap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Firefox issue &amp;amp; handling IE
&lt;/h3&gt;

&lt;p&gt;At the time of writing this article, &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1405761" rel="noopener noreferrer"&gt;Firefox has a bug&lt;/a&gt; related to preloading CSS. This efficient way of loading non-critical CSS currently isn't working on Firefox, but it should be fixed soon.&lt;/p&gt;

&lt;p&gt;You might want to provide a fallback for browsers that do not support preloading or have issue with it (like Firefox). Luckily, this is really easy to do with inline JavaScript.&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;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isIE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MSInputMethodContext&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;documentMode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;isFirefox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userAgent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firefox&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;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isIE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isFirefox&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;pageStylesheet&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="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;pageStylesheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylesheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;pageStylesheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;pageStylesheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/path/to/styles.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageStylesheet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&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;We just need to add this code before &lt;code&gt;body&lt;/code&gt; closing tag to insert the regular &lt;code&gt;link&lt;/code&gt; element into &lt;code&gt;head&lt;/code&gt; element for Firefox and IE browsers which do not support preloading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling critical JavaScript
&lt;/h2&gt;

&lt;p&gt;We handle critical JavaScript the similar way we handle critical CSS, by inlining it within HTML code. It's important to note that we need to insert critical JavaScript code using &lt;code&gt;script&lt;/code&gt; tag before the &lt;code&gt;body&lt;/code&gt; closing tag. That way we make sure that JavaScript doesn't block content render and all available DOM nodes are created and available to JavaScript code.&lt;/p&gt;


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

&lt;p&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;br&gt;
  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;br&gt;
    &lt;span class="cm"&gt;/* Inlined JavaScript code */&lt;/span&gt;&lt;br&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Handling non-critical JavaScript&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;We can handle non-critical JavaScript just by adding &lt;code&gt;defer&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; tags to &lt;code&gt;script&lt;/code&gt; tag (inline JavaScript or JavaScript loaded from &lt;code&gt;src&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We use &lt;code&gt;defer&lt;/code&gt; for scripts that need the whole DOM and/or their relative execution order is important. It tells the browser to load the page first and then load the script in the background.&lt;/li&gt;
&lt;li&gt;We use &lt;code&gt;async&lt;/code&gt; for independent scripts that can be executed in any order. This script doesn't wait for any other scripts and can loaded in parallel with other scripts with &lt;code&gt;async&lt;/code&gt; scripts.&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/path/to/script.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/path/to/script.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Boosted performance &amp;amp; Lighthouse score&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;On my personal website I've handled critical and non-critical CSS and JavaScript as I've described in the article. After implementing this modern approach, I've eliminated render-blocking, non-critical CSS and JavaScript which in turn boosted my Lighthouse score and overall performance!&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%2Fllf9skh1rppbykj31bxt.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%2Fllf9skh1rppbykj31bxt.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/ubnZ8GgDJ" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-red.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.&lt;/p&gt;

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