Skip to content

Add support for styling third-party components #1808

Closed
@antony

Description

@antony

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>

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting submitterneeds a reproduction, or clarification

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions