question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Styles encapsulation: opt-in inheritance

See original GitHub issue

This is a feature request or rather an idea – would love to know your opinion.

Like CSS Modules, CSS-in-JS solutions or even BEM and SUIT CSS, styled components generates unique class names to avoid name clashing and global disasters caused by the CSS cascade property.

People feel pretty confident when using these tools but ignore the fact that there is another enemy around the corner that is CSS inheritance i.e.

styles applied to a component can affect the subtree and even reach the leaves. Properties like color, font-size, font-family are still inherited.

This is good for many reasons but it is an unpredictable side-effect and imho inheritance should be opt-in (instead of opt-out) and predictable. Pete Hunt mentioned it at CSSConf [video] but we were already implementing this idea into SUIT CSS preprocessor and it is now available in v3 [link].

We could reset inherited and non-inherited properties at the root of the component to get styles encapsulation like in ShadowDOM. Descendants can still inherit from the component scope because they only get non-ineherited properties reset – styles won’t affect nested components.

The only difference between SUIT and styled components is that in styled components there aren’t descendants i.e. each component is a single element without nested stuff. Therefore in order to fit components into a specific context we’d need to have a way to tell that a component is part of a widget or something (in a way a descendant of a scoped component) and reset only non-inherited properties instead.

API Ideas:

import {descendant} from 'styled-components'

// returns a styled component with inherited and non-inherited properties reset
const Button = styled.button`
  border: 1px solid ${color};
`

// returns a styled component with only non-inherited properties reset
const HeaderButton = descendant(Button)

In alternative styles encapsulation could be opt-in

const Button = styled.button`
  /** @encapsulate */
  border: 1px solid ${color};
`
// or

import {encapsulate} from 'styled-components'
const EncapsulatedButton = encapsulate(Button)

Any of the above solutions would just inject (or remove) the following global class names:

.__styled-components-encapsulate-reset-inherited {
  color: initial;
  font-family: initial;
  font-size: medium;
  /* ... */
}

.__styled-components-encapsulate-reset-non-inherited {
  margin: 0;
  padding: 0;
  width: auto;
  /* ... */
}

These two rules should be at the top of the stylesheet so that styled components can override single properties.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:1
  • Comments:9 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
geelencommented, Oct 31, 2016

Hmm, this is interesting. But I don’t think the Shadow DOM does quite what you think. Shadow DOM makes a boundary that selectors can’t cross, but inheritance can. You can use all: initial on an element to override anything inherited, but that’s something different (at least I think that’s the case, this sort of stuff is hard to know definitively)

I’m actually a big proponent of using inheritance judiciously rather than trying to reset every element all the time. I tend to think people are more worried by the idea of inheritance changing values within their components than the reality of doing so. Personally, I think each “outer component” can simply reset the properties it cares about and pass on the ones it doesn’t. That way your “descendants” are totally responsive to the properties already set on the page, which makes them much more reusable.

I gave a talk on this topic a few months back if you’re interested: https://www.youtube.com/watch?v=XR6eM_5pAb0

1reaction
mxstbrcommented, Jul 1, 2017

Since nobody has asked for this feature in almost half a year it’s unlikely we’re going to introduce it to the library. We would also break a large amount of existing users with this change, which is not something I’d be particularly comfortable with.

I’ll close this issue for now, if you still strongly feel this should be part of styled-components one way or another feel free to comment again or open a new issue!

Read more comments on GitHub >

github_iconTop Results From Across the Web

angular - Angular2's component's styles are not inherited in ...
Style encapsulation (preventing style from bleeding into or out of components) is a main feature of Angular components. There are different options to ......
Read more >
CSS Encapsulation in Angular - Pluralsight
CSS Encapsulation allows for scoping one's styles to a specific component or reusable piece of code. When using component-based architecture ...
Read more >
Encapsulating Style and Structure with Shadow DOM
There are a few exceptions that inherit from the parent document, like font family and document font sizes (e.g. rem ) that can...
Read more >
CSS Encapsulation with Angular Components - Cory Rylan
This isolates the component completely so we do not inherit the global .cmp styles with that had our padding and margin. Rendered output...
Read more >
Our custom CSS encapsulation story | by Code And Wild
The last disadvantage(as far as we're aware) is that child components will inherit any parent's styles. In practice, this is not a real ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found