Sunday, 28 September 2025
The fascinating intersection of SVG and Svelte
## The context
I'm working on a new top-secret web project that had some interesting graphical requirements:
- Tileable images that scale to fit the entire device viewport
- Support rotation in 4 steps (N,S,E,W)
- Support overlaying
- Support filling in distinct steps
- Support theming; i.e. be able to draw the images using (at least) a "light" and "dark" variant
Pretty steep requirements, and once I realised the final two requirements were non-optional, PNGs just weren't going to cut it; the sheer number of permutations would be prohibitive.
## Evangelising Svelte - Svangelising?
[Svelte](https://svelte.dev/) is definitely my "current squeeze" when it comes to building web front-ends; it's minimal, seems to avoid React's primary footguns and with [SvelteKit](https://svelte.dev/docs/kit/introduction), makes development of full-stack apps an absolute breeze. It truly feels like standing on the shoulders of giants when using these powerful tools!
Svelte has an extremely interesting property in that due to the way that `.svelte` files are laid out, i.e.:
```
```
... you can drop an *SVG file* into a Svelte project, change its extension to `.svelte` and it **Just Works** - it's a Svelte file that just happens to not have any `script` or `style`.
## SVelteGraphics Version 1
Given that an SVG "is just" (or perhaps [`satisfies` the definition of](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator)) a Svelte component, that means we can give it props, right?
`FillableThing.svelte`:
```
```
Which we can use like this:
`Caller.svelte`:
```
```
... although this is arguably not particularly useful; being able to set `filled` is nice, but we really want dynamic control over *which* SVG we're actually rendering in the first place.
## Snippet Like It's Hot
Further messing-around with the possibilities inherent in this finally led me to this "shape", that uses a [Svelte snippet](https://svelte.dev/docs/svelte/snippet):
`FillableThingSnippet.svelte`
```
{#snippet thingSnippet(filled: boolean)}
{/snippet}
```
So what I've ended up with is the "guts" of the original SVG (that had the two paths `main` and `inner`) inside a Svelte `snippet` that I can put anywhere in my Svelte app, and call with:
`Caller.svelte`
```
{@render thingSnippet(true)}
```
and as long as I've got my themed CSS variables (e.g. `--theme-color` and `--theme-fill-color`) defined, I've got fillable, themable SVG content.
## Bonus: The MDN SVG Tutorial
MDN has a [fantastic tutorial](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorials/SVG_from_scratch) that introduces the components of SVGs one-by-one, and I'm really interested in exploring programmatic manipulations of these. Stay tuned!
Subscribe to:
Posts (Atom)