Skip to content

Styles

There are several ways to style a Van Element.

WARNING

The Shadow DOM gets in the way very often, and is even one of the main reasons Web Components face skepticism from the Web development community.

If you don't want isolated styles, you can just use Van Elements without the Shadow DOM!

Inline styles

The simplest way to style Van Elements is inline styles

ts
define("inline-styles", () => p({ style: "color:red" }, "I am red"));
html
<inline-styles></inline-styles>
Result

Inline styles are often frowned upon for good reasons. However, in an isolated environment like the Shadow DOM, they can work really well if complex styling is not needed.

style tag

If you want more complex styling, using a style tag is a very good option. The reason it works is because the Shadow DOM will isolate these styles from the rest of the DOM so it won't leak out!

TIP

You can use the CSS selector ::slotted to apply specific styles to the slotted element.

ts
define("style-tag", () => [
  style(`
    p {
      color: red;
    }
    ::slotted(p) {
      color: orange;
    }
  `),
  slot(),
  p("Paragraph in Shadow DOM"),
]);
html
<style-tag><p>Paragraph in the slot</p></style-tag>
<p>Paragraph in normal DOM</p>
Result

Paragraph in the slot

Paragraph in normal DOM

Adopted stylesheets

This method revolves around creating a CSSStyleSheet and add it to the Shadow Root.

ts
define("adopted-style", ({ $this }) => {
  const css = new CSSStyleSheet();
  css.replaceSync(`
    * {
      color: orange;
    }
  `);
  $this.shadowRoot?.adoptedStyleSheets.push(css);
  return p(slot());
});
html
<adopted-style>Adopted styles!</adopted-style>
ResultAdopted styles!

WARNING

This method currently lacks testing and support. It is also a bit more awkward to use, so the style tag method is preferred.

However it has benefits, the major one being that you can merge two style sheets without conflicts or share them between components.

If you would like more support for this, feel free to create an issue or even to contribute 🙂