goenning
goenning

Reputation: 6654

How to prevent flickering with web components?

Consider a simple web component

class TimeAgo extends HTMLElement {
    constructor() {
        super();
        this.innerHTML = '2 hours ago'
    }
}

customElements.define('time-ago', TimeAgo);

Being used like this

This post was created <time-ago datetime="2020-09-26T11:28:41.9731640+01:00">September 26th</time-ago>

When the page renders, the browser will first write "September 26th" and right after that switch to "2 hours ago".

Is there a way to prevent this from happening? I'd much prefer to display "2 hours" on first paint.

The JS file is loaded through a CDN, moving the script tag up and down the response didn't change anything.

Upvotes: 6

Views: 2019

Answers (2)

But is your element defined and its script executed before that part of the DOM is parsed?

Code below displays 1A because the 1 is injected into the DOM before content A is parsed.

So if you don't want a FOUC leave <time-ago> content empty.. or maybe blur it with CSS

<script>
  window.onload = () => console.log("onload");
  customElements.define( "my-element", class extends HTMLElement {
      constructor() {
        super();
        console.log("constructor");
      }
      connectedCallback() {
        console.log("connectedCallback");
        this.innerHTML = "1";
      }
    }
  );
</script>
<my-element>A</my-element>
<script>
  console.log("end DOM");
</script>

Upvotes: 4

Isaac
Isaac

Reputation: 12884

One of the possible solution I can think of is to enable shadow-dom

class TimeAgo extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
        this.innerHTML = '2 hours ago'
    }
}

customElements.define('time-ago', TimeAgo);

By defining your web component to be shadow dom, you can change the content even before it's attached to the DOM.

Upvotes: 1

Related Questions