Photo by Michele Blackwell on Unsplash
So you are working on your Web Components and soon enough you realize they are really good at encapsulating stuff. That's the goal. Check out this Web Component:
There are 2 p
tags. On the one hand, we have one declared entirely inside the Web Component, the one with inner content
:
...
render() {
return html`
<div>
<p>Inner content</p>
</div>
<div>
<slot></slot>
</div>
`
}
...
And on the other hand, we have a p
tag declared as part of the body which is moved in as part of the slot
functionality of our Web Component:
...
<div>
<my-element>
<p>Slotted content</p>
</my-element>
</div>
...
We have a reset rule declared for p
tags:
p {
margin: 0;
}
As you can see, the p
tag declared outside gets the style applied and moved in without margins. However the p
declared inside is "protected" from the page styles and so it gets general treatment: user agent styles. That's why they look different.
How do we solve this problem?
So far, I think there's only one way to solve it: declaring the reset styles within the Web Component as well. In our Web Component, the styles
static class getter will looke like so:
static get styles() {
return css`
div {
border: 1px solid red;
}
p {
margin: 0;
}
`;
}
Here is our updated pen:
Solved, right? Well, it works, but this is far from optimal. Firstly, we should have this reset styles outside the Web Component itself, that way you can share the reset styles amongst other components. Something like this:
...
const resetStyles = () => css`
p {
margin: 0;
}
`
...
static get styles() {
return [
resetStyles(),
css`
div {
border: 1px solid red;
}
`
]
}
...
But secondly and more importantly, as a good rule of thumb in software development: never have the same stuff repeated.
We still have a reset styles stylesheet, let's call it reset.css
, and an object with the reset styles which is returned by resetStyles()
. That means we have the reset styles both as a LitElement's css object and as an independent stylesheet.
The cool thing would be to have the reset stylesheet and that's it.
How do we do that?
We can process the stylesheet and create a CSS object, just how LitElement understands them. There are many ways to do this, I'll use Rollup for my example.
Let's Rollup! Using a simple config like this:
import litcss from 'rollup-plugin-lit-css'
export default {
input: 'src/reset.css.js',
plugins: [
litcss({ uglify: true })
],
output: {
file: 'reset.css.lit.js',
format: 'es'
}
}
Here we're using Rollup's great rollup-plugin-lit-css
plugin by
Our src/reset.css.js
is super simple:
export { default } from '../reset.css'
That's it!
Now we can use it in LitElement:
...
import reset from "./reset.css.lit.js";
const resetStyles = () => reset
...
We'll need something more advanced than CodePen for this, let's use Glitch and voilรก! Now we only have one place where our reset styles are written (reset.css
). Check it out:
Remember in this example the file reset.css.lit.js
has been created by Rollup.
Minireset.css
A similar approach than the one just explained I used to improve minireset.css in this PR and provide an additional LitElement compatible file other people can use in LitElement Web Components. minireset.css is a great (and very tiny) reset you can use at production sites, which I recommend, check it out:
https://jgthms.com/minireset.css/
Install it on your project:
npm install --save minireset.css
Then in LitElement Web Components where you want to have the styles reset, import them:
import { minireset } from 'minireset.css/minireset.css.lit.js'
And then either use them as part of an array CSS result, like so:
static get styles() {
return [
minireset,
... your other styles
]
}
or directly in your styles:
static get styles() {
return css`
${minireset}
... your other styles
`
}
That's a wrap!
I hope you found this article useful. Questions and feedback are very welcome ๐
Top comments (1)
Great job on the PR for minireset! Using this approach while we implement the rollup css plugin for all of our components in the library. Thanks!