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
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;
}
}
}
This also works, but circumvents the scoped style system, and takes component styles away from their component, which breaks the whole component model.
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>
I find it a bit odd that we can't style imported components. Is this just something that's not been thought of yet?
<Component/>
<script>
export default {
components: {
Component: './Component.html'
}
};
</script>
<style>
.component {
color: green;
}
</style>
https://svelte.technology/repl?version=2.15.1&gist=353a4f670a3b9e111530bad1aa2d2d5f
Maybe it's because I am used to using web components, and if you import a web component you can style using its element name my-component however with Svelte the components can be transparent and doesn't necessarily have to have a "container" as such.
Perhaps a class name or attribute could be reserved for components for a hook that allows you to style them.
.Component {} or cmp:component {}
Something to that effect.
I had considered creating a Postcss plugin which converts a Component {} to another selector so that it made more sense when styling imported components.
<Component/>
<script>
export default {
components: {
Component: './Component.html'
}
};
</script>
<style>
Component { /* would be preprocessed to .Component or something similar */
color: green;
}
</style>
Could you check if https://github.com/sveltejs/svelte/issues/2870 issue is a similar feature request? If that is the case https://github.com/sveltejs/svelte/pull/2888 will probably address this one, too (for svelte@3).
Essentially https://github.com/sveltejs/svelte/pull/2888 implements support for preserving classes passed to child components and passing them with the parents scoping selector included.
@nikku I like the suggestion referenced in #2870 - as per PR #2888.
It will certainly address my concerns/issues. How do you feel about it @limitlessloop ?
As I commented on #2888, this general feature is something we want to support, but I don't think that PR is the way we want to go about it.

@Conduitry I suppose idea with scopes looks very good. I am not sure about binding to ref: here but the idea itself very good.
#2888 it's too unnatural and you can't send custom css rules into the component. If we won't make new syntax for css (I hope no) we should use something like in this proposal.
2888 it's too unnatural and you can't send custom css rules into the component.
Could you elaborate on this? How would that limit you in your desired abilities? The whole aim of passing classes down (as you would in HTML) is to not be required to implement any new syntax.
Yep, seems it's a problem. I heard about it many times. In addition to the solution from initial comment, perhaps we can use Special selectors syntax from Svelte 2:
<div>
<ThirdPartyComponent bind:this={comp}/>
</div>
<script>
let comp;
</script>
<style>
div {
color: green;
}
ref:comp .third-party-owned-div {
color: red;
}
</style>
Interesting, just spotted this in the source code.
https://github.com/sveltejs/svelte/blob/master/src/compiler/parse/index.ts#L211
it's also should help with sapper cases, multiple style tags will be the best implementation IMHO.
@Conduitry What exactly is pending clarification regarding this issue?
What's pending clarification is how we want this feature to work. Treating a prop called class specially as in #2888 doesn't seem to be the right answer, and is probably also a breaking change.
Treating a prop called class specially as in #2888 doesn't seem to be the right answer, and is probably also a breaking change.
My personal input is: Make things work intuitively, out of the box. What are concrete examples where https://github.com/sveltejs/svelte/pull/2888 would not be the desired behavior? I'm probably not thinking in Svelte enough here.
@nikku I personally don't see the value in passing some magic class attribute to components, when a reference to the svelte namespaced svelte-xyzzy would work the same way, if only we had access to it's future value.
@antony I mean is that not the point of the class attribute, to somehow derive the scoped selector for the child.
It's not a class attribute, it's a class prop on a component. There are no other props currently whose operation is at all inspired by the attribute of the same name.
right okay, magic prop.
Closing this issue in absolute favour of https://github.com/sveltejs/rfcs/pull/13
Most helpful comment
it's also should help with sapper cases, multiple style tags will be the best implementation IMHO.