Description
The problem
One of the things I come across repeatedly whilst working with Svelte is that scoped styles, whilst absolutely excellent, also prevent efficient style overrides of child components whose css you don't control.
For instance, if I have some code like this:
<div>
<ThirdPartyComponent />
</div>
This renders html similar to the following:
<div class="svelte-l34ns">
<!-- <ThirdPartyComponent /> -->
<div class="third-party-owned-div svelte-b33fs">
stuff
</div>
</div>
Which in itself is fine, however, I am unable then to style the third-party-owned-div
from my parent component, since all styles are prefixed - my CSS ends up like:
[svelte-l34ns] .third-party-owned-div {
background-color: blue;
}
There are some solutions, but they have their own issues
:global(.third-party-owned-div) *
This works, but attempts to style every instance of .third-party-owned-div in the application. This global style conflicts with other components (especially if they don't have unique names), unless you prefix it with a local element selector, however, you can't use :global in the middle of a selector either, so you need to wrap the entire remainder of the selector inside :global.
Effectively, you can, in a rather awkward way, address a deep child of a third-party component as follows:
.parent :global(.some-component-div div ul li a) {
text-decoration: none;
}
However, when using a preprocessor such as scss, the above is no longer usable, since global modifiers are only allowed at the beginning or end of a selector:
.parent :global(.some-component-div) {
... other styles
div ul li {
... other styles
a {
text-decoration: none;
}
}
}
include a separate global css file for styling the component:
This also works, but circumvents the scoped style system, and takes component styles away from their component, which breaks the whole component model.
Proposed solutions:
I've been thinking around a few solutions for this, and I think the cleanest one which fits the Svelte model the best is to allow a section of styles to be scoped to a different scope, which can be specified with a 'scope' attribute in the style tag, which specifies a ref, or similar. For example:
<div>
<ThirdPartyComponent ref:thirdparty />
</div>
<style>
div {
color: green;
}
</style>
<style scope="thirdparty">
.third-party-owned-div {
color: red;
}
</style>