Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use CSS "target" selector in web components using lit html

I am using lit html to create custom web components in my project. And my problem is when I try to use the CSS target selector in a web component it wont get triggered, but when I am doing it without custom component the code works perfectly. Could someone shed some light to why this is happening and to what would be the workaround for this problem? Here is my code:

target-test-element.js:

import { LitElement, html} from '@polymer/lit-element';

class TargetTest extends LitElement {

  render(){
    return html`
      <link rel="stylesheet" href="target-test-element.css">
        <div class="target-test" id="target-test">
        <p>Hello from test</p>
    </div>
    `;
  }
}
customElements.define('target-test-element', TargetTest);

with the following style:

target-test-element.css:

.target-test{
    background: yellow;
}

.target-test:target {
    background: blue;
}

and I created a link in the index.html:

index.html(with custom component):

<!DOCTYPE html>

<head>
 ...
</head>

<body>
    <target-test-element></target-test-element>
    <a href="#target-test">Link</a>
</body>

</html>

And here is the working one:

index.html(without custom component)

<!DOCTYPE html>
<head>
    ...
</head>
<body>
    <a href="#target-test">Link</a>
    <div class="target-test" id="target-test">
        Hello
    </div>
</body>
</html>
like image 458
Tibor Fekete Avatar asked Oct 24 '25 06:10

Tibor Fekete


2 Answers

LitElement uses a Shadow DOM to render its content. Shadow DOM isolates the CSS style defined inside and prevent selecting inner content from the outide with CSS selectors. For that reason, the :target pseudo-class won't work.

Instead, you could use a standard (vanilla) custom element instead of the LitElement.

With no Shadow DOM:

class TargetTest extends HTMLElement {
  connectedCallback() {
    this.innerHTML = `
      <div>
        <span class="test" id="target-test">Hello from test</span>
      </div>`
  }
}
customElements.define('target-test-element', TargetTest)
.test { background: yellow } 
.test:target { background: blue }
<target-test-element></target-test-element>
<a href="#target-test">Link</a>

Alternately, if you still want to use a Shadow DOM, you should then set the id property to the custom element itself. That supposes there's only one target in the custom element.

class TargetTest extends HTMLElement {
  connectedCallback() {
    this.attachShadow( { mode: 'open' } ).innerHTML = `
      <style>
        :host( :target ) .test { background-color: lightgreen }
      </style>
      <div>
        <span class="test">Hello from test</span>
      </div>`
  }
}
customElements.define('target-test-element', TargetTest)
<target-test-element id="target-test"></target-test-element>
<a href="#target-test">Link</a>
like image 59
Supersharp Avatar answered Oct 25 '25 19:10

Supersharp


Bit in late, i've experienced the same problem! So i'm following one of two paths:

  1. Use a lit element but without the shadowDOM, to do that in your Lit element call the method createRenderRoot()
createRenderRoot () {
    return this
  }
  1. Instead handle the CSS logic with :target i'm handling the attribute on the element (easy to do with Lit) eg. active and use it in CSS:
element[active] {
   /* CSS rules */
}

These are my solutions for the moment! Hope it's help...

like image 35
cicciosgamino Avatar answered Oct 25 '25 19:10

cicciosgamino