I’ve worked on a Svelte/SvelteKit project for over a year and have become familiar with many of its features. It’s been one of the easiest frameworks for me to adopt. I attribute that to its simple syntax and well-written documentation. I’ve previously written about the Context API, but I want to highlight a few other useful features available in Svelte 5, some of which may feel familiar if you work in React.
Snippets (Svelte)
Snippets, which replace slots from Svelte 4, are reusable blocks of markup that get passed into a component. This is similar to how React handles children in components.
Below is a simple React example using children:
function Card({ children }) {
return <div className="card">{children}</div>;
}
<Card>
<h2>Title</h2> <p>Body text</p>
</Card>
You can achieve this in Svelte by doing:
// Card.svelte
<script>
let { children } = $props();
</script> <
div class="card">
{@render children()}
</div>
// Usage example:
<Card>
<h2>Title</h2>
<p>Body text</p>
</Card>
At this point, snippets look very similar to React’s children, but the real utility of snippets is being able to pass several different blocks as props into one component.
Here’s an example of a component that accepts multiple snippets:
// Panel.svelte
<script>
let { header, body, footer } = $props();
</script>
<section class="panel">
<header>{@render header?.()}</header>
<main>{@render body?.()}</main>
<footer>{@render footer?.()}</footer>
</section>
// Usage example:
<Panel>
{#snippet header()} <h3>Settings</h3> {/snippet}
{#snippet body()} <p>Controls go here</p> {/snippet}
{#snippet footer()} <button>Save</button> {/snippet}
</Panel>
The optional chaining (?.) ensures snippets are only rendered if defined. This pattern gives you the flexibility to render markup in various places within a component’s layout, combining templating with customization to cut down on redundant code.
Declaring const in Templated HTML (Svelte)
You can declare local constants directly inside your markup. These constants are scoped to the block they’re defined in, such as a {#each} or {#if} block.
<ul>
{#each products as product}
{@const savings = product.originalPrice - product.price}
{@const isDiscounted = savings > 0}
<li class:discounted={isDiscounted}>
<strong>{product.name}</strong>
<span>${product.price}</span>
{#if isDiscounted} <
em>Save ${savings}</em>
{/if}
</li>
{/each}
</ul>
This is useful when performing various calculations with the same initial value. The logic is closer to the definition which is more readable in complex components.
SSR Flag (SvelteKit)
The server-side rendering (SSR) flag in SvelteKit allows you to toggle SSR on or off for a given page in your application. The default value is true, but there are some cases where it’s useful to render on the client instead, such as when a page depends on browser-only globals like window or document. I’ve run into this situation while adding a CAPTCHA widget to a form page.
To use the flag, simply add export const ssr = false to the +page.server.tsfile. Be careful, if you add this line to a root +layout.js file it forces the entire application to render on the client.
While these features exist in other frameworks, the way Svelte 5 implements them feels more intentional and straightforward to use. I’ve found Svelte to be quite accessible for beginners and worth exploring if you’re looking for a robust framework with a gentle learning curve.