DEV Community

Cover image for Resetting styles inside Lit-Element Web Components
Daniel Vivar
Daniel Vivar

Posted on

Resetting styles inside Lit-Element Web Components

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>
  `
}
...
Enter fullscreen mode Exit fullscreen mode

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>
...
Enter fullscreen mode Exit fullscreen mode

We have a reset rule declared for p tags:

p {
  margin: 0;
}
Enter fullscreen mode Exit fullscreen mode

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;
    }
  `;
}
Enter fullscreen mode Exit fullscreen mode

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;
      }
    `
  ]
}
...
Enter fullscreen mode Exit fullscreen mode

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'
  }
}
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

That's it!

Now we can use it in LitElement:

...
import reset from "./reset.css.lit.js";
const resetStyles = () => reset
...
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Then in LitElement Web Components where you want to have the styles reset, import them:

import { minireset } from 'minireset.css/minireset.css.lit.js'
Enter fullscreen mode Exit fullscreen mode

And then either use them as part of an array CSS result, like so:

static get styles() {
  return [
    minireset,
    ... your other styles
  ]
}
Enter fullscreen mode Exit fullscreen mode

or directly in your styles:

static get styles() {
  return css`
    ${minireset}

    ... your other styles
  `
}
Enter fullscreen mode Exit fullscreen mode

That's a wrap!

I hope you found this article useful. Questions and feedback are very welcome ๐Ÿ™‚

Top comments (1)

Collapse
 
mrseabass profile image
Sebastian Alvarez

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!