1

The following code works fine with Firefox, but is buggy with Chrome.

I have a tst-list web component. In it is a tst-add component, which looks like a plus icon, with id ADD. When one clicks the add button (#ADD plus icon), it will create a tst-wrapper component and add it to the tst-list component. Each tst-wrapper item will show a PREV and NEXT button if appropiate, for re-ordering. If an items is first, it will NOT show a PREV, if the items is last, it will not show a NEXT button.

NOT WORKING RESULT

This is what the output looks like (after clicking #ADD 5 times), when NOT working (the NEXT button never shows):

enter image description here

WORKING RESULT

And when working:

enter image description here

I have identified a styling issue and a hack to make it work, detailed in the following 2 sections:

STYLING ISSUE

This styling of the ADD icon makes last-of-type not work. So if I remove this styling, it works, In particular the CSS selector is the issue. However I would like this styling:

:host(:active) #ICON {
   fill: red;
}

HACK

If one hides then shows the previous last-of-type element, it seems to give the CSS a kick and it renderes correctly, in the code example, uncommenting the hack as shown below will make it work:

                // --- START OF HACK
                child.previousElementSibling.style.display="none"
                setTimeout(() =>child.previousElementSibling.style.display="block");
                // --- END OF HACK

MINIMAL REPRODUCIBLE EXAMPLE

customElements.define('tst-add', class extends HTMLElement {
  constructor() {
    super().attachShadow({mode: 'open'})
           .append(document.getElementById('TEMPLATE_add').content.cloneNode(true));
  }
});
customElements.define('tst-wrapper', class extends HTMLElement {
  constructor() {
    super().attachShadow({mode: 'open'})
           .append(document.getElementById('TEMPLATE_wrapper').content.cloneNode(true));
  }
});

const WRAPPER_LOCAL_NAME = 'tst-wrapper';
customElements.define('tst-list', class extends HTMLElement {
  constructor() {
    super().attachShadow({mode: 'open'})
           .append(document.getElementById('TEMPLATE_list').content.cloneNode(true));
    this.shadowRoot.getElementById('ADD')
        .addEventListener('click', (evt) => this.addChild(evt));
  }
  addChild(evt) {
    const child = document.createElement(WRAPPER_LOCAL_NAME);
    child.textContent = "NEW"
    this.appendChild(child);
    if (child.previousElementSibling) {
      // --- START OF HACK
      //child.previousElementSibling.style.display="none"
      //setTimeout(() =>child.previousElementSibling.style.display="block");
      // --- END OF HACK
    }
  }
});
<template id="TEMPLATE_add">
  <style>
    :host(:active) #ICON {
       fill: red;
  }
  </style>
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000" draggable="false" id="ICON">
      <path d="M0 0h24v24H0z" fill="none"></path>
      <path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path>
  </svg>
</template>
<template id="TEMPLATE_wrapper">
  <style>
    :host(:first-of-type) #PREV,
    :host(:last-of-type) #NEXT {
        display: none;
  }
  </style>
  <div id="CONTAINER">
      <slot></slot>
      <button id="PREV"   type="button">PREV</button>
      <button id="NEXT"   type="button">NEXT</button>
  </div>
</template>
<template id="TEMPLATE_list">
  <div id="CONTAINER">
      <div id="LIST" part="list">
          <slot id="SLOT"></slot>
      </div>
      <tst-add id="ADD"></tst-add>
  </div>
</template>

<tst-list></tst-list>

Using Chrome v109

1
  • I've played around with your code for a while, but also can't spot the issue. I thought at first that it might be related to the fact that there might be a problem with non-unique IDs (even though they're properly scoped). I tried using class attributes instead, but that doesn't solve the issue. Give it a little more time so better minds than mine can maybe chime in, but otherwise it indeed looks like a Chrome bug. Commented Feb 24, 2023 at 1:16

1 Answer 1

0

Labeling it a Chrome bug is a bit pointless. This CSS has been around for ages. Very unlikely you are now finding bugs.

I presume you want this behaviour.

Don't know when exactly (and I am not going to retrace my deletions), but pruning your code solved it

class MYHTMLElement extends HTMLElement {
  constructor() {
    super().attachShadow({mode:'open'}).append(document.getElementById(this.nodeName).content.cloneNode(true));
  }
}
 
customElements.define('tst-wrapper', class extends MYHTMLElement{});

customElements.define('tst-list', class extends MYHTMLElement {
  constructor() {
    super();
    this.onclick = (evt) => this.addChild(evt);
  }
  addChild(evt) {
    const child = document.createElement("tst-wrapper");
    child.textContent = "NEW";
    this.append(child);
  }
});
<template id="TST-WRAPPER">
  <style>
    :host{display:block}
    :host(:first-of-type) #PREV,
    :host(:last-of-type) #NEXT {
        xdisplay: none;
        background:red;
  }
  </style>
  <slot></slot>
  <button id="PREV"   type="button">PREV</button>
  <button id="NEXT"   type="button">NEXT</button>
</template>

<template id="TST-LIST">
  <div id="LIST" part="list">
      <slot id="SLOT"></slot>
  </div>
  <button>ADD</button>
</template>

<tst-list></tst-list>

Update 1 - Real Minimal Reproducible Example Code (in Chrome)

<style>     
  div:last-of-type { background:red }
</style>
<section id="LIST"/>
<script>
LIST.attachShadow({mode: 'open'})
    .innerHTML=`<style>:host(:active) button{}</style><slot></slot><button>ADD</button>`;
LIST.onclick=()=>LIST.appendChild(document.createElement('div')).innerHTML="DIV";
</script>

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks Danny, however when creating the example, I saw that when I did not use the SVG as a ADD button, the behaviour was the correct, hence I added the SVG to the minimal reproducible example. Also if the add icon is not styled when active, it also solves the issue.
I am not going to investigate; probably something CSS block related
The code runs fine with Firefox, just not with Chrome. Going to file a bug. Yes CSS has been around, but Chrome changes fast/adds features often, opening lots of space for bugs.
How does this answer the question? Unless you can point out specific issues in OP's code, how is labeling it as a Chrome bug pointless? And if that's pointless, what's the point of saying: sure, you're code doesn't work, but here's some different code that does work? Especially when OP has already clearly pointed out in their question what piece of CSS triggers the unexpected behavior, and how to work around it.
@RobbyCornelissen, have you seen his other questions? Have you read all the replies I gave Run over the past years? Yes, the tone of voice may look a bit blunt. My hope was (and is) he is not going to post Chrome Bug in more question titles. The fact that Chrome and Firefox behave different doesn't mean its a Chrome bug. In the past years I have found multiple bugs in Firefox Web Component behavour, which Mozilla has fixed. So Yes, it can be a bug, and No, we don't know which browser is wrong.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.