<?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>Forem: Jesse Wei</title>
    <description>The latest articles on Forem by Jesse Wei (@jessewei).</description>
    <link>https://forem.com/jessewei</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%2F572788%2Fbaca5b47-06d9-49b8-9e3c-bd90ed999dac.png</url>
      <title>Forem: Jesse Wei</title>
      <link>https://forem.com/jessewei</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jessewei"/>
    <language>en</language>
    <item>
      <title>A Hands-On Guide to Figma's Component Properties</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Fri, 05 May 2023 10:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/a-hands-on-guide-to-figmas-component-properties-2fik</link>
      <guid>https://forem.com/jessewei/a-hands-on-guide-to-figmas-component-properties-2fik</guid>
      <description>&lt;p&gt;The &lt;a href="https://help.figma.com/hc/en-us/articles/5579474826519-Explore-component-properties#h_01G2Q5FYN2ADEDQ3ZSB1KKY8Z0" rel="noopener noreferrer"&gt;component properties feature&lt;/a&gt; of Figma is powerful but can feel somewhat unintuitive at first.&lt;/p&gt;

&lt;p&gt;While there are quite some resources online and offline about this topic, few give real-world examples to help us truly understand it. So I created this hands-on tutorial to show you how this feature can boost your design workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;What Are Component Properties&lt;/li&gt;
&lt;li&gt;
Types of Component Properties

&lt;ul&gt;
&lt;li&gt;Boolean Property&lt;/li&gt;
&lt;li&gt;Example&lt;/li&gt;
&lt;li&gt;Instance Swap Property&lt;/li&gt;
&lt;li&gt;Example&lt;/li&gt;
&lt;li&gt;Text Property&lt;/li&gt;
&lt;li&gt;Example&lt;/li&gt;
&lt;li&gt;Variant Property&lt;/li&gt;
&lt;li&gt;Example&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;A Challenge&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you should have some basic knowledge on Figma in general. You should understand what a component is and how to create one in Figma.&lt;/p&gt;

&lt;p&gt;If you're new to Figma, don't worry, check out &lt;a href="https://help.figma.com/hc/en-us/sections/4405269443991-Figma-for-Beginners-tutorial-4-parts-" rel="noopener noreferrer"&gt;this beginner guide&lt;/a&gt; before getting back to this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Component Properties
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Component properties are styles and/or content of a component that can be changed to create variations of the component&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They can be the content of some text, having or not having a nested component, the specific type of the nested component and so on.&lt;/p&gt;

&lt;p&gt;By applying those properties, we can create sophisticated component libraries out of limited number of components, which is a great time-saver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Component Properties
&lt;/h2&gt;

&lt;p&gt;There are four types of component properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Boolean Property&lt;/li&gt;
&lt;li&gt;Instance Swap Property&lt;/li&gt;
&lt;li&gt;Text Property&lt;/li&gt;
&lt;li&gt;Variant Property&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll examine each of them closely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boolean Property
&lt;/h3&gt;

&lt;p&gt;This property controls whether something is visible or not. To be precise, it shows or hides a &lt;strong&gt;layer&lt;/strong&gt; of a component. So anything of the component that appears in the &lt;em&gt;Layers panel&lt;/em&gt; can have this property applied.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Suppose we have componentized a button with a text label and an icon. We want to be able to create variations of the button with or without the icon.&lt;/p&gt;

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



&lt;p&gt;&lt;em&gt;Breakdown&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1). Double-click the icon to select it. In the &lt;strong&gt;Layer&lt;/strong&gt; section of the right sidebar, click the &lt;strong&gt;Create boolean property&lt;/strong&gt; button.&lt;/p&gt;

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

&lt;p&gt;2). Give it a self-explanatory name, such as &lt;em&gt;Show Icon&lt;/em&gt;, leave the &lt;strong&gt;Value&lt;/strong&gt; as it is and hit &lt;strong&gt;Create property&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%2Fuploads%2Farticles%2F2zyv9iz45iyi7iarpdzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2zyv9iz45iyi7iarpdzq.png" alt="Boolean property: step 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3). Now the property is added to the icon layer and appears in the &lt;strong&gt;Layer&lt;/strong&gt; section of the right sidebar.&lt;/p&gt;

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

&lt;p&gt;4). Create an instance from the button component. A switch for the property appears under the component name in the right sidebar. We can use it to toggle the showing and hiding of the icon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6utvyalbs1ed8y2indyf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6utvyalbs1ed8y2indyf.png" alt="Boolean property: step 4-1"&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2brn0b0ftnvzv96x3re.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2brn0b0ftnvzv96x3re.png" alt="Boolean property: step 4-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Instance Swap Property
&lt;/h3&gt;

&lt;p&gt;If Boolean property controls &lt;em&gt;show or hide&lt;/em&gt;, then Instance Swap property controls &lt;strong&gt;what to show&lt;/strong&gt;. In the button component example above, we may want to change the icon in practice to fit our needs and this is where the Instance Swap property comes in handy.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Let's build upon our button component example. But before we start, as a pre-step, add a couple of icons to our canvas and componentize them (you can go to &lt;em&gt;Plugins&lt;/em&gt;, search for &lt;em&gt;icons&lt;/em&gt;, pick a library and arbitarily add a few icons to the canvas).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxiuj8gweax6yz43fzekj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxiuj8gweax6yz43fzekj.gif" alt="Example of adding instance swap property"&gt;&lt;/a&gt;&lt;/p&gt;
Example of adding instance swap property



&lt;p&gt;&lt;em&gt;Breakdown&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1). Double-click the icon to select it. In the right sidebar and next to the name of the selected icon name, click the &lt;strong&gt;Create instance swap property&lt;/strong&gt; button.&lt;/p&gt;

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

&lt;p&gt;2). In the modal that appears, feel free to give the new property a proper name, choose the default icon (I'll leave both as they are here) and hit &lt;strong&gt;Create property&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%2Fuploads%2Farticles%2Fve53ahd2bzzh6zox94ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fve53ahd2bzzh6zox94ls.png" alt="Instance Swap property: step 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3). Now we see from the right sidebar that our new property is successfully created.&lt;/p&gt;

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

&lt;p&gt;4). Create an instance from our button component and from the right sidebar and under the instance name, we can see our new instance property is availabe. Click the dropdown button.&lt;/p&gt;

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

&lt;p&gt;5). Finally, from the dropdown menu, choose another icon and we're done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97stgiob75twkxafiwp5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97stgiob75twkxafiwp5.png" alt="Instance Swap property: step 5-1"&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhff2px553vw86yxh9d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhff2px553vw86yxh9d1.png" alt="Instance Swap property: step 5-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please note that, Instance Swap property only applies to components. If we want to choose an icon from a list of icons, for example, we must first componentize them for them to appear in the instance list.&lt;/p&gt;

&lt;h3&gt;
  
  
  Text Property
&lt;/h3&gt;

&lt;p&gt;Text property is pretty straightforward. As the name suggests, it controls the content of text. Whenever we want the text of a component to be customizable, we can add a text property to it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;We'll keep building upon our button component example.&lt;/p&gt;

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

  

&lt;p&gt;&lt;em&gt;Breakdown&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1). Double-click the text to select it. In the &lt;em&gt;Content&lt;/em&gt; section of the right sidebar, click the &lt;strong&gt;Create text property&lt;/strong&gt; button.&lt;/p&gt;

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

&lt;p&gt;2). In the modal that appears, feel free to give the new property a proper name, set the default text (I'll leave both as they are here) and hit &lt;strong&gt;Create property&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%2Fuploads%2Farticles%2Fnttmuhf1ec5yfjbkp8xd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnttmuhf1ec5yfjbkp8xd.png" alt="Text property: step 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3). Now we see from the right sidebar that our new property is successfully created.&lt;/p&gt;

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

&lt;p&gt;4). Create an instance from our button component and from the right sidebar and under the instance name, we can see our new instance property is availabe. We can change the text from the text box here (or you can choose to edit the text directly on the button instance).&lt;/p&gt;

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

&lt;p&gt;5). Finally, change the text to something like &lt;em&gt;Submit&lt;/em&gt; and we're done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux7qfsg8cbp2z3ul1oq5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux7qfsg8cbp2z3ul1oq5.png" alt="Text property: step 5-1"&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmcbo4e3856tdabpne9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmcbo4e3856tdabpne9v.png" alt="Text property: step 5-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Variant Property
&lt;/h3&gt;

&lt;p&gt;Simply put, a variant property is one that is out of the reach of all the component properties we saw above. We cannot use any of the Boolean, Instance Swap or Text properties to control the size or background color, for example, of our button. If we want to have buttons of different sizes and different background colors, we need to create &lt;em&gt;variants&lt;/em&gt; of that button.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;We'll add a type and a size property to our button component and create a variant for each of the new properties. Follow these steps:  &lt;/p&gt;

&lt;p&gt;1). Select our button component and click &lt;strong&gt;&lt;em&gt;Add Variant&lt;/em&gt;&lt;/strong&gt; from the top menu. First, we want to make the new variant an outline type of button. So we give it an &lt;strong&gt;&lt;em&gt;Outline&lt;/em&gt;&lt;/strong&gt; value and rename the default &lt;em&gt;Property 1&lt;/em&gt; to &lt;strong&gt;&lt;em&gt;Type&lt;/em&gt;&lt;/strong&gt; from the right sidebar. Change its style to make it an outline button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk32mz9ru4baxpniwrol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk32mz9ru4baxpniwrol.png" alt="Variant property: step 1"&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9tgql3z86yjk4nsp7yzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9tgql3z86yjk4nsp7yzq.png" alt="Variant property: step 1-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2). Next, we want to create a smaller-sized variant for each of the existing variant. Select our component set by clicking the &lt;em&gt;Button&lt;/em&gt; tag and drag the border to make it wider. Then, with the component set still selected, click the &lt;strong&gt;&lt;em&gt;Create component property&lt;/em&gt;&lt;/strong&gt; button from the &lt;em&gt;Properties&lt;/em&gt; section in the right sidebar and select &lt;strong&gt;&lt;em&gt;Variant&lt;/em&gt;&lt;/strong&gt; from the menu. Name it &lt;strong&gt;&lt;em&gt;Size&lt;/em&gt;&lt;/strong&gt; and hit &lt;strong&gt;&lt;em&gt;Create property&lt;/em&gt;&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%2Fuploads%2Farticles%2Ftegda1gxb6t8q231c22c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftegda1gxb6t8q231c22c.png" alt="Variant property: step 2-1"&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nkk1d5t95hl7huwfr0r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nkk1d5t95hl7huwfr0r.png" alt="Variant property: step 2-2"&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fo8ibj1gd63hj14z7ca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fo8ibj1gd63hj14z7ca.png" alt="Variant property: step 2-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3). Select both of the existing variants, press and hold Option/Alt and drag to duplicate them. In the focused text box in the right sidebar, change the text to Small. Then, with the new variants still selected, resize them in the Auto  layout section by giving them smaller paddings and we're done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw81aae4glu29q1dhz6pv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw81aae4glu29q1dhz6pv.png" alt="Variant property: step 3-1"&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3c3ndd4c5v4erp40ec3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3c3ndd4c5v4erp40ec3b.png" alt="Variant property: step 3-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4). Now, create a button instance and try out all the properties we've created. &lt;/p&gt;

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

&lt;h2&gt;
  
  
  A Challenge
&lt;/h2&gt;

&lt;p&gt;Now we'll get some practice by building a profile card component using our button component. It has an avatar, a title, some description text and a button. It allows us to change the avatar image, the title and the text dynamically and we can access all of the properties we added to the button from within the card component.&lt;/p&gt;

&lt;p&gt;Here is what it looks like when finished:&lt;/p&gt;

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

&lt;p&gt;And here are some instances created from it:&lt;/p&gt;

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

&lt;p&gt;Make sure to try building it out yourself but if you're stuck, try these steps:&lt;/p&gt;

&lt;p&gt;1). Use the &lt;a href="https://www.uifaces.co/plugin-figma/" rel="noopener noreferrer"&gt;UI Faces&lt;/a&gt; Figma plugin to generate a few avatar images and componentize them. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7akliah9uh26l1as3seh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7akliah9uh26l1as3seh.png" alt="Create profile card component: step 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2). Create a rectangle, set its background color to white and give it a shadow if you want. Don't worry about the size or aspect ratio of it.&lt;/p&gt;

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

&lt;p&gt;3). Drag an avatar and a button instance from the Assets of the left sidebar onto the new rectangle, and add title and description text to it too. Don't worry about the positions of the elements as we'll align them later.&lt;/p&gt;

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

&lt;p&gt;4). Now select the rectangle along with everything inside it and componentize it.&lt;/p&gt;

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

&lt;p&gt;5). To be able to access all of the properties of our button, we need to &lt;strong&gt;&lt;em&gt;expose properties from nested instances&lt;/em&gt;&lt;/strong&gt;. If you are not familiar with it, check out &lt;a href="https://help.figma.com/hc/en-us/articles/5579474826519-Explore-component-properties#exposed-instances" rel="noopener noreferrer"&gt;Figma docs&lt;/a&gt; on this. In this case, with the card component selected, click the &lt;strong&gt;&lt;em&gt;Create component property&lt;/em&gt;&lt;/strong&gt; button from the &lt;em&gt;Properties&lt;/em&gt; section in the right sidebar and select &lt;strong&gt;&lt;em&gt;Nested instances&lt;/em&gt;&lt;/strong&gt; from the menu. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jwbdf0p0m2dnx975oyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jwbdf0p0m2dnx975oyr.png" alt="Profile card component: step 5-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, check in &lt;strong&gt;&lt;em&gt;Button&lt;/em&gt;&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%2Fuploads%2Farticles%2Flp542e7xk8w69dx3cnwd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp542e7xk8w69dx3cnwd.png" alt="Profile card component: step 5-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6). Now we can tweak the property values of our button.&lt;/p&gt;

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

&lt;p&gt;Follow the steps introduced in this tutorial to create an Instance Swap property on the avatar, a Text property on the title and another Text property on the description text.&lt;/p&gt;

&lt;p&gt;7). Finally, align the elements with &lt;em&gt;Auto Layout&lt;/em&gt; which is out of the scope of this post. If you are not familiar with it, take a look at &lt;a href="https://help.figma.com/hc/en-us/articles/5731482952599-Using-auto-layout" rel="noopener noreferrer"&gt;Figma docs&lt;/a&gt; on this (I'm considering creating a tutorial on Auto Layout so stay tuned). The completed design should look something like this:&lt;/p&gt;

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

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

&lt;p&gt;In this tutorial, we learned what component properties are in Figma and how to use them to create dynamic and flexible UI. There are 4 types of component properties: Boolean, Instance Swap, Text and Variant properties.&lt;/p&gt;

&lt;p&gt;Each of the first 3 properties provides a specific control over a part of a componet while Variant property allows us to tweak the size, the color, the state or other aspects of a component that are beyond the reach of the first 3 properties. &lt;/p&gt;

&lt;p&gt;Figma is easy to get started but hard to truly master. I'm considering creating more tutorials covering other important topics on it, so please stay tuned!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>figma</category>
      <category>design</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Implement Click-And-Copy With Clipboard API</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Mon, 06 Mar 2023 10:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/navigatorclipboard-ije</link>
      <guid>https://forem.com/jessewei/navigatorclipboard-ije</guid>
      <description>&lt;p&gt;Click-and-copy is everywhere these days. By simplifying a multi-step action to a single-step one, this functionality makes web users happy so as a UI/UX designer, you don't want to miss out on it.&lt;/p&gt;

&lt;p&gt;At the core of the implementation is the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Clipboard" rel="noopener noreferrer"&gt;Clipboard API&lt;/a&gt;. It may sound daunting at first, but the logic is actually quite straightforward. I'll help you get familiar with it by building a real world example together in this tutorial.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What We Will Build&lt;/li&gt;
&lt;li&gt;HTML &amp;amp; CSS&lt;/li&gt;
&lt;li&gt;
Clipboard API

&lt;ul&gt;
&lt;li&gt;An Overview&lt;/li&gt;
&lt;li&gt;Elements and Event Listeners&lt;/li&gt;
&lt;li&gt;Click-and-Copy Handler&lt;/li&gt;
&lt;li&gt;Form Submission Handler&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  What We Will Build
&lt;/h2&gt;

&lt;p&gt;Our example will look and work like this when finished:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84qje46b4aouqk3689z9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84qje46b4aouqk3689z9.gif" alt="Click-and-copy example" width="660" height="348"&gt;&lt;/a&gt;&lt;/p&gt;
Click-and-copy example



&lt;p&gt;When you click a coupon code, it will be selected and highlighted, and a tooltip with the copied coupon code will appear. You can then paste the content to the coupon code input to apply it, which mimics how we work with coupon code in the real world.&lt;/p&gt;

&lt;p&gt;For brevity, I will only show the code that's relevant to the step in the description below. You can find the full code of the example &lt;a href="https://github.com/jw1219/clipboard-api-example" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  HTML &amp;amp; CSS
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a &lt;code&gt;index.html&lt;/code&gt; and &lt;code&gt;style.css&lt;/code&gt; file at our project root.&lt;/p&gt;

&lt;p&gt;Give &lt;code&gt;index.html&lt;/code&gt; the following content (full code can be found &lt;a href="https://github.com/jw1219/clipboard-api-example/blob/main/index.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&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;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"coupons"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"coupon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;small&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"coupon-label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Coupon Code: &lt;span class="nt"&gt;&amp;lt;/small&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"coupon-code-1"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"coupon-code-1"&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"ABC12345"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;small&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"tooltip"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"copied-code"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt; Copied&lt;span class="nt"&gt;&amp;lt;/small&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"coupon"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;small&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"coupon-label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Coupon Code: &lt;span class="nt"&gt;&amp;lt;/small&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"coupon-code-2"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"coupon-code-2"&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"XYZ098765"&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;small&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"tooltip"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"copied-code"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt; Copied&lt;span class="nt"&gt;&amp;lt;/small&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"off"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"code-input"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Your Coupon Code: &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"code-input"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"code-input"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Apply&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then give &lt;code&gt;style.css&lt;/code&gt; the following content (full code can be found &lt;a href="https://github.com/jw1219/clipboard-api-example/blob/main/style.css" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&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;50vh&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="no"&gt;beige&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;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.container&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;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stretch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.coupons&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.coupons&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;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="nl"&gt;column-gap&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.coupon&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="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;space-between&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&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;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.coupon&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.coupon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&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="nc"&gt;.coupon-label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="o"&gt;^=&lt;/span&gt;&lt;span class="s2"&gt;'coupon-code-'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;large&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.tooltip&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="no"&gt;darkslategray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&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;5px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&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;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;-6px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.tooltip&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;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;100%&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;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;darkslategray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;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;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="n"&gt;minmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="nl"&gt;column-gap&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="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'code-input'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'code-input'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;grid-column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'submit'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;grid-column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;span&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;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;20px&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;
  
  
  Clipboard API
&lt;/h2&gt;

&lt;h3&gt;
  
  
  An Overview
&lt;/h3&gt;

&lt;p&gt;Before implementing the API, let's take a quick look at what we can do with it.&lt;/p&gt;

&lt;p&gt;This API allows us to access the system clipboard through the following methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;read()&lt;/code&gt;. Get the data (not limited to text) from the clipboard.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;readText()&lt;/code&gt;. Get the text data from the clipboard.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;write()&lt;/code&gt;. Write data (not limited to text) to the clipboard.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;writeText()&lt;/code&gt;. Write text data to the clipboard.
Now let's implement the Clipboard API in Javascript to give our example the expected behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the methods return a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" rel="noopener noreferrer"&gt;Promise&lt;/a&gt;. For the &lt;code&gt;read*&lt;/code&gt; methods, the promise is resolved with the data of the clipboard and for the &lt;code&gt;write*&lt;/code&gt; methods, the promise is resolved when the data is copied to the clipboard.&lt;/p&gt;

&lt;p&gt;Note that,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We access the &lt;code&gt;Clipboard&lt;/code&gt; object through the &lt;code&gt;navigator.clipboard&lt;/code&gt; global.&lt;/li&gt;
&lt;li&gt;The support of the API varies across browsers. Check out &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Clipboard#browser_compatibility" rel="noopener noreferrer"&gt;browser compatibility&lt;/a&gt; to see if your browser supports it.&lt;/li&gt;
&lt;li&gt;Permission is required for the API to access the system clipboard, so an alert may appear that asks for your permission when calling the API for the first time (if that's the case, click &lt;em&gt;allow&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Elements and Event Listeners
&lt;/h3&gt;

&lt;p&gt;Now let's get started coding! First, create a &lt;code&gt;script.js&lt;/code&gt; file at the project root. Then, let's select and store the elements we'll use in variables and prepare our event listeners:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;codeEls&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;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[name^="coupon-code-"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tooltips&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;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.tooltip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;codeInput&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[name=code-input]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * todo: define handleCopy and handleSubmit methods
 */&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;codeEl&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;codeEls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;codeEl&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="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;handleCopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codeEl&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;form&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="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Click-and-Copy Handler
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;handleCopy()&lt;/code&gt; method contains the core business logic for the click-and-copy action. In our example, we only deal with text data, so we use &lt;code&gt;readText()&lt;/code&gt; and &lt;code&gt;writeText()&lt;/code&gt; here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCopy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;el&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;return &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="cm"&gt;/**
     * 1. copy coupon code to clipboard
     */&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;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/**
         * 2. select and highlight clicked coupon code
         */&lt;/span&gt;
        &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSelectionRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="cm"&gt;/**
         * 3. hide all currently displayed tooltips
         *    if there is any
         */&lt;/span&gt;
        &lt;span class="nx"&gt;tooltips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tooltip&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tooltip&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;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="cm"&gt;/**
         * 4. select the tooltip for the clicked coupon
         */&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tooltip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextElementSibling&lt;/span&gt;
        &lt;span class="cm"&gt;/**
         * 5. insert the copied code to the tooltip
         *    before displaying the tooltip
         */&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copiedCodeEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.copied-code&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readText&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;code&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;copiedCodeEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;tooltip&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;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="cm"&gt;/**
         * 6. clear any existing timeout
         *    before assigning a new one to the variable
         */&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&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;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="cm"&gt;/**
         * 7. display the tooltip for 2 seconds
         */&lt;/span&gt;
        &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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="nx"&gt;tooltip&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;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
          &lt;span class="nx"&gt;copiedCodeEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2000&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;
  
  
  Form Submission Handler
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;handleSubmit&lt;/code&gt;, we'll just get the input value of the text field and display it in an alert:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&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;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;code-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * clearing the text field after form submission
   * makes great UX
   */&lt;/span&gt;
  &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;code-input&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="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;codeInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Coupon Code &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has been applied successfully.`&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's it. Make sure to get your hands dirty and write the code line by line to really understand the concept.&lt;/p&gt;

&lt;p&gt;The full Javascript code can be found &lt;a href="https://github.com/jw1219/clipboard-api-example/blob/main/script.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And the final and live example can be found &lt;a href="https://jw1219.github.io/clipboard-api-example/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




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

&lt;p&gt;In this tutoria, we learned how to implement a &lt;em&gt;click-and-copy&lt;/em&gt; component by building an example that can be used out of the box in your next project.&lt;/p&gt;

&lt;p&gt;We looked at the &lt;code&gt;Clipboard API&lt;/code&gt; which is the core to our implementation. The Javascript code looks somewhat lengthy but the idea is not that complex, especially when we break the steps down.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ai</category>
      <category>freelancing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Supercharge Your HTML&amp;CSS Workflow With Pug and TailwindCSS</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Fri, 03 Mar 2023 21:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/supercharge-your-htmlcss-workflow-with-pug-and-tailwindcss-4kg6</link>
      <guid>https://forem.com/jessewei/supercharge-your-htmlcss-workflow-with-pug-and-tailwindcss-4kg6</guid>
      <description>&lt;p&gt;Coding in HTML and CSS can be time-consuming. For large HTML and CSS files, they can be hard to maintain as well.&lt;/p&gt;

&lt;p&gt;A much better approach is to use &lt;strong&gt;HTML templating languages&lt;/strong&gt;, such as &lt;a href="https://pugjs.org/api/getting-started.html" rel="noopener noreferrer"&gt;Pug&lt;/a&gt; and &lt;strong&gt;CSS frameworks&lt;/strong&gt;, such as &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;, to &lt;em&gt;generate your HTML and CSS code&lt;/em&gt; on the fly.&lt;/p&gt;

&lt;p&gt;In this tutorial, I'll show you how to bootstrap such a project in no time using the &lt;a href="https://www.npmjs.com/package/create-pug-tailwindcss-app" rel="noopener noreferrer"&gt;create-pug-tailwindcss-app&lt;/a&gt; package I built and how to really leverage the power of Pug and Tailwind CSS to make your life easier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;How Pug Works&lt;/li&gt;
&lt;li&gt;How Tailwind CSS Works&lt;/li&gt;
&lt;li&gt;
Build an Example in &amp;lt;10 Minutes

&lt;ul&gt;
&lt;li&gt;Get Started&lt;/li&gt;
&lt;li&gt;Pug to HTML&lt;/li&gt;
&lt;li&gt;Add Tailwind CSS Classes&lt;/li&gt;
&lt;li&gt;Go to Production&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You're expected to have basic knowledge about HTML templating languages. If not, I have a &lt;a href="https://dev.to/jessewei/pug-a-html-templating-language-3oe2"&gt;post&lt;/a&gt; covering the basics of Pug so feel free to check it out. You can also take a look at the &lt;a href="https://pugjs.org/api/getting-started.html" rel="noopener noreferrer"&gt;official docs of Pug&lt;/a&gt;. I'll cover some more advanced usage of Pug in this tutorial too.&lt;/li&gt;
&lt;li&gt;You're expected to have basic knowledge about Tailwind CSS. If not,  check out its &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;official docs&lt;/a&gt;, especially the &lt;a href="https://tailwindcss.com/docs/installation" rel="noopener noreferrer"&gt;Get Started&lt;/a&gt; and &lt;a href="https://tailwindcss.com/docs/utility-first" rel="noopener noreferrer"&gt;Core Concepts&lt;/a&gt; sections. They also have an &lt;a href="https://play.tailwindcss.com/" rel="noopener noreferrer"&gt;interactive playground&lt;/a&gt; where you can try Tailwind CSS out easily.&lt;/li&gt;
&lt;li&gt;I use &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VSCode&lt;/a&gt; as my editor  with the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer" rel="noopener noreferrer"&gt;Live Server&lt;/a&gt; extension installed. Any other editors that the extension supports should work as well. But if there's no compatible Live Server extension for your editor, you'd need to do a bit research to find a dev server with hot reload support.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Pug is a templating language that when compiled, outputs HTML code. So instead of writing HTML directly, you write Pug code and then compile it to generate HTML.&lt;/p&gt;

&lt;p&gt;For example, this Pug snippet,&lt;/p&gt;

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

doctype html
html
  head
    title My Site
  body
    h1 Hello, World!
    p This is my site.


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

&lt;/div&gt;

&lt;p&gt;generates the following HTML:&lt;/p&gt;

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

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Site&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello, World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is my site.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;If you want to know more about Pug, check out &lt;a href="https://dev.to/jessewei/pug-a-html-templating-language-3oe2"&gt;my post&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Tailwind CSS Works
&lt;/h2&gt;

&lt;p&gt;Tailwind CSS is a utility-first CSS framework. It provides a set of pre-defined CSS classes that can be used directly in HTML markup without having to write any CSS code from scratch (mostly).&lt;/p&gt;

&lt;p&gt;Let's say I want to give the &lt;code&gt;p&lt;/code&gt; element in the following markup a font size of &lt;code&gt;20px&lt;/code&gt; and a color of dark red, I can do,&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;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-xl text-red-900"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello World&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;When compiled, Tailwind CSS adds the &lt;code&gt;text-xl&lt;/code&gt; and &lt;code&gt;text-red-900&lt;/code&gt; classes to the output stylesheet (the CSS file we link in the head of our HTML) where the CSS of the classes are specified:&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;.text-xl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.25rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* 20px */&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* 28px */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.text-red-900&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;124&lt;/span&gt; &lt;span class="m"&gt;45&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You can see it's no magic here. We're still using CSS to style our page, just that instead of defining the classes and writing the CSS ourselves, Tailwind CSS does the heavy lifting for us.&lt;/p&gt;




&lt;h2&gt;
  
  
  Build and Deploy an Example in &amp;lt;10 Minutes
&lt;/h2&gt;

&lt;p&gt;Now we've seen how Pug and Tailwind CSS work separately, it's time to put the pieces together. We'll build a sample page and this is how it looks like when finished:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ign0yv59d68jb2ll6d5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ign0yv59d68jb2ll6d5.png" alt="Sample page to build"&gt;&lt;/a&gt;&lt;/p&gt;
Sample page to build(Photo by &lt;a href="https://unsplash.com/@marekpiwnicki?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Marek Piwnicki&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/G_6kPyje9Lk?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;)



&lt;p&gt;It's simple but looks good enough. More importantly, you can build it in less than 10 minutes without writing a single line of HTML or CSS!&lt;/p&gt;

&lt;h3&gt;
  
  
  Get Started
&lt;/h3&gt;

&lt;p&gt;Bootstrapping a project that uses Pug and Tailwind CSS for the first time can be a bit tricky, so I created an &lt;a href="https://www.npmjs.com/package/create-pug-tailwindcss-app" rel="noopener noreferrer"&gt;npx tool&lt;/a&gt; to make your life easier.&lt;/p&gt;

&lt;p&gt;To get started, just run the following command in your terminal (remember to replace your-project-name with your real project name):&lt;/p&gt;

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

npx create-pug-tailwindcss-app your-project-name


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

&lt;/div&gt;

&lt;p&gt;Now, your project structure should look like this:&lt;/p&gt;

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

&lt;span class="nb"&gt;.&lt;/span&gt;
├── README.md
├── bin
│   └── cli.js
├── images
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── index.pug
│   └── input.css
└── tailwind.config.js


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

&lt;/div&gt;

&lt;p&gt;You would work with,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/&lt;/code&gt;. This is where your Pug files and input CSS file (the CSS file to be compiled) reside.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;images/&lt;/code&gt;. This is where you put your images.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tailwind.config.js&lt;/code&gt;. This is where you configure your Tailwind CSS or add global styles, if necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can ignore all the other directories and files in the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pug to HTML
&lt;/h3&gt;

&lt;p&gt;Open the &lt;code&gt;src/index.pug&lt;/code&gt; file and replace its content with the following:&lt;/p&gt;

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

//- 1. We can define variables in Pug just like we do in Javascript
- var navItems = ['Top', 'Services', 'About Us', 'Contact'] 

doctype html
html(lang='ja')
  head
    meta(name="viewport", content="width=device-width, initial-scale=1")
    title Foo Company
    link(rel="stylesheet" href="style.css")
  body
    header
      div
        a(href="#") Foo Company
        nav 
          ul
            //- 2. Iteration makes code more concise and readable
            each item in navItems
              li
                a(href="#")= item
    main
      section
        img(src="kv.jpg", alt="key visual of Foo Company")
        h1 Foo Company
      section
        h2 Our Services
        div
          div
            h3 Service 1
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
          div
            h3 Service 2
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
          div
            h3 Service 3
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
    footer
      div
        a(href="#") Foo Company 
        nav 
          ul
            each item in navItems
              li
                a(href="#")= item
      small Copyright © 2023 Foo Company


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

&lt;/div&gt;

&lt;p&gt;Some interesting points to be noted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At 1, we defined the items of our nav in an array &lt;em&gt;just like we'd normally do in Javascript&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;At 2, we used &lt;code&gt;each&lt;/code&gt; expression to iterate our &lt;code&gt;navItems&lt;/code&gt; variable which made the code much more concise and readable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now download the key visual image &lt;a href="https://unsplash.com/photos/G_6kPyje9Lk" rel="noopener noreferrer"&gt;here&lt;/a&gt;, rename it as &lt;code&gt;kv.jpg&lt;/code&gt; and put into the &lt;code&gt;images/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Then run this command in your terminal to compile our Pug file into HTML:&lt;/p&gt;

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

npm start


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

&lt;/div&gt;

&lt;p&gt;You should notice a &lt;code&gt;dist/&lt;/code&gt; directory is generated automatically in our project root. Within it, there is the compiled &lt;code&gt;index.html&lt;/code&gt; and &lt;code&gt;style.css&lt;/code&gt; files along with our key visual image.&lt;/p&gt;

&lt;p&gt;Start your editor's Live Server extension and in the opened browser, click the dist directory. Our page should be displayed and should look like this by this point:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhn4fm79dbvusol5md0nx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhn4fm79dbvusol5md0nx.png" alt="Sample page before CSS is applied"&gt;&lt;/a&gt;&lt;/p&gt;
Sample page before CSS is applied



&lt;h3&gt;
  
  
  Add Tailwind CSS Classes
&lt;/h3&gt;

&lt;p&gt;Now it's time to add Tailwind CSS classes to our markup to give our page a cool style. Due to the limit of the length of this tutorial, I cannot go through all the classes used to style our page. But as an example, let's give our &lt;code&gt;header&lt;/code&gt; a light grey background color:&lt;/p&gt;

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

...
header.bg-slate-100
...


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

&lt;/div&gt;

&lt;p&gt;Save your changes and the background color of the &lt;code&gt;header&lt;/code&gt; should be changed in real-time in the browser. You can find more about the default colors you can use out of the box &lt;a href="https://tailwindcss.com/docs/background-color#setting-the-background-color" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you saw above, styling our page is as easy as attaching Tailwind CSS classes to Pug tags. Our final &lt;code&gt;src/index.pug&lt;/code&gt; looks like this:&lt;/p&gt;

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

- var navItems = ['Top', 'Services', 'About Us', 'Contact'] 

doctype html
html(lang='ja')
  head
    meta(name="viewport", content="width=device-width, initial-scale=1")
    title Foo Company
    link(rel="stylesheet" href="style.css")
  body
    header.w-full.bg-slate-100.fixed.top-0.left-0.z-10
      .container.flex.justify-between.items-center
        a.font-bold(href="#") Foo Company
        nav 
          ul.flex.justify-end
            each item in navItems
              li
                a.block.p-4(href="#")= item
    main
      section.relative.mb-12
        img.w-full.h-screen.object-cover.brightness-50(src="kv.jpg", alt="key visual of Foo Company")
        h1(class="text-6xl font-bold text-white absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2") Foo Company
      section.container.mb-12
        h2.text-4xl.font-bold.mb-6 Our Services
        .grid.grid-cols-3.gap-12
          div
            h3.text-2xl.font-bold.mb-3 Service 1
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
          div
            h3.text-2xl.font-bold.mb-3 Service 2
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
          div
            h3.text-2xl.font-bold.mb-3 Service 3
            p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi accumsan, sem et porttitor placerat, lacus risus molestie ligula, congue venenatis augue ante ac dui. Aliquam ipsum neque, tempus id magna eget, fringilla sollicitudin nunc. Phasellus non eros maximus, posuere elit in, vestibulum orci. Phasellus eget pellentesque ligula.
    footer.w-full.bg-slate-900.text-white
      .container.flex.justify-between.items-center.mb-6
        a.font-bold(href="#") Foo Company 
        nav 
          ul.flex.justify-end
            each item in navItems
              li
                a.block.p-4(href="#")= item
      small.block.text-center Copyright © 2023 Foo Company


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

&lt;/div&gt;

&lt;p&gt;For the other classes I used in the page, check out &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS docs&lt;/a&gt;. Just hit &lt;code&gt;CMD + /&lt;/code&gt; (Mac OS) or &lt;code&gt;Ctrl + /&lt;/code&gt; (Windows) and type in the property you want style (e.g. text color). &lt;/p&gt;

&lt;h3&gt;
  
  
  Go to Production
&lt;/h3&gt;

&lt;p&gt;To bring our page to production, just run:&lt;/p&gt;

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

npm run build:prod


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;dist/&lt;/code&gt; directory is re-generated. The only difference of this version of &lt;code&gt;dist/&lt;/code&gt; and the dev version is the &lt;code&gt;index.html&lt;/code&gt; in the production &lt;code&gt;dist/&lt;/code&gt; is minified.&lt;/p&gt;

&lt;p&gt;Now you can pick your favorite hosting service and upload the generated HTML, CSS and image files to it to publish your page.&lt;/p&gt;




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

&lt;p&gt;It can sound daunting to build a website using multiple new technologies other than HTML and CSS. But as I showed you in this tutorial, with a bit of good tooling, we can create a modern page times faster with Pug and Tailwind CSS than with traditional HTML and CSS workflow.&lt;/p&gt;

&lt;p&gt;The benefit of generating HTML and CSS dynamically doesn't stop here. When the codebase of your page is large, for example, it makes sense to &lt;em&gt;componentize&lt;/em&gt; your page. This involves creating reusable &lt;em&gt;partials&lt;/em&gt; and &lt;em&gt;mixins&lt;/em&gt; which &lt;a href="https://pugjs.org/language/mixins.html" rel="noopener noreferrer"&gt;Pug&lt;/a&gt; supports out of the box. This way, when you want to make a change to a part which is used in multiple places across the page, you only have to make the change once to the relevant partial or mixin. This makes your code much more maintainable.&lt;/p&gt;

&lt;p&gt;Also, by leveraging the functionality of Pug to pass data or data file to the compiler, you can separate the data and UI layer of your code, which makes it far easier to generate versions of the same page in different languages, for example.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>html</category>
      <category>css</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Implement a Dynamically Displayed Header With Window &amp; Element Scroll Positions</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Mon, 27 Feb 2023 12:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/implement-a-dynamically-displayed-header-with-window-element-scroll-positions-4cm1</link>
      <guid>https://forem.com/jessewei/implement-a-dynamically-displayed-header-with-window-element-scroll-positions-4cm1</guid>
      <description>&lt;p&gt;One of the most frequently seen patterns in web design is to hide the header on page load until the user scrolls and when the page hits a specific point.&lt;/p&gt;

&lt;p&gt;You may choose to use jQuery or vanilla Javascript to implement this but whichever tool you use, you need to be able to obtain the top/bottom positon of the target element relative to the scroll position of the page.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll get our hands dirty and build a simple page with a header and some content. The header is not shown at page load but when the user scrolls the page to a certain point, it appears. When he/she scrolls past a certain point, the header becomes invisible again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An Overview of Our Example&lt;/li&gt;
&lt;li&gt;HTML &amp;amp; CSS&lt;/li&gt;
&lt;li&gt;Query and Store Elements&lt;/li&gt;
&lt;li&gt;Element.getBoundingClientRect()&lt;/li&gt;
&lt;li&gt;window.scrollY&lt;/li&gt;
&lt;li&gt;Event Listener&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An Overview of Our Example
&lt;/h2&gt;

&lt;p&gt;This is what we'll build:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakckecmdael2cewvl5i2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakckecmdael2cewvl5i2.gif" alt="The example we'll build" width="982" height="892"&gt;&lt;/a&gt;&lt;/p&gt;
The example we'll build



&lt;p&gt;The header is only visible when the page is scrolled within a range. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5omdw5omg1gngd6kacc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5omdw5omg1gngd6kacc0.png" alt="The behavior of the header" width="800" height="682"&gt;&lt;/a&gt;&lt;/p&gt;
The behavior of the header



&lt;h2&gt;
  
  
  HTML &amp;amp; CSS
&lt;/h2&gt;

&lt;p&gt;Let's prepare our html code and give it some CSS first.&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Document&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&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;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&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;300px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;list-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;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="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="m"&gt;0.5s&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="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="nc"&gt;.show&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;opacity&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="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;nav&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;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#section1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Section1&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#section2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Section2&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#section3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Section3&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&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;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"section1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Section 1&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"section2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Section 2&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"section3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Section 3&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"section4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Section 4&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"section5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Section 5&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// todo: implement header behavior.&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, nothing will happen when you scroll the page because we haven't implemented our Javascript code yet. We'll do this in the next steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Query and Store Elements
&lt;/h2&gt;

&lt;p&gt;Let's start by querying and storing the relevant elements in variables as we'll need them later.&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;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;section2&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#section2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;section3&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#section3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header&lt;/span&gt;&lt;span class="dl"&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;Next comes one of the key steps in our implementation. We want to add the &lt;code&gt;show&lt;/code&gt; class name to our header when the top of section2 hits the top of the window as we scroll and remove the class name when the bottom of section3 reaches the top of the window. To achieve this, we need 3 values:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The y position of the top of section2&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The y position of the bottom of section3&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How much the document is scrolled&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To obtain value 1 and 2, I'm going to call the &lt;code&gt;getBoundingClientRect()&lt;/code&gt; method on section2 and section3 elements and to get value 3, I'll use &lt;code&gt;scrollY&lt;/code&gt; of the &lt;code&gt;window&lt;/code&gt; object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Element.getBoundingClientRect()
&lt;/h2&gt;

&lt;p&gt;This method returns an object containing the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;left&lt;/strong&gt;: pixels from the left of the viewport to the left of the element&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;top&lt;/strong&gt;: pixels from the top of the viewport to the top of the element&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;right&lt;/strong&gt;: pixels from the left of the viewport to the right of the element&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;bottom&lt;/strong&gt;: pixels from the top of the viewport to the bottom of the element&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;x&lt;/strong&gt;: equal to the value of &lt;em&gt;left&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;y&lt;/strong&gt;: equal to the value of &lt;em&gt;top&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;width&lt;/strong&gt;: width of the element including padding and border&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;height&lt;/strong&gt;: height of the element including padding and border&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see that this method is very powerful because we can get the position and size of an element in one shot. Check out &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect" rel="noopener noreferrer"&gt;MDN&lt;/a&gt; to learn more about it.&lt;/p&gt;

&lt;p&gt;We'll need the &lt;em&gt;top&lt;/em&gt; value of section2 and &lt;em&gt;bottom&lt;/em&gt; value of section3. Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;...
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="c1"&gt;// add these&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;top_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;section2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBoundingClientRect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bottom_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;section3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBoundingClientRect&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;h2&gt;
  
  
  window.scrollY
&lt;/h2&gt;

&lt;p&gt;This property of the &lt;code&gt;window&lt;/code&gt; object gives us the number of pixels the document is scrolled vertically.&lt;/p&gt;

&lt;p&gt;To achieve the expected behavior of our header, we'll check &lt;code&gt;window.scrollY&lt;/code&gt; against the &lt;code&gt;top_&lt;/code&gt; and &lt;code&gt;bottom_&lt;/code&gt; to decide whether to add or remove the &lt;code&gt;show&lt;/code&gt; class name in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event Listener
&lt;/h2&gt;

&lt;p&gt;Now it's time to wire up our scroll event listener.&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;script&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="c1"&gt;// add these&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;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollY&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;top_&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;scrollY&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;bottom_&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&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="k"&gt;else&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;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the full Javascript code looks like this.&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;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;section2&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#section2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;section3&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#section3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&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;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;top_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;section2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBoundingClientRect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bottom_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;section3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBoundingClientRect&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;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollY&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;top_&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;scrollY&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;bottom_&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&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="k"&gt;else&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;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Open the page in your browser and make sure it works as expected. If anything goes wrong, double check your code.&lt;/p&gt;

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

&lt;p&gt;In this tutorial, we built a simple page with a dynamic header that appears and disappears based on the scroll position of the document.&lt;/p&gt;

&lt;p&gt;At the core of the implementation are the &lt;code&gt;Element.getBoundingClientRect()&lt;/code&gt; method and the &lt;code&gt;window.scrollY&lt;/code&gt; property. You can also make use of them to implement things like &lt;em&gt;back-to-top&lt;/em&gt; button which only appears when user scrolls past a certain point. &lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Understanding Assignment and Reactivity in Svelte</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Mon, 30 Jan 2023 10:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/understanding-assignment-and-reactivity-in-svelte-d1j</link>
      <guid>https://forem.com/jessewei/understanding-assignment-and-reactivity-in-svelte-d1j</guid>
      <description>&lt;p&gt;&lt;em&gt;Svelte's reactivity is built into the language&lt;/em&gt; as this &lt;a href="https://svelte.dev/blog/svelte-3-rethinking-reactivity"&gt;post&lt;/a&gt; noted. Despite limited experiece with svelte yet, I feel more comfortable working with reactivity in svelte than in other frontend frameworks I've used so far.&lt;/p&gt;

&lt;p&gt;In this post, I want to share a question I had on the topic and my effort to find the answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;My Question&lt;/li&gt;
&lt;li&gt;Assignment With Side-Effect&lt;/li&gt;
&lt;li&gt;$$invalidate and Indirect Assignment&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Question
&lt;/h2&gt;

&lt;p&gt;When I first picked up &lt;a href="https://svelte.dev/"&gt;svelte&lt;/a&gt; a month ago after working with React for a few years, I made a simple todo app to play with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="s1"&gt;buy milk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="s1"&gt;buy food&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO: implement toggle&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="nl"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sr"&gt;/each&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Toggle&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I tried implementing two versions of the &lt;code&gt;toggle&lt;/code&gt; function as the following and was surprised to see the different outcomes produced by them when I hit the button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// version 1&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// version 2&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;todos&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;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todos&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://res.cloudinary.com/practicaldev/image/fetch/s--NGsHlTCp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0lr63b0v4pb0f4gzvlbt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NGsHlTCp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0lr63b0v4pb0f4gzvlbt.png" alt="Output for toggle version 1" width="356" height="328"&gt;&lt;/a&gt;&lt;/p&gt;
Output for toggle version 1





&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3qdS6CHm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/thelvoyqbgeg05v9dz3f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3qdS6CHm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/thelvoyqbgeg05v9dz3f.png" alt="Output for toggle version 2" width="353" height="302"&gt;&lt;/a&gt;&lt;/p&gt;
Output for toggle version 2





&lt;p&gt;Obviously, both &lt;code&gt;toggle&lt;/code&gt;s updated the data but only version 2 triggered an update of the UI, in which case we say, in the frontend development world, the app is &lt;em&gt;reactive&lt;/em&gt; to &lt;code&gt;toggle&lt;/code&gt; version 2 but not version 1.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;




&lt;h2&gt;
  
  
  Assignment With Side-Effect
&lt;/h2&gt;

&lt;p&gt;To answer the question, I realized I had first to understand how reactivity works in svelte.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://dev.toSvelte's%20reactivity%20is%20based%20on%20assignments"&gt;docs&lt;/a&gt;, &lt;em&gt;svelte's reactivity is based on assignments&lt;/em&gt;. But what are the implications of this? Both of my implementations of the &lt;code&gt;toggle&lt;/code&gt; function include an assignment statement and a further check indicated that both &lt;code&gt;todo&lt;/code&gt; in version 1 and &lt;code&gt;todos[i]&lt;/code&gt; in version 2 point to the same object as expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;todos&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="c1"&gt;// =&amp;gt; true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This explained why the data, &lt;code&gt;todos&lt;/code&gt;, was correctly updated in both cases as the console outputs showed and made it clear that there must have been a &lt;em&gt;side-effect&lt;/em&gt;(as svelte creator &lt;a href="https://twitter.com/Rich_Harris"&gt;Rich Harris&lt;/a&gt; mentioned in &lt;a href="https://www.youtube.com/watch?v=AdNJ3fydeao"&gt;this video&lt;/a&gt;) coming along with the version 2 of &lt;code&gt;toggle&lt;/code&gt; that triggered a re-rendering of the UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  $$invalidate and Indirect Assignment
&lt;/h2&gt;

&lt;p&gt;One thing I love about svelte most is the highly interactive &lt;a href="https://svelte.dev/repl/hello-world?version=3.55.1"&gt;REPL&lt;/a&gt;. It makes playing around with the code much easier and of much more fun.&lt;/p&gt;

&lt;p&gt;I checked out the compiled JS of both versions of the &lt;code&gt;toggle&lt;/code&gt; function and found they were not nearly the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// version 1: compiled&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// version 2: compiled&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$$invalidate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todos&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;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todos&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;The alien-looking &lt;code&gt;$$invalidate&lt;/code&gt; function in the second snippet turned out to be the source of all the magic. It is the side-effect generated by assignment that triggers an update of the screen.&lt;/p&gt;

&lt;p&gt;You don't need to know the implementation details of &lt;code&gt;$$invalidate&lt;/code&gt; to understand reactivity in svelte, but for those who are curious, feel free to take a look at this amazing &lt;a href="https://lihautan.com/compile-svelte-in-your-head-part-1/"&gt;post&lt;/a&gt; by svelte's maintainer &lt;a href="https://twitter.com/lihautan"&gt;Tan Li Hau&lt;/a&gt; before diving deep into the &lt;a href="https://github.com/sveltejs/svelte/blob/739bfaec1285e9be1301f9dbc26551c79c61c2d8/src/compiler/compile/render_dom/invalidate.ts#L8"&gt;source code&lt;/a&gt; of svelte.&lt;/p&gt;

&lt;p&gt;Now, the question becomes why did one assignment generate &lt;code&gt;$$invalidate&lt;/code&gt; and another fail to? The answer has something to do with &lt;em&gt;indirect assignment&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://svelte.dev/tutorial/updating-arrays-and-objects"&gt;official tutorial&lt;/a&gt;, it's pointed out that &lt;em&gt;indirect assignments won't trigger reactivity&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Just as this code, used in the tutorial, won't trigger reactivity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;baz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first implementation of &lt;code&gt;toggle&lt;/code&gt; won't either, because fundamentally, it is an indirect assignment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// version 1&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// is equivalent to&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todos&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;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Svelte checks if the updated variable or any of its properties is assigned a new value to determine whether &lt;code&gt;$$invalidate&lt;/code&gt; should be generated. This is how reactivity in svelte is implemented under the hood. If you wonder HOW it is implemented, again, go ahead and read its docs.&lt;/p&gt;

&lt;p&gt;Based on what we've found, if I'm so stubborn as to insist on using the first version of &lt;code&gt;toggle&lt;/code&gt; but want all the reactive magic to happen at the same time, I can just add a legitimate assignment like the following to generate the &lt;code&gt;$$invalidate&lt;/code&gt; side-effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// version 1&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="c1"&gt;// add this line&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;code&gt;todos[i] = todos[i]&lt;/code&gt; also does the trick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// version 1&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;todos&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todos&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="c1"&gt;// this works too&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;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The answer to my question turned out to be that the code, which failed to trigger a re-rendering of the UI, had an indirect assignment and indirect assignment does not trigger reactivity in svelte.&lt;/p&gt;

&lt;p&gt;We looked at the &lt;code&gt;$$invalidate&lt;/code&gt; side-effect which is the source of reactive magic behind svelte. We realized that to make a variable reactive, we must assign a value to itself or its properties if the variable is an object, otherwise &lt;code&gt;$$invalidate&lt;/code&gt; won't be generated.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Slim: A HTML Templating Language</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Mon, 09 Jan 2023 10:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/slim-a-html-templating-language-4665</link>
      <guid>https://forem.com/jessewei/slim-a-html-templating-language-4665</guid>
      <description>&lt;p&gt;In this part of the series, let's explore another popular templating language, &lt;a href="https://github.com/slim-template/slim" rel="noopener noreferrer"&gt;Slim&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is developed in the Ruby language and is often used to create view templates for Ruby on Rails projects. But apart from that, it is very similar to &lt;a href="https://pugjs.org/api/getting-started.html" rel="noopener noreferrer"&gt;Pug&lt;/a&gt; as well as other templating languages. &lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Basic Example&lt;/li&gt;
&lt;li&gt;
Start a Slim Project

&lt;ul&gt;
&lt;li&gt;Compile From Command Line&lt;/li&gt;
&lt;li&gt;Use Slim in Ruby Frameworks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;A More Advanced Example&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Basic Example
&lt;/h2&gt;

&lt;p&gt;Here's an example of a simple Slim template that generates an HTML page with a heading and a paragraph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight slim"&gt;&lt;code&gt;&lt;span class="nn"&gt;doctype&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;html
&lt;span class="nt"&gt;html&lt;/span&gt;
  &lt;span class="nt"&gt;head&lt;/span&gt;
    &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;My&lt;span class="w"&gt; &lt;/span&gt;Site
  &lt;span class="nt"&gt;body&lt;/span&gt;
    &lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Hello,&lt;span class="w"&gt; &lt;/span&gt;World!
    &lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;This&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;my&lt;span class="w"&gt; &lt;/span&gt;site&lt;span class="nc"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may have noticed that it looks &lt;em&gt;EXACTLY&lt;/em&gt; the same as the basic example of Pug we saw in &lt;a href="https://dev.to/jessewei/pug-a-html-templating-language-3oe2"&gt;part 1&lt;/a&gt; of the series. If you understand another templating language like Pug, you'll be comfortable using Slim too.&lt;/p&gt;

&lt;p&gt;And it would be &lt;em&gt;compiled&lt;/em&gt; into the exactly same HTML:&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Site&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello, World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is my site.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rendered page from the HTML looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kx3e9wk3xstl5q5b0of.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kx3e9wk3xstl5q5b0of.png" alt="Rendered page from basic example" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;
Rendered page from basic example



&lt;p&gt;Also as we discussed in &lt;a href="https://dev.to/jessewei/pug-a-html-templating-language-3oe2"&gt;part 1&lt;/a&gt; of the series, templates writen in languages other than HTML must be &lt;em&gt;compiled&lt;/em&gt; into HTML files before being served to the browser for rendering and this applies to Slim as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwlihfizvhiaia1m9vv5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwlihfizvhiaia1m9vv5.png" alt="How Slim works" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;
How Slim works






&lt;h2&gt;
  
  
  Start a Slim Project
&lt;/h2&gt;

&lt;p&gt;There are many different ways to start a Slim project depending on how you want to use it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compile From Command Line
&lt;/h3&gt;

&lt;p&gt;The easiest way to start is to install the &lt;code&gt;slimrb&lt;/code&gt; command-line tool and use it to compile your Slim files into HTML files.&lt;/p&gt;

&lt;p&gt;To install &lt;code&gt;slimrb&lt;/code&gt;, we use &lt;code&gt;gem install&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;slim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have not yet had &lt;code&gt;gem&lt;/code&gt; installed on your computer, you may need to install &lt;code&gt;ruby&lt;/code&gt; first. If you need help, check out &lt;a href="https://www.ruby-lang.org/en/documentation/installation/" rel="noopener noreferrer"&gt;Ruby docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then, we can create a Slim file at a location of your choice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;index.slim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add some code to the new file. I'll use code from our basic example here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight slim"&gt;&lt;code&gt;&lt;span class="nn"&gt;doctype&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;html
&lt;span class="nt"&gt;html&lt;/span&gt;
  &lt;span class="nt"&gt;head&lt;/span&gt;
    &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;My&lt;span class="w"&gt; &lt;/span&gt;Site
  &lt;span class="nt"&gt;body&lt;/span&gt;
    &lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Hello,&lt;span class="w"&gt; &lt;/span&gt;World!
    &lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;This&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;my&lt;span class="w"&gt; &lt;/span&gt;site&lt;span class="nc"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, compile the file to HTML file from command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;slimrb index.slim &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-p&lt;/code&gt; option tells &lt;code&gt;slimrb&lt;/code&gt; to output a &lt;em&gt;pretty&lt;/em&gt; (formatted) index.html file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Slim in Ruby Frameworks
&lt;/h3&gt;

&lt;p&gt;Most often, we want to use Slim in Ruby Frameworks such as Rails. In such cases, we can just write view templates in Slim (often with the help of a Slim template generator) instead of HTML and the built-in renderer of the framework will do the rest for us. &lt;/p&gt;

&lt;p&gt;Slim can be also used in projects of other languages such as Javascript with the help of proper packages. &lt;/p&gt;




&lt;h2&gt;
  
  
  A More Advanced Example
&lt;/h2&gt;

&lt;p&gt;This example demonstrates how to use variables, how to loop over a list, conditional rendering and css styling in Slim templates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight slim"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"My Shop"&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Calculator'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;price: &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Note Pad'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;price: &lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Pen'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;price: &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;

&lt;span class="nn"&gt;doctype&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;html
&lt;span class="nt"&gt;html&lt;/span&gt;
  &lt;span class="nt"&gt;head&lt;/span&gt;
    &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;My&lt;span class="w"&gt; &lt;/span&gt;Shop
  &lt;span class="nt"&gt;body&lt;/span&gt;
    &lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;heading&lt;/span&gt;
    &lt;span class="nt"&gt;table&lt;/span&gt;
      &lt;span class="nt"&gt;thead&lt;/span&gt;
        &lt;span class="nt"&gt;tr&lt;/span&gt;
          &lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Item&lt;span class="w"&gt; &lt;/span&gt;Name
          &lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Item&lt;span class="w"&gt; &lt;/span&gt;Price
          &lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Availability
      &lt;span class="nt"&gt;tbody&lt;/span&gt;
        &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="nt"&gt;tr&lt;/span&gt;
            &lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:price&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="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:available&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
              &lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;In&lt;span class="w"&gt; &lt;/span&gt;Stock
            &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;
              &lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="nc"&gt;.alert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Out&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;Stock

&lt;span class="nd"&gt;css:
&lt;/span&gt;  &lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;grey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-collapse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;collapse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.alert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This template is compiled to the following HTML file:&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Shop&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;
      My Shop
    &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;
            Item Name
          &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;
            Item Price
          &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;th&amp;gt;&lt;/span&gt;
            Availability
          &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            Calculator
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            10
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            In Stock
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            Note Pad
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            2.5
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            Out of Stock
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            Pen
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            6
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;
            In Stock
          &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;grey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-collapse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;collapse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.alert&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&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;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our page should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fip033i1nl7471itwv0ie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fip033i1nl7471itwv0ie.png" alt="An advanced example of Slim template" width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;
An advanced example of Slim template



&lt;p&gt;Please note that,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spreading variable definition on multiple lines causes syntax error and that's why I kept the &lt;code&gt;items&lt;/code&gt; definition on a single line (I haven't found a way to spread without an error yet).&lt;/li&gt;
&lt;li&gt;We can also link external stylesheets instead of specifying css rules directly in the template. Suppose we have a &lt;code&gt;styles.css&lt;/code&gt; in the same directory as our Slim template and we can link the style file like this, which is how we normally do in HTML files:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight slim"&gt;&lt;code&gt;&lt;span class="nc"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;head&lt;/span&gt;
  &lt;span class="c"&gt;/ we can also use an external stylesheet like this↓&lt;/span&gt;
  &lt;span class="nt"&gt;link&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"styles.css"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'stylesheet'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'text/css'&lt;/span&gt;
&lt;span class="nc"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Slim can do even more than the advanced example has demonstrated. For example, if you're working on a Rails project, it's likely you would want to create multiple partial templates and include them in other templates. This is when we'd want to use the &lt;code&gt;= render&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight slim"&gt;&lt;code&gt;&lt;span class="nn"&gt;doctype&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;html
&lt;span class="nt"&gt;html&lt;/span&gt;
  &lt;span class="nt"&gt;head&lt;/span&gt;
    &lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;My&lt;span class="w"&gt; &lt;/span&gt;Shop
  &lt;span class="nt"&gt;body&lt;/span&gt;
    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="s1"&gt;'header'&lt;/span&gt;
    &lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;This&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;my&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;shop&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;'footer'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;= render&lt;/code&gt; method is provided by frameworks like Rails but not available if you're using Slim as standalone template engine.&lt;/p&gt;




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

&lt;p&gt;In this part of the series, we learned the basics of Slim, another templating language that is widely used in Ruby frameworks.&lt;/p&gt;

&lt;p&gt;It shares a lot similarities with other templating languages like Pug in terms of general concepts and syntax. Thanks to its high expressiveness, it helps speed up development and improve code readability.&lt;/p&gt;

&lt;p&gt;And that's it. If you have any questions or feedback on the series, please comment below. Thank you.&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Pug: A HTML Templating Language</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Tue, 03 Jan 2023 10:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/pug-a-html-templating-language-3oe2</link>
      <guid>https://forem.com/jessewei/pug-a-html-templating-language-3oe2</guid>
      <description>&lt;p&gt;This series builds on my post, &lt;a href="https://dev.to/jessewei/supercharge-your-web-dev-workflow-with-emmet-3cg4"&gt;Supercharge Your Web Dev Workflow With Emmet&lt;/a&gt;, to which &lt;a href="https://dev.to/mackfitz"&gt;Maciek Fitzner&lt;/a&gt; posted a comment mentioning &lt;a href="https://pugjs.org/api/getting-started.html" rel="noopener noreferrer"&gt;Pug&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Templating languages are widely used in Web development and two of the most popular ones are &lt;a href="https://pugjs.org/api/getting-started.html" rel="noopener noreferrer"&gt;Pug&lt;/a&gt; and &lt;a href="https://github.com/slim-template/slim" rel="noopener noreferrer"&gt;Slim&lt;/a&gt;. In this series, we're going to learn the basics of these two and hopefully they would help improve your workflow further. &lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Emmet vs. Templating Languages&lt;/li&gt;
&lt;li&gt;
Meet Pug

&lt;ul&gt;
&lt;li&gt;An Overview&lt;/li&gt;
&lt;li&gt;How It Works&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Start a Pug Project&lt;/li&gt;

&lt;li&gt;Next Steps&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Emmet vs. Templating Languages
&lt;/h2&gt;

&lt;p&gt;The fundamental difference between Emmet and templating languages like Pug and Slim is that,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With the former which is just an editor extension, we write abbreviations which expand to full HTML code instantly when we press TAB. So we're basically &lt;strong&gt;still writing in HTML&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The latter, however, are different languages than HTML and have their own syntax. This means these template files must be &lt;strong&gt;converted (compiled, as we call it in the programming world) to HTML&lt;/strong&gt; before being forwarded to browsers to render.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It should be noted that many templating languages do not only support HTML, but can generate other types of files as well. In this series, however, we'll focus on HTML.&lt;/p&gt;




&lt;h2&gt;
  
  
  Meet Pug
&lt;/h2&gt;

&lt;h3&gt;
  
  
  An Overview
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://pugjs.org/api/getting-started.html" rel="noopener noreferrer"&gt;Pug&lt;/a&gt; is a templating language for Node.js and the browser. It is often used to generate HTML, but it can also be used to generate XML or other types of documents.&lt;/p&gt;

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

&lt;p&gt;Here's an example of a simple Pug template that generates an HTML page with a heading and a paragraph:&lt;/p&gt;

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

doctype html
html
  head
    title My Site
  body
    h1 Hello, World!
    p This is my site.


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

&lt;/div&gt;

&lt;p&gt;This template would be &lt;em&gt;compiled&lt;/em&gt; into the following HTML:&lt;/p&gt;

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

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Site&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello, World!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is my site.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The rendered page from the HTML looks like this:&lt;/p&gt;

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



&lt;p&gt;As the example demonstrates, Pug uses a combination of whitespace, indentation, and special characters to distinguish between HTML elements, code blocks, and other constructs.&lt;/p&gt;

&lt;p&gt;The Pug file is then &lt;em&gt;compiled&lt;/em&gt; into HTML files before being served to the browser for rendering. In fact, all templating languages work in similar manner because browers can only read HTML.&lt;/p&gt;

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






&lt;h2&gt;
  
  
  Start a Pug Project
&lt;/h2&gt;

&lt;p&gt;Before starting a pug project, make sure you have Node.js installed in your computer. Installation of Node.js is beyond this post, so do a bit of googling if you need any help.&lt;/p&gt;

&lt;p&gt;Follow these steps to start a new Pug project:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a new directory for your project and navigate to it in the terminal. For example:&lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/my-pug-project
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/my-pug-project


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initialize the project by creating a &lt;code&gt;package.json&lt;/code&gt; file in your project root and install the Pug package. For example:&lt;/p&gt;

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

npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;pug


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

&lt;/div&gt;

&lt;p&gt;Or if you choose to use &lt;code&gt;yarn&lt;/code&gt;:&lt;/p&gt;

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

yarn init &lt;span class="nt"&gt;-y&lt;/span&gt;
yarn add pug


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a directory in your project root to hold your Pug templates and create a pug file in it:&lt;/p&gt;

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

&lt;span class="nb"&gt;mkdir &lt;/span&gt;views
&lt;span class="nb"&gt;touch &lt;/span&gt;views/index.pug


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

&lt;/div&gt;

&lt;p&gt;Then give the new file the following content:&lt;/p&gt;

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

doctype html
html
  head
    title My Site
  body
    - var name = 'Jesse'
    h1 Hello, #{name}!
    p
      | This is my site. It is powered by
      |
      strong Pug
      | .
    - var users = ['Alice', 'Bob', 'Charlie', 'Dan']
    ul
      each user in users
        li= user
    if users.length &amp;gt; 3
      p There are more than 3 users in the list.
    else
      p There are 3 or fewer users in the list.


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

&lt;/div&gt;

&lt;p&gt;In this pug file, we used some more advanced features of Pug such as &lt;a href="https://pugjs.org/language/interpolation.html" rel="noopener noreferrer"&gt;variables&lt;/a&gt;, &lt;a href="https://pugjs.org/language/plain-text.html#piped-text" rel="noopener noreferrer"&gt;piped text&lt;/a&gt;, &lt;a href="https://pugjs.org/language/iteration.html" rel="noopener noreferrer"&gt;iteration&lt;/a&gt; and &lt;a href="https://pugjs.org/language/conditionals.html" rel="noopener noreferrer"&gt;conditionals&lt;/a&gt;. If you want to further familiarize yourself with these concepts, check out the links.&lt;/p&gt;

&lt;p&gt;Our pug template generates the following HTML code:&lt;/p&gt;

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

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Site&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello, Jesse!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is my site. It is powered by
      &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Pug&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;.
    &lt;span class="nt"&gt;&amp;lt;/p&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;li&amp;gt;&lt;/span&gt;Alice&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Bob&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Charlie&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Dan&lt;span class="nt"&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;p&amp;gt;&lt;/span&gt;There are more than 3 users in the list.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We need a server to compile our Pug file into HTML file, so at our project root, create a &lt;code&gt;server.js&lt;/code&gt; file:&lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;server.js


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

&lt;/div&gt;

&lt;p&gt;And add the following content to it:&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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Set the view engine to pug&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;view engine&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="s1"&gt;pug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Set the views directory&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;views&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="s1"&gt;./views&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Define a route for the home page&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index&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="c1"&gt;// Start the server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Listening on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&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="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;As we're using the &lt;code&gt;express&lt;/code&gt; package here, we need to install it:&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;express


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

&lt;/div&gt;

&lt;p&gt;Or:&lt;/p&gt;

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

yarn add express


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

&lt;/div&gt;

&lt;p&gt;If you need help with &lt;code&gt;express&lt;/code&gt; or want to learn more about it, check out its &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;official docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start the server by running:&lt;/p&gt;

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

node server.js


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

&lt;/div&gt;

&lt;p&gt;Now go to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; and boom! Our page should be rendered properly like this:&lt;/p&gt;

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






&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;In the first part of the series, we learned the basics of Pug, a popular templating language for generating HTML. We saw some simple but inspiring examples that should be enough to help you get started.&lt;/p&gt;

&lt;p&gt;If you want to dive a bit deeper into Pug, I'd recommend you have a look at their &lt;a href="https://pugjs.org/api/getting-started.html" rel="noopener noreferrer"&gt;docs&lt;/a&gt;. Each of the topics is explained with code examples that you can try out instantly.&lt;/p&gt;

&lt;p&gt;In the next part, I'll walk you through another templating language, Slim. So please follow me to stay tuned.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>html</category>
      <category>pug</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Supercharge Your Web Dev Workflow With Emmet</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Thu, 29 Dec 2022 10:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/supercharge-your-web-dev-workflow-with-emmet-3cg4</link>
      <guid>https://forem.com/jessewei/supercharge-your-web-dev-workflow-with-emmet-3cg4</guid>
      <description>&lt;p&gt;&lt;a href="https://emmet.io/" rel="noopener noreferrer"&gt;Emmet&lt;/a&gt; is a tool that allows you to quickly generate HTML and CSS code by using abbreviations and expanding them into full code.&lt;/p&gt;

&lt;p&gt;It is built into many popular code editors, including &lt;a href="https://code.visualstudio.com/docs/editor/emmet" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;, &lt;a href="https://github.com/emmetio/sublime-text-plugin" rel="noopener noreferrer"&gt;Sublime Text&lt;/a&gt; and &lt;a href="https://github.com/emmetio/emmet-atom" rel="noopener noreferrer"&gt;Atom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Today, let's take a look at how to use Emmet to boost your web development speed. I'll use VSCode as my editor, but feel free to pick up your favorite. You'll need to check out editor-specific docs of Emmet for the configuration part of the post if you choose something other than VSCode, but that should not be a problem for you to follow along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Example Usage for HTML

&lt;ul&gt;
&lt;li&gt;Represent relationships&lt;/li&gt;
&lt;li&gt;Represent attributes&lt;/li&gt;
&lt;li&gt;Represent Repeating Snippets&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Example Usage for CSS&lt;/li&gt;

&lt;li&gt;Advanced Configuration&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Example Usage for HTML
&lt;/h2&gt;

&lt;p&gt;The best part of coding HTML involves writing (deeply) nested structures with attributes such as classes and ids attached to tags. Emmet can help us generating highly complicated HTML structures with a single line of code.&lt;/p&gt;

&lt;p&gt;To achieve that, Emmet use concise syntax to represent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relationships between tags&lt;/li&gt;
&lt;li&gt;Attributes attached to tags&lt;/li&gt;
&lt;li&gt;Repeating snippets&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Represent relationships
&lt;/h3&gt;

&lt;p&gt;One of the most common use cases of Emmet is to generate HTML tag hierarchy. Here is a quick example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93zpq68f23qsheevceg5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93zpq68f23qsheevceg5.gif" alt="Basic example of using Emmet to generate HTML tag hierarchy"&gt;&lt;/a&gt;&lt;/p&gt;
Emmet generating nested tags with &amp;gt; mark



&lt;p&gt;We use &lt;code&gt;&amp;gt;&lt;/code&gt; to represent parent-child relationship in Emmet.  To represent sibling-sibling relationship, we use &lt;code&gt;+&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vju11hn86hkiy9elij2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vju11hn86hkiy9elij2.gif" alt="Use + to generate sibling tags"&gt;&lt;/a&gt;&lt;/p&gt;
Emmet generating sibling tags with + mark



&lt;p&gt;We can even &lt;em&gt;climb up&lt;/em&gt; from current level to upper level using &lt;code&gt;^&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxw9m9r2txh3av4hbmmbw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxw9m9r2txh3av4hbmmbw.gif" alt="Climb up to upper level with ^ mark"&gt;&lt;/a&gt;&lt;/p&gt;
Climb up to upper level with ^ mark



&lt;p&gt;Here, we generated a &lt;code&gt;p&lt;/code&gt; with two &lt;code&gt;span&lt;/code&gt;s inside and a &lt;code&gt;ul&lt;/code&gt; at the same level as the &lt;code&gt;p&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Please note we can also achieve the same result by using &lt;em&gt;grouping&lt;/em&gt;:&lt;/p&gt;

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



&lt;p&gt;We grouped the &lt;code&gt;p&lt;/code&gt; and its children in a pair of parentheses and replaced climb-up mark (&lt;code&gt;^&lt;/code&gt;) with sibling mark (&lt;code&gt;+&lt;/code&gt;) for &lt;code&gt;ul&lt;/code&gt; (it seems same structure can still be correctly generated even if you don't replace &lt;code&gt;^&lt;/code&gt; with &lt;code&gt;+&lt;/code&gt; here, but for semantic reasons, I think &lt;code&gt;+&lt;/code&gt; is more appropriate in this case).&lt;/p&gt;

&lt;h3&gt;
  
  
  Represent attributes
&lt;/h3&gt;

&lt;p&gt;HTML tags usually have attributes such as classes and ids. In Emmet, we use &lt;code&gt;.classname&lt;/code&gt; and &lt;code&gt;#id&lt;/code&gt; to represent classes and ids respectively:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa734pjsz92zijhczqjb0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa734pjsz92zijhczqjb0.gif" alt="Specify class with dot and id with sharp mark"&gt;&lt;/a&gt;&lt;/p&gt;
Specify class with dot and id with sharp mark



&lt;p&gt;It's as easy as that. For abbrevations for other attributes, check out the &lt;a href="https://docs.emmet.io/cheat-sheet/" rel="noopener noreferrer"&gt;official Emmet cheat sheet&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Represent Repeating Snippets
&lt;/h3&gt;

&lt;p&gt;Repeating structures usually take the most time to write and fortunately with Emmet, such snippets cannot be generated more easily:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpo662zotaavu70rvf8hj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpo662zotaavu70rvf8hj.gif" alt="Generate repeating tags with asterisk mark"&gt;&lt;/a&gt;&lt;/p&gt;
Generate repeating tags with asterisk mark



&lt;p&gt;To generate auto-incrementing ids, for example, we can combine asterisk with &lt;code&gt;$&lt;/code&gt; (dollar sign):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8dw0j3c1o7eyde5x64j6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8dw0j3c1o7eyde5x64j6.gif" alt="Generate auto-incrementing ids with * and $"&gt;&lt;/a&gt;&lt;/p&gt;
Generate auto-incrementing ids with * and $



&lt;p&gt;Here is a more advanced example demonstrating auto-incrementing ids along with auto-incrementing &lt;em&gt;text&lt;/em&gt;:&lt;/p&gt;

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






&lt;h2&gt;
  
  
  Example Usage for CSS
&lt;/h2&gt;

&lt;p&gt;Emmet makes coding with CSS just as easy as HTML. Each CSS rule has corresponding abbreviations and once you understand the patterns of abbreviations, you don't need to remember them:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpal2vwb7ke4z3xkg4ax6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpal2vwb7ke4z3xkg4ax6.gif" alt="Generating CSS code is as easy using Emmet"&gt;&lt;/a&gt;&lt;/p&gt;
Generating CSS code is as easy using Emmet



&lt;p&gt;Please note that,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wrote &lt;code&gt;db&lt;/code&gt;, for example, instead of &lt;code&gt;d:b&lt;/code&gt; as the &lt;a href="https://docs.emmet.io/cheat-sheet/" rel="noopener noreferrer"&gt;cheat sheet&lt;/a&gt; suggests. It seems either way works, although it's not clear why. So choose the convention that suits you best.&lt;/li&gt;
&lt;li&gt;While the cheat sheet does not mention, you can expand shorthand CSS rules, e.g. &lt;code&gt;margin: 10px auto&lt;/code&gt; with &lt;code&gt;m10:a&lt;/code&gt; or &lt;code&gt;m:10:a&lt;/code&gt; as I did in the screenshot above.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Advanced Configuration
&lt;/h2&gt;

&lt;p&gt;While Emmet is available by default for common file types such as html, slim, css and sass, you'll need to manually enable it if you're working on a different file type where Emmet is not activated by default.&lt;/p&gt;

&lt;p&gt;For example, Emmet is not enabled by default for Ruby on Rails view files with the &lt;code&gt;.erb&lt;/code&gt; extension. If I want to write HTML code in these files, I can update the &lt;code&gt;emmet.includeLanguages&lt;/code&gt; setting in my VSCode's &lt;code&gt;settings.json&lt;/code&gt; file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"emmet.includeLanguages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"erb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key (&lt;code&gt;"erb"&lt;/code&gt;) on the left side is the &lt;strong&gt;target file type&lt;/strong&gt; where I want Emmet to be available while the value (&lt;code&gt;"html"&lt;/code&gt;) is a &lt;strong&gt;file type that Emmet already supports&lt;/strong&gt;. See &lt;a href="https://code.visualstudio.com/docs/editor/emmet#_emmet-abbreviations-in-other-file-types" rel="noopener noreferrer"&gt;VSCode docs on this&lt;/a&gt; for more information.  &lt;/p&gt;




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

&lt;p&gt;In this post, we took a quick look at some of the most common scenarios where Emmet can help us write HTML and CSS code times faster.&lt;/p&gt;

&lt;p&gt;As I said, there's more Emmet can do for us than I demonstrated here. It has an amazing, super comprehensive &lt;a href="https://docs.emmet.io/cheat-sheet/" rel="noopener noreferrer"&gt;cheat sheet&lt;/a&gt; which you can use as a reference.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Manage Node.js Versions With n</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Wed, 28 Dec 2022 00:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/manage-nodejs-versions-with-n-5fi0</link>
      <guid>https://forem.com/jessewei/manage-nodejs-versions-with-n-5fi0</guid>
      <description>&lt;p&gt;One of the first challenges you may come across when starting to learn Javascript is how to deal with multiple versions of Node.js.&lt;/p&gt;

&lt;p&gt;Today, let's find out why you would need multiple versions of Node.js in the first place and how to manage them efficiently with &lt;a href="https://github.com/tj/n"&gt;n&lt;/a&gt;, a Node.js version manager that is very developer-friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Multiple Versions of Node.js?
&lt;/h2&gt;

&lt;p&gt;The main reason why you may need multiple versions of Node.js is &lt;strong&gt;compatibility&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Different versions of Node.js can be incompatible with certain packages or libraries and different projects are usually developed using different versions of Node.js. &lt;/p&gt;

&lt;p&gt;For example, a package that was built for Node.js version 8 might not work with version 12. Also, you may have to work on a project that is developed with Node.js version 14 but you only have version 18 installed in your local computer.&lt;/p&gt;

&lt;p&gt;By managing multiple versions of Node.js, you can ensure that your application is compatible with the packages and libraries it depends on and you can choose the right version to use for a particular project.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Manage Node.js Versions: Meet n
&lt;/h2&gt;

&lt;p&gt;Now that we see why we may need multiple versions of Node.js, let's take a look at how to manage them.&lt;/p&gt;

&lt;p&gt;Although we can just head to the official website of Node.js, download and install it, it is only one version and we cannot keep multiple versions of Node.js on our computer this way.&lt;/p&gt;

&lt;p&gt;That's where &lt;em&gt;Node.js managers&lt;/em&gt; come into play. A Node.js manager is itself a package, but it can help us install multiple versions of Node.js and switch between the versions easily.&lt;/p&gt;

&lt;p&gt;The Node.js manager I want to introduce today is &lt;a href="https://github.com/tj/n"&gt;n&lt;/a&gt;, which is super easy to install and use.&lt;/p&gt;

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

&lt;p&gt;If you have Node.js installed, you can just run:&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;-g&lt;/span&gt; n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to install &lt;code&gt;n&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you haven't had Node.js installed yet, you can run these commands to first install the latest version of Node.js (to make &lt;code&gt;npm&lt;/code&gt; available) and then install &lt;code&gt;n&lt;/code&gt; with &lt;code&gt;npm&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://raw.githubusercontent.com/tj/n/master/bin/n &lt;span class="nt"&gt;-o&lt;/span&gt; n
bash n lts
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other installation options include installing with &lt;code&gt;brew&lt;/code&gt; or &lt;code&gt;port&lt;/code&gt; for Mac users and installing from github. Check out the &lt;a href="https://github.com/tj/n#readme"&gt;README&lt;/a&gt; of the &lt;code&gt;n&lt;/code&gt; repo for more information.&lt;/p&gt;

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

&lt;p&gt;After &lt;code&gt;n&lt;/code&gt; is installed, let's run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/local/n
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; /usr/local/n
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/local/bin /usr/local/lib /usr/local/include /usr/local/share
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;whoami&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; /usr/local/bin /usr/local/lib /usr/local/include /usr/local/share
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands look daunting but basically what we're doing here is just take ownership of the &lt;code&gt;n&lt;/code&gt; directory as well as other relevant system directories. This way, we don't have to use &lt;code&gt;sudo&lt;/code&gt; to install packages with &lt;code&gt;n&lt;/code&gt; or &lt;code&gt;npm&lt;/code&gt;. Find out more about this from the &lt;a href="https://github.com/tj/n#installation"&gt;installation guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Out
&lt;/h2&gt;

&lt;p&gt;To see versions of Node.js available for downloading:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;n ls-remote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lists the latest 20 versions, but if you want to list all versions, add the &lt;code&gt;--all&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;n ls-remote &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see downloaded versions of Node.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's as simple as that. This command output all versions that you've downloaded with the active version highlighted.&lt;/p&gt;

&lt;p&gt;To download a specific version of Node.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;n &amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To download the latest version of Node.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;n lts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To switch versions of Node.js, output downloaded versions first with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then, use arrow keys to select a version and press Enter (Return) to confirm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  ο node/14.18.1
    node/19.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information on the usage of &lt;code&gt;n&lt;/code&gt;, check out its &lt;a href="https://github.com/tj/n#installing-nodejs-versions"&gt;docs&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;In this post, we took a quick look at why we might want to manage multiple versions of Node.js and how we can do it by using the &lt;code&gt;n&lt;/code&gt; manager.&lt;/p&gt;

&lt;p&gt;There are a couple of other alternatives to &lt;code&gt;n&lt;/code&gt;, but I find &lt;code&gt;n&lt;/code&gt; the easiest to get used to and its docs are great. Try it out now and I think you'll like it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Javascript Prototype: Prototype Chain and Shadowing</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Sat, 24 Dec 2022 10:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/javascript-prototype-prototype-chain-and-shadowing-3oe2</link>
      <guid>https://forem.com/jessewei/javascript-prototype-prototype-chain-and-shadowing-3oe2</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/jessewei/javascript-prototype-the-basics-3n16"&gt;part 1&lt;/a&gt; of the series, we learned the basics of Javascript prototype. We saw why it is important to understand it, what a prototype really is and looked at some relevant terms.&lt;/p&gt;

&lt;p&gt;In this part, we'll continue our journey by diving a bit deeper into prototype and have a look at what &lt;em&gt;prototype chain&lt;/em&gt;  and &lt;em&gt;property shadowing&lt;/em&gt; are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prototype Chain&lt;/li&gt;
&lt;li&gt;Property Shadowing&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prototype Chain
&lt;/h2&gt;

&lt;p&gt;Every object in JavaScript has a prototype, which is &lt;strong&gt;either an object itself or null&lt;/strong&gt;. When a property or method is accessed on an object, JavaScript will first look for that property on the object itself. If it is not found, it will search its prototype. This continues until the property is found or the uppermost prototype, which is &lt;em&gt;null&lt;/em&gt;, is reached. This process is called prototype chain.&lt;/p&gt;

&lt;p&gt;As an example, let's say we have the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;vehicle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;run&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;run, run, run!&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;drive&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drive, drive, drive!&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myCar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;broken&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="nx"&gt;myCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: myCar.drive is not a function&lt;/span&gt;
&lt;span class="nx"&gt;myCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// TypeError: myCar.run is not a function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we try to access the &lt;code&gt;drive()&lt;/code&gt; and &lt;code&gt;run()&lt;/code&gt; methods on &lt;code&gt;myCar&lt;/code&gt;, we get an error. This is no surprise, as &lt;code&gt;myCar&lt;/code&gt; does not have these methods defined on it.&lt;/p&gt;

&lt;p&gt;Let's add the following code before calling the methods:&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vehicle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myCar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// and this&lt;/span&gt;

&lt;span class="nx"&gt;myCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 'drive, drive, drive!'&lt;/span&gt;
&lt;span class="nx"&gt;myCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 'run, run, run!'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the errors are gone and we get the expected results from calling the methods. But wait, &lt;code&gt;myCar&lt;/code&gt; still does not have these methods defined on it, does it? &lt;/p&gt;

&lt;p&gt;Because we set the prototype of &lt;code&gt;car&lt;/code&gt; to &lt;code&gt;vehicle&lt;/code&gt; and the prototype of &lt;code&gt;myCar&lt;/code&gt; to &lt;code&gt;car&lt;/code&gt;, now when Javascript does not find the method &lt;code&gt;drive()&lt;/code&gt; on &lt;code&gt;myCar&lt;/code&gt;, it traverses up to its prototype (&lt;code&gt;car&lt;/code&gt;) where it finds and calls the method. This is prototype chain in action and Javascript follows the chain to find and call &lt;code&gt;run()&lt;/code&gt; too.&lt;/p&gt;

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





&lt;p&gt;Please note that the image above does not show the full story. The prototype chain can actually go even further beyond &lt;code&gt;vehicle&lt;/code&gt; until it reaches &lt;em&gt;null&lt;/em&gt;.&lt;/p&gt;

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





&lt;p&gt;Near the top of the chain we have &lt;code&gt;Object.prototype&lt;/code&gt; which is itself an object with methods like &lt;code&gt;hasOwnProperty&lt;/code&gt;, &lt;code&gt;toString&lt;/code&gt; and &lt;code&gt;valueOf&lt;/code&gt;. As any objects down the chain inherit these methods, we can access these methods on &lt;code&gt;vehicle&lt;/code&gt;, &lt;code&gt;car&lt;/code&gt; and &lt;code&gt;myCar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;myCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;broken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;span class="nx"&gt;myCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note that setting the prototype of an object with &lt;code&gt;Object.setPrototypeOf()&lt;/code&gt; is slow as explained &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Instead, it's recommended we create new objects with the desired prototype using &lt;code&gt;Object.create()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myNewCar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myNewCar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;car&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Property Shadowing
&lt;/h2&gt;

&lt;p&gt;Property shadowing sounds abstract and daunting but it is actually a very simple concept. It basically &lt;strong&gt;describes what happens when an object and its prototype both define a property with the same name&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because in a prototype chain the object is traversed before its prototype, we know the property defined on the object itself will be accessed or called (in case of a function) before Javascript reaches its prototype.&lt;/p&gt;

&lt;p&gt;Considering the previous example after the prototype of &lt;code&gt;myCar&lt;/code&gt; is set to &lt;code&gt;car&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;drive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// body of drive method },&lt;/span&gt;
  &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt; &lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;myCar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;broken&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="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt; &lt;span class="c1"&gt;// add this&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;myCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 50000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we say the &lt;code&gt;price&lt;/code&gt; on &lt;code&gt;myCar&lt;/code&gt; &lt;em&gt;shadowed&lt;/em&gt; the &lt;code&gt;price&lt;/code&gt; property on the prototype of &lt;code&gt;myCar&lt;/code&gt;.&lt;/p&gt;




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

&lt;p&gt;In this part of the series, we looked at how prototype chain works and what property shadowing is.&lt;/p&gt;

&lt;p&gt;If you followed along, you should've had a pretty solid idea on Javascript prototype. But there's just much more about it and in the next part, let's explore concepts like &lt;em&gt;constructors, classes and inheritance&lt;/em&gt; which are all built upon the concept of prototype.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>prototype</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Javascript Prototype: The Basics</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Sun, 18 Dec 2022 10:00:00 +0000</pubDate>
      <link>https://forem.com/jessewei/javascript-prototype-the-basics-3n16</link>
      <guid>https://forem.com/jessewei/javascript-prototype-the-basics-3n16</guid>
      <description>&lt;p&gt;I think &lt;em&gt;prototype&lt;/em&gt; is one of the hardest concepts to understand in Javascript. Some of the reasons for that may be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More and more developers are using Javascript frameworks these days and most developers can get their job done without touching prototype.&lt;/li&gt;
&lt;li&gt;There are a few terms about prototype that are just confusing, e.g. &lt;code&gt;__proto__&lt;/code&gt;, &lt;code&gt;getPrototypeOf&lt;/code&gt; and &lt;code&gt;prototype&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So why bother even talking about it then? Because understanding how prototypes work can help you develop more efficient and organized code in JavaScript. If you want to become an experienced Javascript developer, you cannot escape it.&lt;/p&gt;

&lt;p&gt;In this series, I want to share with you what I learned about prototype and hope it helps you a bit in your journey to Javascript mastery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Glimpse of Prototype&lt;/li&gt;
&lt;li&gt;
__proto__, Object.getPrototypeOf() and prototype

&lt;ul&gt;
&lt;li&gt;__proto__ and Object.getPrototypeOf()&lt;/li&gt;
&lt;li&gt;prototype&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Glimpse of Prototype
&lt;/h2&gt;

&lt;p&gt;In JavaScript, a prototype is &lt;strong&gt;an object that serves as a template for creating new objects&lt;/strong&gt;. When a new object is created, it inherits the properties and methods of its prototype. This makes it easy to organize and extend your code. &lt;/p&gt;

&lt;p&gt;This example demonstrates how to create an object with a particular prototype and how to access the object's prototype and (don't worry about the code at this point, we'll get to it later).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;canDrive&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;andy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// check the prototype of the new object: andy&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;andy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;span class="c1"&gt;// call the method defined on the object's prototype&lt;/span&gt;
&lt;span class="nx"&gt;andy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canDrive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  __proto__, Object.getPrototypeOf() and prototype
&lt;/h2&gt;

&lt;p&gt;Now that we had a basic idea on prototype, it's time to clarify a few terms that cause most confusion: &lt;code&gt;__proto__&lt;/code&gt;, &lt;code&gt;Object.getPrototypeOf()&lt;/code&gt; and &lt;code&gt;prototype&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  __proto__ and Object.getPrototypeOf()
&lt;/h3&gt;

&lt;p&gt;To get the prototype of an object in JavaScript, we have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the &lt;code&gt;__proto__&lt;/code&gt; property&lt;/li&gt;
&lt;li&gt;Or the &lt;code&gt;Object.getPrototypeOf()&lt;/code&gt; method&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While many modern browser supports it, &lt;code&gt;__proto__&lt;/code&gt; is deprecated and it's recommended we use &lt;code&gt;Object.getPrototypeOf()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is an example using both approaches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// properties and methods go here&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// These two are equivalent↓&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fooPrototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__proto__&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fooPrototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  prototype
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Every function has a &lt;em&gt;prototype&lt;/em&gt; property&lt;/strong&gt; in Javascript. It's important to distinguish it from the notion, &lt;strong&gt;every object has a prototype&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The prototype of an object is in fact a property too, only that it cannot be accessed via &lt;code&gt;someObject.prototype&lt;/code&gt;. Instead, we use &lt;code&gt;someObject.__proto__&lt;/code&gt; as we've seen above. In other words, &lt;strong&gt;it is the &lt;code&gt;__proto__&lt;/code&gt; property that points to the actual prototype of an object&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;prototype&lt;/em&gt; property of a function, on the other hand, serves as the prototype of new objects created using the function as constructor (that is, with the &lt;code&gt;new&lt;/code&gt; keyword).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// call foo as constructor&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myObj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is &lt;code&gt;foo.prototype&lt;/code&gt; the prototype of &lt;code&gt;foo&lt;/code&gt;? Certainly not. I said &lt;code&gt;foo.prototype&lt;/code&gt; is the prototype of new objects created via &lt;code&gt;new foo()&lt;/code&gt;, so it cannot be the prototype of &lt;code&gt;foo&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;What is the prototype of &lt;code&gt;foo&lt;/code&gt; then? It is &lt;code&gt;Function.prototype&lt;/code&gt; in most cases (by which I mean if you didn't assign a new prototype to it), because functions are all created calling &lt;code&gt;Function&lt;/code&gt; as constructor (via &lt;code&gt;new Function(args)&lt;/code&gt;) under the hood.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please remember that the &lt;code&gt;prototype&lt;/code&gt; property is itself an object whose prototype is &lt;code&gt;Object.prototype&lt;/code&gt; (if you didn't override it).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To summerize, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The prototype of an object is a property that can be accessed via &lt;code&gt;__proto__&lt;/code&gt; and &lt;code&gt;Object.getPrototypeOf()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;prototype&lt;/code&gt; is a property that every function has. It is the prototype of new objects created by calling the function as constructor.&lt;/li&gt;
&lt;li&gt;The actual prototype of a function (as distinguished from the &lt;code&gt;prototype&lt;/code&gt; property) is &lt;code&gt;Function.prototype&lt;/code&gt; (if you didn't override it).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;prototype&lt;/code&gt; property is itself an object whose prototype is &lt;code&gt;Object.prototype&lt;/code&gt; (if you didn't override it).&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;In the first part of the series, we had an overview of prototype, clarified some key terms about it and saw some code samples to help us get an initial impression on how prototype works.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/jessewei/javascript-prototype-prototype-chain-and-shadowing-3oe2"&gt;part 2&lt;/a&gt;, we'll take a closer look at concepts like prototype chain and shadowing.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>prototype</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Fix Error: Cannot Redeclare Block-Scoped Variable in TypeScript</title>
      <dc:creator>Jesse Wei</dc:creator>
      <pubDate>Thu, 15 Dec 2022 06:31:51 +0000</pubDate>
      <link>https://forem.com/jessewei/fix-error-cannot-redeclare-block-scoped-variable-in-typescript-1efb</link>
      <guid>https://forem.com/jessewei/fix-error-cannot-redeclare-block-scoped-variable-in-typescript-1efb</guid>
      <description>&lt;p&gt;If you're using Typescript, it's likely you've run into this error, &lt;em&gt;"Cannot redeclare block-scoped variable"&lt;/em&gt; a couple of times.&lt;/p&gt;

&lt;p&gt;Although the issue is discussed widely online across multiple platforms, I could not find a comprehensive source explaing the why and the fix in depth.&lt;/p&gt;

&lt;p&gt;So I wrote this article to help you understand the problem in context, look at different scenarios where you can run into the error and how to fix it in each scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Concept of Scope&lt;/li&gt;
&lt;li&gt;Understanding the Error&lt;/li&gt;
&lt;li&gt;
Fixing the Error

&lt;ul&gt;
&lt;li&gt;Scenario 1: Same variable in same block&lt;/li&gt;
&lt;li&gt;Scenario 2: Same variable in same project&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Concept of Scope
&lt;/h2&gt;

&lt;p&gt;To understand the error and come up with a fix for it, we need to understand the concept of scope first.&lt;/p&gt;

&lt;p&gt;Scope refers to the visibility and accessibility of variables and functions in different parts of your code. There are two main types of scope in JavaScript (Typescript): &lt;strong&gt;global scope&lt;/strong&gt; and &lt;strong&gt;local scope&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global scope&lt;/strong&gt; refers to the scope where variables and functions can be accessed throughout your entire file or project. Variables and functions that are declared at the top level of your code, outside of any functions or blocks, are considered to be in global scope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local scope&lt;/strong&gt;, on the other hand, refers to the visibility and accessibility of variables and functions within a specific block of code, such as within a function or a block of code delimited by curly braces ({}). Variables and functions that are declared within a block of code are considered to be in local scope and are only accessible within that block of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Error
&lt;/h2&gt;

&lt;p&gt;Now that we learned what a scope is, we can better understand the error "Cannot redeclare block-scoped variable 'foo'". As you may have realized, it basically says we're trying to declare a variable named &lt;code&gt;foo&lt;/code&gt; in the same scope where a variable named &lt;code&gt;foo&lt;/code&gt; already exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing the Error
&lt;/h2&gt;

&lt;p&gt;There can be a couple of different scenarios where you might run into this error and so we need to take a look at how to fix it in those scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 1: Same variable in same block
&lt;/h3&gt;

&lt;p&gt;For example, this code throws the error mentioned because the variable &lt;code&gt;foo&lt;/code&gt; is declared twice in the same function block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;myFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can fix it by either renaming the second &lt;code&gt;foo&lt;/code&gt; variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;myFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// renamed to bar&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Or by moving the declaration of the second &lt;code&gt;foo&lt;/code&gt; variable to a different block of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;myFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="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;foo&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// a different scope&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;
  
  
  Scenario 2: Same variable in same project
&lt;/h3&gt;

&lt;p&gt;Say we have a simple project with the following hierarchy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── main.js
├── main.ts
├── node_modules
├── package-lock.json
└── package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;main.ts&lt;/code&gt;, we have this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we compile &lt;code&gt;main.ts&lt;/code&gt; to &lt;code&gt;main.js&lt;/code&gt; and now, &lt;code&gt;main.js&lt;/code&gt; has the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;foo&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now back to the &lt;code&gt;main.ts&lt;/code&gt; file and we get the error saying, "Cannot redeclare block-scoped variable 'foo'", &lt;em&gt;even though we only declared &lt;code&gt;foo&lt;/code&gt; once in our file&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This is because variables declared in a file, which does not have a top-level import or export, are available in the entire project. According to &lt;a href="https://www.typescriptlang.org/docs/handbook/modules.html#handbook-content"&gt;Typescript Docs&lt;/a&gt;,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any file containing a top-level import or export is considered a module. Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since we have another &lt;code&gt;foo&lt;/code&gt; in &lt;code&gt;main.js&lt;/code&gt;, Typescript complained with the error.&lt;/p&gt;

&lt;p&gt;To fix this, we have a couple of options. First, we can just rename one of the &lt;code&gt;foo&lt;/code&gt;s to something else as we did in scenario 1, but most likely this is not desirable as we don't want to rename every variable after compilation.&lt;/p&gt;

&lt;p&gt;Then, we can just add an export to &lt;code&gt;main.ts&lt;/code&gt; to make it a module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&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;export&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// add this line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or we can also wrap the variable with &lt;code&gt;{}&lt;/code&gt; to move it into a local scope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another option to get rid of the error is, if you have &lt;code&gt;tsconfig.json&lt;/code&gt; in your project root, adding the following setting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ES6"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I googled multiple sources to find out why this works but unfortunately could not get a persuasive answer. Some argue it's about opting out Typescript's DOM typings (check out &lt;a href="https://stackoverflow.com/a/50913569/19012032"&gt;this answer&lt;/a&gt; and &lt;a href="https://github.com/microsoft/TypeScript/issues/9466#issuecomment-230089243"&gt;this thread&lt;/a&gt;), but no error is thrown even if I &lt;em&gt;KEEP&lt;/em&gt; the DOM typings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"DOM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ES6"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've got a better answer, feel free to share in the comments below.&lt;/p&gt;

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

&lt;p&gt;In this post, I shared with you a common error in Typescript, the cause of it and how to fix it in different scenarios.&lt;/p&gt;

&lt;p&gt;Even though there are quite a few answers and blog posts on this topic, very few of them explored the why in depth and discussed the different cases where you could run into the error.&lt;/p&gt;

&lt;p&gt;I hope this article helps and if you have got an idea why this setting,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ES6"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;did the trick, please comment below. Thank you.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>debug</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
