Navigation
Off-canvas menu / Navigation
Navigation.svelte
<script>
import { onMount } from 'svelte';
let isMenuOpen = false;
const toggleMenu = () => (isMenuOpen = !isMenuOpen);
const menuItems = [
{ href: '/', text: 'Home' },
{ href: '/about', text: 'Over ons' },
{ href: '/killer', text: 'Diensten' },
{ href: '/contact', text: 'Contact' }
];
onMount(() => {
const handleResize = () => {
if (window.innerWidth >= 768) {
isMenuOpen = false;
}
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
});
</script>
<div class="fixed min-h-screen w-full">
<!-- Mobile menu button -->
<button
class="hamb fixed left-4 top-4 z-20 h-14 w-14 p-2 text-black md:hidden"
class:active={isMenuOpen}
on:click={toggleMenu}
aria-label="Toggle Menu"
>
<span class="sr-only">Toggle Menu</span>
<svg
class="ham h-15 w-15 cursor-pointer duration-300"
class:rotate-45={isMenuOpen}
viewBox="0 0 100 100"
>
<path
class="line top duration-300"
class:stroke-dashoffset-[-64px]={isMenuOpen}
d="m 30,33 h 40 c 3.722839,0 7.5,3.126468 7.5,8.578427 0,5.451959 -2.727029,8.421573 -7.5,8.421573 h -20"
/>
<path
class="line middle origin-center duration-300"
class:rotate-90={isMenuOpen}
d="m 30,50 h 40"
/>
<path
class="line bottom duration-300"
class:stroke-dashoffset-[-64px]={isMenuOpen}
d="m 70,67 h -40 c 0,0 -7.5,-0.802118 -7.5,-8.365747 0,-7.563629 7.5,-8.634253 7.5,-8.634253 h 20"
/>
</svg>
</button>
<!-- Off-canvas menu (mobile) -->
<div
class="fixed left-0 top-0 h-full w-64 transform bg-blue-500 pl-9 pt-16 text-white transition-transform duration-500 md:hidden"
class:translate-x-0={isMenuOpen}
class:-translate-x-full={!isMenuOpen}
>
<nav class="mt-8">
<ul class="space-y-4">
{#each menuItems as item}
<li>
<a href={item.href} class="block hover:text-blue-300" on:click={toggleMenu}
>{item.text}</a
>
</li>
{/each}
</ul>
</nav>
</div>
<!-- Desktop menu -->
<div class="fixed hidden w-full md:block">
<div class="container py-8">
<nav class="hidden justify-between md:flex">
<div>Logo</div>
<ul class="flex gap-8">
{#each menuItems as item}
<li>
<a href={item.href} class="hover:text-blue-300">{item.text}</a>
</li>
{/each}
</ul>
</nav>
</div>
</div>
</div>
<style lang="postcss">
.line {
@apply rounded fill-none stroke-black stroke-[5] duration-300;
}
.top {
stroke-dasharray: 40 160;
}
.middle {
stroke-dasharray: 40 142;
}
.bottom {
stroke-dasharray: 40 85;
}
:global(.active) .top,
:global(.active) .bottom {
stroke-dashoffset: -64px;
}
:global(.hamb .ham) {
-webkit-tap-highlight-color: transparent;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
</style>
Simple Hamburger Menu
Dependencies
Built using a Svelte port of Flowbite
npm i -D flowbite-svelte flowbite
npm i -D flowbite-svelte-icons
Navigation.svelte
<script>
import { page } from '$app/stores';
import { Navbar, NavBrand, NavLi, NavUl, NavHamburger } from 'flowbite-svelte';
$: activeUrl = $page.url.pathname;
</script>
<Navbar>
<NavBrand href="/">
<img src="/images/flowbite-svelte-icon-logo.svg" class="me-3 h-6 sm:h-9" alt="Flowbite Logo" />
<span class="self-center whitespace-nowrap text-xl font-semibold dark:text-white">Flowbite</span
>
</NavBrand>
<NavHamburger />
<NavUl {activeUrl}>
<NavLi href="/" class={activeUrl === "/" ? `text-red-500` : `text-black`}>Home</NavLi>
<NavLi href="/about" class={activeUrl === "/about" ? `text-red-500` : `text-black`}>About</NavLi>
<NavLi href="/killer" class={activeUrl === "/killer" ? `text-red-500` : `text-black`}>Killer</NavLi>
</NavUl>
</Navbar>
Last updated