emotion-js/emotion

Use class name combination for nested styled component

zhangbenber opened this issue · 0 comments

The problem

Consider that we have a styled component:

const Button = styled.button({ color: 'blue' });

And we want to wrap another styled for the component, overriding some of it's style:

const BigButton = styled(Button)({ fontSize: '1.5em' });

When we render both of the components, we get:

<style>.hash-for-button { color: blue }</style>
<style>.hash-for-big-button { color: blue; font-size: 1.5em }</style>
<button class="hash-for-button" />
<button class="hash-for-big-button" />

As we see, we are cloning any styles defined on Button (color: blue on the base component) into the BigButton component.

The worse thing is:

  • If there are rules for nested selectors in the base component, the <style> tag itself duplicates
  • If the wrap chain continues (e.g., styled(BigButton)), the styles keep increasing

There is a demo for a case in which the two points above apply. We keep repeating color: red and background: silver in the demo.

image

That is not a rare case. Imagine that the "base" component is from a design system like MUI, and we have lot of base styles in there. If we want to style or override them again in the application, that makes it easy for an application to have thousands of style tags in a single page. That does a great impact on performance.

Proposed solution

Can we reuse the class names defined already for the base styled component, and combine that with the outer class name wrapped? Or add an option for rendering the result like this:

<style>.hash-for-button { color: blue }</style>
<style>.hash-for-big-button { font-size: 1.5em }</style>
<button class="hash-for-button" />
<button class="hash-for-button hash-for-big-button" />

In that way, we may have a better performance for the situation, in which styles for both components applies.

Or any other suggestions or practice for that kind of use cases? Thanks!