4 ms·
The usefulness of this articled is lessened because it's React-specific and React is bad with DOM and style isolation in general. The base problem here is that
by spankalee 7y ago
The usefulness of this articled is lessened because it's React-specific and React is bad with DOM and style isolation in general.
The base problem here is that both a component and its host may want to style the component. The component model should account for this and offer some guidance.
Web components do this with the `:host` selector that styles the component from within its shadow root. The styles applied with the `:host` selector can be overridden by the outside styles, without the component needing to weaken encapsulation by allowing styling from the outside via JS properties. This means it's not really bad for a component to give itself default outside styling like block vs inline display, or even margins, because the user can always reset them as needed, much like built-in elements.
For instance, a web component might have these styles:
<my-element>
#shadow-root
:host {
margin: 1em;
}
And at its use-site, the margins can be set differently:
<style>
my-element {
margin-botton: 0;
}
</style>
<h1>...</h1>
<my-element></my-element>
<div>...</div>
Shadow DOM also helps with specificity fights, as the cascade goes: shadow style -> light style -> light !important -> shadow !important. This way a component can define which styles are only defaults.
Edit to clarify: one of the big problems with the article is the use of inline styles. They have the highest specificity and there's no built-in way to "merge" inline styles like you normally get via inheritance and the cascade.
- deleted 7y ago[deleted]
- TomMarius 7y agoconst MyComponent: React.FC<{style?:React.CSSProperties}> = (props) => <div style={{margin: 16, ...props.style}}>{props.children}</div> I don't see any issue; additionally, it's well typed and you have fine control over it!
- spankalee 7y agoThat's not stylable from CSS though, so you have to pass JS props and can't use selectors. It also duplicates styling strings across all similar style attributes which is not good for memory or perf.
- TomMarius 7y agoNoone using React cares about styling from CSS though. It doesn't have to duplicate much, you can use e.g. typestyle or React Native's Stylesheet
- ss3000 7y ago> Web components do this with the `:host` selector that styles the component from within its shadow root. The styles applied with the `:host` selector can be overridden by the outside styles, without the component needing to weaken encapsulation by allowing styling from the outside via JS properties. I don't see how the React approach of accepting styles as JS props is any weaker in terms of encapsulation compared to your example above. If anything, it offers the opportunity for stronger encapsulation because it supports limiting/transforming the styling props we accept through those JS props, and even allows us to define a styling API for our component that's completely independent of CSS semantics, enabling components APIs that can span multiple platforms with independent implementations.
- spankalee 7y agoYou're right. If we're talking about only the root element, it is similar to :host, because the custom element is itself stylable from the outside. What makes me say that encapsulation is weakened is that threading JS property bags to other internal elements is also relatively common, and inline styles don't really offer any encapsulation there. Other selectors in the page can still select and style properties that are not directly styled by the element. I should have clarified that. Shadow DOM provides true runtime style encapsulation, and the selectors on the page can't select the internal elements at all.
- ss3000 7y agoAh I see, that makes sense. Shadow DOM definitely offers much stronger style encapsulation than a React component where you can only "enforce" that components shouldn't reach into it to style internals by convention.