stencil-constructible-style
v2.0.0
Published
A Stencil decorator for dynamically creating constructible stylesheets.
Downloads
12
Maintainers
Readme
stencil-constructible-style
What is it?
stencil-constructible-style
is a decorator for Stencil components that gives you the ability to add dynamic styles as constructible stylesheets, with a fallback for non-supported browsers.
* Requires @stencil/[email protected] or later
Why? Don't Stencil do this already?
Yes, for your .css
-files they do. But what if your style depends on some variables? Then you end up having to write <style>
tags in your render
function.
Or if you host your code from a CDN, such as unpkg.com? Then the assets folder will not be on a relative URL, as it would be relative to the website your web components are being used on (getAssetPath
to the rescue!).
How to use it?
import { Component, Element, getAssetPath } from "@stencil/core";
import { ConstructibleStyle } from "stencil-constructible-style";
@Component({...})
export class MyComponent {
// A componentWillLoad is required, even if it's empty.
componentWillLoad() {}
@ConstructibleStyle() styles = `
.classIcon { background: url(${ getAssetPath("../assets/class-icon.png") }); }
`;
}
You can also set the ConstructibleStyle
to a function in case you want to avoid running it for every instance of the component.
The above would be:
@ConstructibleStyle() styles = () => `
.classIcon { background: url(${ getAssetPath("../assets/class-icon.png") }); }
`;
Caching
The stylesheet, once constructed, is cached statically per component and therefore won't be recreated when new instances of the component are created. This could be a problem if you have variables that affects that stylesheet. That's where the cacheKeyProperty
option comes in.
import { Component, Element, getAssetPath } from "@stencil/core";
import { ConstructibleStyle } from "stencil-constructible-style";
@Component({...})
export class MyComponent {
@Prop() myClass: string;
// A componentWillLoad is required, even if it's empty.
componentWillLoad() {}
@ConstructibleStyle({ cacheKeyProperty: "myClass" }) styles = `
.classIcon { background: url(${ getAssetPath(`../assets/${ this.myClass }-icon.png`) }); }
`;
}
ConstructibleStyle
runs after your componentWillLoad
, so if you have multiple variables that affects your styles and want them all to be relevant in your key, you can prepare a unique key during componentWillLoad
.
@Component({...})
export class MyComponent {
@Prop() myClass: string;
@Prop() mode: string;
private cacheKey: string;
componentWillLoad() {
this.cacheKey = `${ this.myClass }-${ this.mode }`;
}
@ConstructibleStyle({ cacheKeyProperty: "cacheKey" }) styles = `
.classIcon { background: url(${ getAssetPath(`../assets/${ this.myClass }-${ this.mode }-icon.png`) }); }
`;
}
Why is componentWillLoad
required?
StencilJS does heavy optimizations. If none of your components have a componentWillLoad
StencilJS will simply remove the code that calls that function from the output, and hence @ConstructibleStyle
will never execute. Since the decorator has no knowledge about other components however, a warning will be issued to the console if a component that uses @ConstructibleStyle
does not have a componentWillLoad
.
What about browsers that don't suppot Constructible Stylesheets?
If new CSSStyleSheet()
can't be called (same check that Stencil itself uses), the decorator will fall back to render a <style>
element to the end of your rendered output.