Using CSS @property inside shadowRoot (web components) workaround
Another adventure using lit and another little ‘Gotcha’ I picked up from the good folks on the lit Discord.
This one was niche enough I felt it was worth documenting.
I was trying to use the new CSS @property
inside a lit/web component and couldn’t figure out what I was doing wrong. In this case I was making a single element loader, using a conical-gradient. The idea was that I would run an animation that made use of a registered custom property to animate the conical gradient. Here is an example outside of a web component.
See the Pen Super Easy Pie chart loader by Ben Frain (@benfrain) on CodePen.
And for copy and paste goodness, here is the CSS:
@property --countdown {
syntax: "<percentage>";
initial-value: 100%;
inherits: false;
}
@keyframes deplete {
100% {
--countdown: 0%;
}
}
.thing {
height: 100px;
width: 100px;
border-radius: 50%;
animation: deplete 10s linear;
background-image: conic-gradient(
hotpink 0,
pink var(--countdown),
transparent var(--countdown)
);
}
I have set the @property name to --countdown
, set it to use percentage as the syntax, given an initial value, then created a set of @keyframes
to take the value from the default 100%, to 0%.
Then I set my conical-gradient to have a hard lined edge that is at the same value as the countdown, so that when the animation runs, my conical-gradient gets animated giving me the Pie Timer effect.
However, sticking this in a web component does not work. The reason is, that @property
does not work inside the CSS of a shadowRoot
.
To get things working in Web Component land, this requires installing the @property in the document, and here is the way you can do that:
import { html, css, LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";
@customElement("simple-greeting")
export class SimpleGreeting extends LitElement {
static {
console.log("install document styles");
const documentStyles = css`
@property --panelCountdown {
syntax: "<percentage>";
initial-value: 100%;
inherits: false;
}
`;
document.adoptedStyleSheets.push(documentStyles.styleSheet);
}
static styles = css`
@keyframes deplete {
100% {
--panelCountdown: 0%;
}
}
.thing {
height: 100px;
width: 100px;
border-radius: 50%;
animation: deplete 10s linear;
background-image: conic-gradient(
hotpink 0,
pink var(--panelCountdown),
transparent var(--panelCountdown)
);
}
`;
render() {
return html`<div class="thing"></div>`;
}
}
With that installed via document.adoptedStyleSheets
the @property is registered and ready to use. You can see this over on the lit.dev playground: https://lit.dev/playground/#gist=f4251bf213f8cbdb9d68a406ff50cd13
Leave a Reply