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