'litelement - how to compute style based on property or attribute values
I'm following the LitElement guide here but can't seem to get my custom element's style values calculated based on it's attribute.
I want my element to be written in one of following ways:
<my-element data="some values" darkmode></my-element>
<my-element data="some values"></my-element>
I want to style the element's background and text colour depending on whether dardmode
attribute is set or not.
In my LitElement class, I created a corresponding property and also initialized it. But, in the static style, this.darkMode
is always returning false
. I think I'm missing something here but not sure what:
class MyElement extends LitElement {
static get properties() {
return {
data: { type: String },
darkMode: { type: Boolean }
};
}
static get styles() {
const background_color = this.darkMode ? css`#000` : css`#fff` ;
const text_color = this.darkMode ? css`#fff` : css`#333333`;
return [
css`
:host {
display: block;
}
.data-container {
font-family: "Roboto",-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
background-color: ${background_color} !important;
color: ${text_color} !important;
}`
];
constructor() {
super();
this.data = "";
this.darkMode = false;
}
render() {
return html`
<div class="data-container">
<p>${this.data}</p>
</div>
`;
}
}
customElements.define('my-element', MyElement);
Solution 1:[1]
In this code:
static get styles() {
const background_color = this.darkMode ? css`#000` : css`#fff` ;
// ...
…styles
is a static method, so within it this
refers to the MyElement class itself, so this.darkMode
is the darkMode
property of MyElement and not the darkMode
property of any instance of MyElement. Of course, MyElement.darkMode
is always undefined
, so you always get the "light" styles.
A different and more maintainable approach would be to "reflect" the darkMode
property to an attribute of the element with the reflect: true
option and then use the CSS attribute selector [dark-mode]
to override the "light" styles, e.g.:
.data-container {
background-color: #fff;
color: #333;
}
:host([dark-mode]) .data-container {
background-color: #000;
color: #fff;
}
You can see this working in the below snippet:
const { LitElement, css, html } = litElement;
class MyElement extends LitElement {
static get properties() {
return {
data: { type: String },
darkMode: {
type: Boolean,
reflect: true,
attribute: 'dark-mode',
},
};
}
static get styles() {
return css `
:host {
display: block;
}
.data-container {
background-color: #fff;
color: #333;
}
:host([dark-mode]) .data-container {
background-color: #000;
color: #fff;
}
`;
}
constructor() {
super();
this.data = "";
this.darkMode = false;
}
render() {
return html `
<div class="data-container">
<p>${this.data}</p>
</div>
`;
}
}
customElements.define('my-element', MyElement);
<script src="https://bundle.run/[email protected]"></script>
<my-element data="some dark values" dark-mode></my-element>
<my-element data="some light values"></my-element>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |