DEV Community

Cover image for The <site-head> Web Component you never see in F12 Dev Tools
Danny Engelman
Danny Engelman

Posted on • Updated on

The <site-head> Web Component you never see in F12 Dev Tools

I have a family of HTML websites that all have similar design, but different titles, description and SEO keywords

For each and every site I need to add

<meta name="title" content="Title siteA">
<meta name="description" content="Description siteA">
<!-- and many more tags -->
Enter fullscreen mode Exit fullscreen mode

I want a single location to update all sites meta data

Traditionally you would solve this with an SSR (Server Side Rendering) solution.

But my source is bare HTML, not created by any Server script.

and SSR can not read any Client Side settings, like URL Parameters, sessionStorage or localStorage.


a CSR (Client Side Rendering) Web Component : <site-head>

Web Components can create DOM elements.
Then one Web Component can create all <meta> DOM elements.

⚠️ and after it has done the work, remove itself from the DOM

  <head>
    <site-head site="A">Description of this site</site-head>
  </head>  
Enter fullscreen mode Exit fullscreen mode

The JavaScript required is very simple:

customElements.define("site-head", class extends HTMLElement {
  connectedCallback() {
    // append all <meta> tags to document.head
    this.remove();
  }
})
Enter fullscreen mode Exit fullscreen mode

It is magic, <site-head> was never in the <head>

If you do not remove the <site-head> element with this.remove(),

addendum from comments:

you will notice some (maybe) unexpected behaviour:

Although the Web Component is defined in the <head> of the HTML document.

The element closes the head and then starts the body. This means that any following element that could live in either the head of body will end up in the body! (the </head> will be ignored, and the <body> will be merged with the body implicitly opened by the site-head).

connectedCallback(){
    console.log( this.parentNode );
}
Enter fullscreen mode Exit fullscreen mode

will log <body> not <head>




This is because <site-head> is not a valid HEAD Element: meta, link, title, style, script, noscript, base

The Web Component is correctly executed after being placed in the <body> by the Browser.


This is very annoying when you create a CSR <css-grid> that applies a CSS grid to the <body> tag, because <site-head> now is a grid element, until it is removed.

And maybe you are doing async stuff in <site-head>, so the this.remove() executes late.


Vanish! Go away! Get out of that <body>!

Because Web Components trigger the disconnectedCallback when removed from the DOM.

The Web Component can immediately be removed from the <body> in the connectedCallback

⚠️ The element and all its attributes and content is still available in the disconnectedCallback

⚠️ But the element is no longer in the DOM

customElements.define("site-head", class extends HTMLElement {
  connectedCallback() {
    this.remove();
  }
  disconnectedCallback() {
    console.log( this ); // <site-head>
    console.log( this.parentNode ); // null
    // append all <meta> tags to document.head
  }
})
Enter fullscreen mode Exit fullscreen mode

All <site-head> Web Component code required

Here is code to get you started

You can get inspiration from:


Challenge

Now it is your turn to create any gameboard with a CSR <css-grid> Web Component:

<css-grid background="khaki" 
          files="ABCDEFGH" 
          ranks="12345678" 
          gap="0" 
          colors="#f0e9c5/#b58863" 
          labels="center"></css-grid>
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
tbroyer profile image
Thomas Broyer

Small note: the element is not moved to the body, it closes the head and then starts the body. This means that any following element that could live in either the head of body will end up in the body! (the </head> will be ignored, and the <body> will be merged with the body implicitly opened by the site-head).

Collapse
 
dannyengelman profile image
Danny Engelman

Good description, I added it to the text, tnx