-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Open
Labels
feature / enhancementNew feature or requestNew feature or requestsvelteThis feature can't be implemented without changes to Svelte itselfThis feature can't be implemented without changes to Svelte itself
Milestone
Description
Let's say I have a _layout.svelte
like the following:
<slot name="layout-pre"></slot>
<div id="intermediate">Some other intermediate stuff.</div>
<slot></slot>
And now I have a child view (let's call it homepage.svelte
which inherits that layout, which puts some stuff into the named slot, and the rest into the default slot:
<h1 slot="layout-pre">This should come before #intermediate.</h1>
<!-- When rendered, the div from above should get inserted here from the layout:
<div id="intermediate">Some other intermediate stuff.</div>
-->
<main>Since this doesn't use a named slot, it'll just get inserted into the unnamed slot above.</main>
Right now this is not allowed, and the following error is thrown: Element with a slot='...' attribute must be a descendant of a component or custom element
. Are there technical or usage reasons why we wouldn't want to treat a layout like any other component with respect to slots?
aromanarguello, nksfrank, nelsonpecora, joakim, alexdilley and 319 moreBeyondoximus, n3dst4, lucavenir, oscarhermoso, davemaul and 21 moreumwwwelt, GeneralMine, pdaddyo, hirokbanik, n3dst4 and 21 more
Metadata
Metadata
Assignees
Labels
feature / enhancementNew feature or requestNew feature or requestsvelteThis feature can't be implemented without changes to Svelte itselfThis feature can't be implemented without changes to Svelte itself
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
joakim commentedon Oct 12, 2019
buhrmi commentedon Nov 4, 2019
I guess it doesn't work because the Svelte compiler needs to know at compile-time which parent-component the slots will end up in.
jdgaravito commentedon Feb 6, 2020
buhrmi commentedon Feb 6, 2020
Well, there's nothing keeping us from writing our pages like
silllli commentedon Feb 14, 2020
jdgaravito commentedon Feb 14, 2020
Bandit commentedon Mar 14, 2020
zakaria-chahboun commentedon Jul 4, 2020
You have to do it in a regular way, by creating a custom layout: (_myLayout.svelte)
and include it in your index page.
mrmaglet commentedon Feb 1, 2021
Can someone show how to include a _customLayout.svelte as zakaria-chahboun suggests?
zakaria-chahboun commentedon Feb 8, 2021
Example:
We have a route called
test
.So we just create a folder named test, and inside of this folder we have our svelte files,
One is our router and the second is our custom layout, like so:
The _customLayout.svelte is like this:
And the [id].svelte is like this:
mquandalle commentedon Feb 17, 2021
Nick-Mazuk commentedon Apr 29, 2021
stalkerg commentedon May 1, 2021
parischap commentedon May 4, 2021
70 remaining items
rChaoz commentedon May 7, 2024
I think they should, but I'm not sure how. Without anything special needed, a layout can do something like this:
And:
This works, but I would love to see a better mechanism for this, that ensures all slots are loaded/unloaded at the same time, as they normally would in a component. One idea would be that top-level snippets in a page are passed as slots, but I don't think would be too great.
Additionally, since slots are now just snippets (plain JS values) passed as props, it would be nice to be able to easily pass any data from the page to the layout. One idea might be a designated
export const
value is passed as spread props to the layout. Then, this would be very easy to do:Could even be made reactive with
export const x = $state({ ...})
.Proof of concept
Bishwas-py commentedon Jun 18, 2024
#627 (comment) Is this solution implemented on the kit code base?
emmnull commentedon Jun 20, 2024
#627 (comment) Passing snippets from children pages/layouts to parent layouts using a context like this works well in simple cases, but it quickly becomes trickier if you want to properly handle reverting to parent snippets when unmounting nested routes/layouts.
For example, in a dashboard layout where children routes can set different sidebar / header / footer content, the context could look more like:
This context can then be used simply like so:
cmolina commentedon Jul 23, 2024
Based on #627 (comment), I implemented a wrapper for the Context API that allows you to get & set only the last element of a property, and supports dynamic properties.
Internally, it works by keeping an internal object with stacks, and by returning a Proxy for end user consumption.
seo-rii commentedon Aug 31, 2024
sveltejs/svelte#12713 (comment)
If svelte supports exporting snippets in the future, I think it can solve this problem with SSR in a very elegant way!
Move accessibility outside main element
Beyondo commentedon Jul 26, 2025
I found a clean solution that does not require changing your exisiting code structure at all. It is majorily inspired by #12928 (comment) but it had a bug that it does not reset the slots, making pages leak their own slots while navigating if they don't override it. I fixed it by simply deleting the slots on every call.
$lib/state/layout.svelte.ts
(or anywhere you want):How to use:
+layout.svelte
:+page.svelte
:page2/+page.svelte
:Note 1: If you don't call
layout
on every page, the slots would not reset and cause them to stay/leak even after navigation.Note 2: The combined amalgamation of non-snippet code is always implicitly passed as
children
, so no need to wrap it.Note 3: Even if you set nothing, you must always call
layout({})
in your+page.svelte
(s) to clear the slots and thus reset them to whatever default you have in+layout.svelte
.For your mental model: It's just a single extra function call on every page to pass your custom snippets for your layout and your
+layout.svelte
simply determines where they are placed (wherever you want). This assumes a single layout for the entire application, but you could always extend by copying thelayout.svelte.ts
file as much you want and rename it or structure it better for your own project to add more reactive state tracking.t1u1 commentedon Jul 30, 2025
The solution I ended up with is to ditch +layout.svelte completely. Instead, I define my own PageLayout components and use them manually in each page route. That way, I have complete control over the layout, including parameters and slots. I still use the +layout.server file for auth and other cross cutting concerns. In a pinch, for a particular subroute, I have the option to drop a +layout.svelte and include the PageLayout component in it.
Have used this for multiple projects now without any regrets.
valentinschabschneider commentedon Jul 31, 2025
We are encountering layouts where this would be a life savior! :)