Search code examples
csscustom-elementcss-counter

Using CSS counter-reset in :host declaration of a Custom Element


[run the code snippet]

I want my DIV number display to start at 0 ,
so I want to start the counter at -1 using: counter-reset : square -1;

Yet, this setting is ignored when used in :host

counter-reset works fine when all DIVs are wrapped in an extra parentDIV (with counter-reset on that parent DIV)
But I prefer not to use this work-around as it requires lots more code in my final application.

Is it possible at all to use counter-reset in :host ???

window.customElements.define('game-toes', class extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'})
     .appendChild(document.querySelector('#Styles').content.cloneNode(true));
  }
});
<TEMPLATE id="Styles">
  <STYLE>
      :host {
        display: grid;
        grid-template: repeat(3, 1fr) / repeat(3, 1fr);
        grid-gap: .5em;
        counter-reset: squarenr -1; /* does not reset to -1 */
      }
      DIV {
        font-size:3em;
        display:flex;
        justify-content:center;
        background:lightgrey;
        counter-increment: squarenr;
      }
      #_::before {
        background:lightgreen;
        content: counter(squarenr);
      }
      #X::after,
      #O::after {
        content: attr(id);
      }
  </STYLE>
  <DIV id=_></DIV><DIV id=_></DIV><DIV id=X></DIV>
  <DIV id=_></DIV><DIV id=X></DIV><DIV id=_></DIV>
  <DIV id=O></DIV><DIV id=O></DIV><DIV id=X></DIV>
</TEMPLATE>
<game-toes></game-toes>


qomponents


Solution

  • :host is a pseudo-class that selects the shadow host element (that is: the HTML element that hosts the Shadow DOM), not the shadow root.

    As a consequence, a counter-reset will affect the counter in the main DOM tree, not the counter in the Shadow DOM (see the example below).

    If you want to set a CSS counter in the Shadow DOM root, you could use the :first-of-type selector:

     div:first-of-type {
        counter-reset: squarenr -1
     }
    

    window.customElements.define('game-toes', class extends HTMLElement {
      constructor() {
        super();
        this.attachShadow({mode: 'closed'})
         .appendChild(document.querySelector('#Styles').content.cloneNode(true));
      }
    });
    div::after {
      counter-increment: squarenr ;
      content: counter( squarenr ) ;
    }
    <TEMPLATE id="Styles">
      <STYLE>
          :host {
            display: grid;
            grid-template: repeat(3, 1fr) / repeat(3, 1fr);
            grid-gap: .5em;
            counter-reset: squarenr -1; 
          }
          :host > div:first-of-type {
            counter-reset: squarenr -1; 
            color: red;
          }
          DIV {
            font-size:2em;
            display:flex;
            justify-content:center;
            background:lightgrey;
            counter-increment: squarenr  ;
          }
          #_::before {
            background:lightgreen;
            content: counter(squarenr);
          }
          #X::after,
          #O::after {
            content: attr(id);
          }
      </STYLE>
      <DIV id=_></DIV><DIV id=_></DIV><DIV id=X></DIV>
      <DIV id=_></DIV><DIV id=X></DIV><DIV id=_></DIV>
      <DIV id=O></DIV><DIV id=O></DIV><DIV id=X></DIV>
    </TEMPLATE>
    <div>squarenr=</div><game-toes></game-toes><div>squarenr=</div>