music on atproto
plyr.fm
1# portals (rendering modals outside parent DOM)
2
3## the problem
4
5when a modal is rendered inside an element with `backdrop-filter`, `transform`, or `filter`, the modal's `position: fixed` becomes relative to that ancestor instead of the viewport. this causes modals to be positioned incorrectly (e.g., appearing off-screen).
6
7the header uses `backdrop-filter` for the glass blur effect, so any modal rendered inside the header will not center properly on the viewport.
8
9## the solution
10
11use `svelte-portal` to render modal content directly on `<body>`, outside the parent DOM hierarchy.
12
13```bash
14bun add svelte-portal
15```
16
17```svelte
18<script>
19 import { portal } from 'svelte-portal';
20</script>
21
22<div class="menu-backdrop" use:portal={'body'} onclick={close}></div>
23<div class="menu-popover" use:portal={'body'}>
24 <!-- modal content -->
25</div>
26```
27
28the `use:portal={'body'}` action moves the element to `document.body` while preserving all svelte reactivity, bindings, and event handlers.
29
30## when to use
31
32use portals for any fixed-position overlay (modals, dropdowns, tooltips) that might be rendered inside:
33- elements with `backdrop-filter` (glass effects)
34- elements with `transform`
35- elements with `filter`
36- `position: sticky` containers (in some browsers)
37
38## reference
39
40- [svelte-portal on GitHub](https://github.com/romkor/svelte-portal)