Search code examples
csslit-elementlit

passing and apply css class from outside to lit element


Hello I'm trying to pass css from outside and apply to lit-element. I did with set property on lit-element where the element should apply the style from this property

The problem is, lit property only read the props as string and the style does not effect on the lit-element.

Here is the lit code

import { LitElement, html, css } from "lit";

export class MyElement extends LitElement {
  static properties = {
    classes: { type: String }
  };

  static styles = css`
    .root {
      background-color: aliceblue;
      color: darkgreen;
    }
  `;
  css;
  render() {
    return html`
      <div class="root ${this.classes}">
        <slot></slot>
        <p>Hello from my template.</p>
      </div>
    `;
  }
}
customElements.define("my-element", MyElement);

I used vue to consume lit-element I created style ".myStyle" where this class will be passed to lit-element property with name as classes the code looks like this

<template>
  <div id="app">
    <my-element classes="myStyle">
      <p>slot of my element</p>
    </my-element>
  </div>
</template>

<script>
import "./MyElement.js";

export default {
  name: "App",
};
</script>


<style scoped>
.myStyle {
  display: flex;
}
my-element > .root {
  color: red;
}
</style>

I also cannot use descended style into lit element, but I noticed the descend style only affects 1 level children of the lit element.

Is it posibble to pass style directly from host to lit element and take style effect from host to lit-element?

Thank you.


Solution

  • I believe a sound approach would be to implement a CSS "API" of sorts leveraging the use of attributes; it would look something like this.

    :host([flex]) {
       display: flex
    }
    

    And then your markup implementation would look something like this.

    <my-element flex>
      <p>slot of my element</p>
    </my-element>
    

    The benefits this type of implementation provides is that it allows you to be very intentional of your web component design by creating a documentable API for consuming developers to leverage, via attributes, to "style" your component.

    You could also leverage attribute values to provide more flexibility.

    :host([color='red']) {
       color: red;
    }
    :host([color='blue']) {
       color: blue;
    }
    :host([color='orange']) {
       color: orange;
    }
    

    And the markup would look like this.

    <my-element color="red">
      <p>slot of my element</p>
    </my-element>
    
    <my-element color="blue">
      <p>slot of my element</p>
    </my-element>
    
    <my-element color="orange">
      <p>slot of my element</p>
    </my-element>
    

    Keep in mind one of the main focuses of shadow roots is to provide CSS encapsulation that prevents intentional or unintentional mutation of the component (the reason you are experiencing challenges styling a web component from the outside).

    The most "scalable" solution I have observed is to be very intentional on the API design of your component with regard to what "styling" you will and will not support in the package.