How to apply styles to slot element in Svelte?

11k views Asked by At

I'd like styles declared in one module to be applied to the slot elements of that module (which get filled in in another file).

Here's a Svelte REPL of the following example:

App.html

<List>
    {{#each items as item}}
        <li><a>{{item}}</a></li>
    {{/each}}
</List>

<script>
    import List from './List.html'

    export default {
        components: {
            List
        }
    }
</script>

List.html:

<h1>A Special List</h1>
<ul>
    <li><a>Let's all be red!</a></li>
    <slot></slot>
</ul>

<style>
    ul a {
        color: red;
    }
</style>

Data:

{
    "items": ["Nope", "I'm good"]
}

The red coloring doesn't apply to the a tag elements that were added through slot.

I'm very new to Svelte, but I read through as much as I could find online, and couldn't seem to find a solution. Any help would be appreciated, thank you.

2

There are 2 answers

5
Rich Harris On BEST ANSWER

The trick here is to opt in to the cascade, using the :global(...) modifier. In your List component:

<style>
  ul :global(a) {
    color: red;
  }
</style>

That means 'any a elements that are children of this component's ul element, whether they belong to this component or not, should be red'.

0
Roman Mahotskyi On

For those who need to style the slot container only if it exists

Create button component

<button>
  {#if $$slots['start-icon']}
    <div class="m-4">
      <slot name="start-icon" />
    </div>
  {/if}

  <slot></slot>
</button>

Usage

<button>
  <Icon slot='start-icon' />

  Button name
</button>

See Component composition / Checking for slot content