41

How would I do something like this:

<style>
Nested {
    color: blue;
}
</style>

<Nested />

i.e. How do I apply a style to a component from its parent?

4
  • What parent? I see no parent here. Commented Jul 11, 2019 at 12:03
  • Just add a class to your Nested component <Nested class="custom"/>. stackoverflow.com/q/42765262/6809926 Commented Jul 11, 2019 at 12:09
  • 1
    @AntoineF that doesn't work in svelte. It thinks that the class is a property, I think. Commented Jul 11, 2019 at 12:30
  • @MarkSchultheiss that is the code in the parent. Commented Jul 11, 2019 at 12:31

8 Answers 8

27

Update 2025 (svelte 4)

You need to explicitly accept the class as a property in the child component and then apply it to some HTML element in the child. Since "class" is reserved, you need to rename it to something like propsClass in the child.

<!-- in parent component -->

<script>
import Nested from './Nested.svelte';
</script>

<Nested class="foo"/>
<style>
:global(.foo) {
    //...
}
</style>
<!-- in Nested.svelte -->

<script>
let {
    class: propsClass = ""
} = $props()
</script>

<p class={propsClass}>
    Yes this will work
</p>

Before svelte 4

You need to pass props to the parent component with export let, then tie those props to class or style in the child component.

You can either put a style tag on the element in the child you want to style dynamically and use a variable you export for the parent to determine the value of a style directly, then assign the color on the tag like this:

<!-- in parent component -->

<script>
import Nested from './Nested.svelte';
</script>

<Nested color="green"/>
<!-- in Nested.svelte -->

<script>
export let color;
</script>

<p style="color: {color}">
    Yes this will work
</p>

Upside here is flexibility if you only have one or two styles to adjust, downside is that you won't be able to adjust multiple CSS properties from a single prop.

or

You can still use the :global selector but just add a specific ref to the element being styled in the child like so:

<!-- in parent component -->

<script>
import Nested from './Nested.svelte';
</script>

<Nested ref="green"/>

<style>
:global([ref=green]) {
    background: green;
    color: white;
    padding: 5px;
    border-radius: .5rem;
}
</style>
<!-- in Nested.svelte -->

<script>
export let ref;
</script>

<p {ref}>
    Yes this will work also
</p>

This ensures global only affects the exact ref element inside the child it's intended for and not any other classes or native elements. You can see it in action at this REPL link

Sign up to request clarification or add additional context in comments.

1 Comment

The ref above is just an attribute, so that global CSS will leak out and affect any component with an attribute of ref=green.
16

The only way I can think of is with an additional div element.

App.svelte

<script>
    import Nested from './Nested.svelte'    
</script>

<style>
    div :global(.style-in-parent) {
        color: green;
    }
</style>

<div>
    <Nested />  
</div>

Nested.svelte

<div class="style-in-parent">
    Colored based on parent style
</div>

Multiple Nested elements

You could even allow the class name to be dynamic and allow for different colors if you use multiple Nested components. Here's a link to a working example.

3 Comments

As I see you use :global so it's not targeting only inside the Nested Component, but all class style-in-parent inside the div. I tried it here.
Ah right, good catch. I think the next step is to understand your use case better and why you try to style from the parent component.
In order to avoid leaking in the same component, you should add a class known to be unique, once again in the same component (svelte will add a hash preventing it from leaking outside. Here's an variation of @MikeNikles example: svelte.dev/repl/09b33283d787480cb30cab35d5b9d0a0?version=3.6.7
13

You could use inline styles and $$props...

<!-- in parent component -->

<script>
import Nested from './Nested.svelte';
</script>

<Nested style="background: green; color: white; padding: 10px; text-align: center; font-weight: bold" />
<!-- in Nested.svelte -->

<script>
    let stylish=$$props.style
</script>

<div style={stylish}>
    Hello World
</div>

REPL

6 Comments

One-liner for Nested.svelte: <div style={$$props.style}>
This seems to be just what OP asked for, are there any downsides to doing it this way? Looks very straight-forward!
@MartinGunnarsson what if you are using library components? Then you have to go to the source code to add props into divs
@cikatomo what will be a good solution in your opinion for headless library components like npmjs.com/package/@bojalelabs/headless-svelte-ui to enable us to add props to divs?
@ayooluwaalfonso sorry, I really don't know
|
10

using :global(*) is the simplest solution.

No need to specify a class in the child if you want to style all immediate children for example

In the parent component:

<style>
  div > :global(*) {
    color: blue;
  }
<style>

<div>
  <Nested />
<div>

Nested will be blue.

1 Comment

This is the best and most simple solution because you can target Components that are more than 1 level Nested.
6

Update for 2023, you can wrap your style tags in svelte:head which will put them in the head, removing them from the scope context.

<svelte:head>
  <style>
    div { color: red };
  </style>
</svelte:head>

This snippet will make all div elements have the color "red". As such, I'd recommend using this sparingly (I'd probably only use it for scripts/content in a legacy way). Only because debugging "why is everything red" will be impossible for projects with significant routes.

The, iirc, "documented" way is through CSS variables.

<!-- Nested.svelte -->
<div>
  <slot />
</div>

<style>
  div { color: var(--nested-color, inherit); }
</style>

===

<!-- Parent.svelte -->
<div>
  <Nested>
    Applesauce
  </Nested>
</div>

<style>
  div {
    --nested-color: red;
  }
</style>

1 Comment

Life saver! <svelte:head><style> is the only thing that worked correctly.
3

I take a look and found nothing relevant (maybe here), so here is an alternative by adding <div> around your custom component.

<style>
.Nested {
    color: blue;
}
</style>
<div class="Nested">
   <Nested />
</div>

Maybe you will found something but this one works.

5 Comments

This approach sets color: blue on the entire Nested component. I provided an answer below that allows you to targed certain elements within Nested.
@MikeNikles nice one, I just discover svelte 20 minute ago, I didn't know about this.
You made a nice discovery :)! I've used it for a while but it also took me quite a bit to figure out how this all works with styling nested components.
Is the . inside the style tag needed?
Yes because you not anymore targeting the Nested component but div class above, so in CSS you need to use the dot to trigger it.
1

The way I do it is like this:

<style lang="stylus">
  section
    // section styles

    :global(img)
    // image styles
</style>

This generates css selectors like section.svelte-15ht3eh img that only affects the children img tag of the section tag.

No classes or tricks involved there.

Comments

1

Similar to pgalle's answer & Johannes's answer:

A. Nested has a wrapper, and it is the only child.

<style>
.wrapper > :global(*){
    color: blue;
}
</style>

<div class="wrapper">
    <Nested class="nested"/>
</div>

B. Nested has a wrapper, and it is not the only child.

<style>
.wrapper > :global(.nested){
    color: blue;
}
</style>

<div class="wrapper">
    <Nested class="nested"/>
    <Nested/>
</div>

Nested.svelte:

<div class={$$props.class} />

C. Nested is the only element.

<style>
:global(.ss-ReplaceWithRandom){
    color: blue;
}
</style>

<Nested class="ss-ReplaceWithRandom"/>
<Nested/>

Nested.svelte:

<div class={$$props.class} />

D. Nested is the child element in first level but not the only one, without classes.

<style>
* + :global(*){
    color: blue;
}
</style>

<template />
<Nested/>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.