How to create a custom element (HTML tag) in HTML?

Until HTML5 , reusing a piece of html code was not straightforward.

Thanks to HTML5 , web components came into picture.

Now you can create your own custom components and include them in your HTML code using custom tags.

And you can reuse them anywhere else in your application by declaring the custom tags just like you declare your standard HTML tags.

For example,

Imagine you are preparing a digital menu for a restaurant using HTML5.

You can create a list of items using the below code:

     
<ul>

<li>

<h2>Soups(Non Veg)</h2>


<ul>

<li class="minigrid">
                
<data class="itemname" id="itemname">Thoum(S/M/L)   </data>
<data class="itemprice" id="itemprice" >Rs.40/65/130</data>
</li>

<li class="minigrid">
<data class="itemname" id="itemname">Hummus(S/M/L)</data>
<data class="itemprice" id="itemprice">Rs.50/95/130</data>
</li>

<li class="minigrid">

<data class="itemname" id="itemname">chicken Hawaiian Salad</data>
<data class="itemprice" id="itemprice">Rs.150</data>
</li> 


</ul>

</li>


</ul>

This just displays the below output:

For every menu item you add , you need to use the below code:

<li class="minigrid">

	<data class="itemname" id="itemname">chicken Hawaiian Salad</data>
	<data class="itemprice" id="itemprice">Rs.150</data>
	</li> 

Each list item has a CSS class associated with it for styling (“minigrid”)

Each item name and item price have their own styling as well.

Imagine how elegant it would be to replace the above piece of code like below:

<menu-item name="chicken Hawaiian Salad" price ="Rs.150"></menu-item>

And for every additional menu item , you can keep repeating the above tag.

That is exactly what HTML custom elements allow you to do.

To do this, follow the below steps:

STEP1: Create a custom element class which extends HTMLElement class , using Javascript :

class MenuItem extends HTMLElement{


}

STEP2: Inside this class create a constructor and call super() keyword . This calls the constructor of HTMLElement class which is mandatory.

class MenuItem extends HTMLElement{


  constructor(){

   super();
}

}

STEP3: Create a shadow DOM and attach all your html elements to it

A shadow DOM can be thought of as a custom DOM which you can build yourself and later attach it to the original HTML DOM.

Here is how you create a shadow DOM root element:

class MenuItem extends HTMLElement{


    constructor(){


        super();


        const shadow = this.attachShadow({mode:'open'});


}

In the above code , the method attachShadow() is used to create the shadow DOM root element.

The mode “open” means elements of the shadow root can be accessed through javascript outside the root.

Once you create the shadow root start creating html elements and appending them to the root.

In the below code , I am creating two “data” elements and appending them to a list element.

In turn the list element is appended to the shadow root element.

Also custom styling can be defined by creating a “style” element.

I am creating this and attaching that to the shadow element as well:

class MenuItem extends HTMLElement{


    constructor(){


        super();


        const shadow = this.attachShadow({mode:'open'});


        const item = document.createElement("li");

        item.setAttribute("class","minigrid");



        const itemname = document.createElement("data");

        itemname.setAttribute("class","itemname");

        const itemnameval = this.getAttribute("name");

        itemname.textContent = itemnameval;


        const itemprice = document.createElement("data");

        itemprice.setAttribute("class","itemprice");

        const itempriceval = this.getAttribute("price");

        itemprice.textContent = itempriceval;



        item.appendChild(itemname);

        item.appendChild(itemprice);


        const style = document.createElement('style');
    

    style.textContent =     `
    
    .itemprice{

        

        text-align: right;
    }
    .minigrid{


        display: grid;
    
        
    
    grid-template-columns: 200px 200px;
    
    padding-left: 10px;
    padding-right: 10px;
    
    padding-top:10px;
    
    }
    
    `;
shadow.appendChild(style);

        shadow.appendChild(item);
    }
}

STEP4: While you append custom elements to the shadow root , you can also create custom attributes for the new element , retrieve their values and assign it to your html elements.

In the above code , notice the below lines:

 const itemnameval = this.getAttribute("name");

        itemname.textContent = itemnameval;

Here “name” is an attribute automatically attributed with the custom element we are creating.

You can retrieve its value and assign it to one of the “data” elements “itemname” which is attached to the shadow root.

STEP5: Once your custom element class is ready , define the custom tag outside the class like this :

customElements.define('menu-item',MenuItem);

The object customElements belongs to window object.

So the above customElements object can also be referred as window.customElements.

Also the custom tag should have the symbol “-” , else browser will complain that it is invalid.

This is used to distinguish custom HTML elements from the standard elements.

That’s it!

Now you can use the tag <menu-item></menu-item> instead of creating the list manually with the custom styling.

You just pass the name and price through attributes to the above tag.

Below is the transformation of the list items code before and after using custom tag:

Before:
             <li class="minigrid"> 
<data class="itemname" id="itemname">Thoum(S/M/L)   </data> 
<data class="itemprice" id="itemprice" >Rs.40/65/130</data> 
</li> 

<li class="minigrid"> 
<data class="itemname" id="itemname">Hummus(S/M/L)</data>
 <data class="itemprice" id="itemprice">Rs.50/95/130</data> 
</li> 

<li class="minigrid">
 <data class="itemname" id="itemname">chicken Hawaiian Salad</data> <data class="itemprice" id="itemprice">Rs.150</data>
 </li> 

 After:
            <menu-item name="Thoum(S/M/L)" price ="Rs.40/65/130"></menu-item>
             <menu-item name="Hummus(S/M/L)" price ="Rs.50/95/130"></menu-item>
             <menu-item name="chicken Hawaiian Salad" price ="Rs.150"></menu-item>

Here is the entire file:

class MenuItem extends HTMLElement{


    constructor(){


        super();


        const shadow = this.attachShadow({mode:'open'});


        const item = document.createElement("li");

        item.setAttribute("class","minigrid");



        const itemname = document.createElement("data");

        itemname.setAttribute("class","itemname");

        const itemnameval = this.getAttribute("name");

        itemname.textContent = itemnameval;


        const itemprice = document.createElement("data");

        itemprice.setAttribute("class","itemprice");

        const itempriceval = this.getAttribute("price");

        itemprice.textContent = itempriceval;



        item.appendChild(itemname);

        item.appendChild(itemprice);


        const style = document.createElement('style');
    

    style.textContent =     `
    
    .itemprice{

        

        text-align: right;
    }
    .minigrid{


        display: grid;
    
        
    
    grid-template-columns: 200px 200px;
    
    padding-left: 10px;
    padding-right: 10px;
    
    padding-top:10px;
    
    }
    
    `;
shadow.appendChild(style);

        shadow.appendChild(item);
    }
}

customElements.define('menu-item',MenuItem);

I defined this in a seperate file name “customelements.js” and imported it in my HTML file using the below code:

<script type="text/javascript" src="customelements.js"></script>

Refer the HTML spec for exploring the full power of custom elements:

https://html.spec.whatwg.org/#custom-elements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s