Svelte
One Svelte component per icon, for Svelte 4, Svelte 5 and SvelteKit, with TypeScript types.
@hubtoolify/icons-svelte has a component for every free icon, in the Line style. It works with Svelte 4, Svelte 5 (runes mode included) and SvelteKit, renders on the server, and comes with TypeScript types. Each icon is its own component, so your bundle keeps only the icons you import.
@hubtoolify-pro/icons-svelte with the other Pro styles, so the Solid and Duotone examples on this page need Pro. Versions 1.x (up to 1.2.1) included Solid and Duotone under the free licence, and copies you already installed keep that licence.
Install#
npm install @hubtoolify/icons-svelte
Use#
Components are named Hti plus the icon's name in PascalCase: arrow-up-right becomes HtiArrowUpRight. Find names in the icon library.
<script>
import { HtiHome, HtiCalendarCheck } from '@hubtoolify/icons-svelte';
</script>
<HtiHome />
<HtiHome variant="solid" size={32} color="#1766f2" />
<HtiCalendarCheck variant="duotone" secondaryColor="#ffd23f" secondaryOpacity={0.9} />
<HtiHome strokeWidth={2} title="Home" />
Props#
| Prop | Value |
|---|---|
variant | 'line' (default). 'solid' and 'duotone' were in 1.x; from 2.0.0 they are in the Pro package |
size | Width and height, default 24 |
color | Defaults to currentColor, so the icon follows the text |
secondaryColor, secondaryOpacity | The Duotone tone |
strokeWidth | On the 24 px grid; default 1.2 for Line (1.7 for Solid and Duotone, in 1.x and Pro) |
title | An accessible name. Without it the icon is aria-hidden |
Any other attribute (class, style, data-*, aria-*) goes to the <svg>. Every instance gets its own mask ids once it is mounted, so the same icon can appear any number of times on a page, and server-rendered pages hydrate without warnings.
Events#
<!-- Svelte 5 -->
<HtiHome onclick={() => open = true} />
<!-- Svelte 4 -->
<HtiHome on:click={() => (open = true)} />
Icon-only buttons#
Label the button, not the icon:
<script>
import { HtiSearch } from '@hubtoolify/icons-svelte';
</script>
<button type="button" aria-label="Search">
<HtiSearch size={20} />
</button>
Icons from data#
Keep the components themselves in your data rather than strings, so the bundler can still drop the icons you do not use. In Svelte 5 you can also write <item.icon size={18} />.
<script>
import { HtiHome, HtiSettings, HtiUser } from '@hubtoolify/icons-svelte';
const nav = [
{ href: '/', label: 'Home', icon: HtiHome },
{ href: '/account', label: 'Account', icon: HtiUser },
{ href: '/settings', label: 'Settings', icon: HtiSettings },
];
</script>
{#each nav as item}
<a href={item.href}><svelte:component this={item.icon} size={18} /> {item.label}</a>
{/each}
One icon per import#
Importing from the package root is fine: a production build keeps only what you use, and Vite pre-bundles the package for the dev server. If you prefer, import each icon by its path:
<script>
import HtiHome from '@hubtoolify/icons-svelte/icons/home';
</script>
CSS classes instead#
If you would rather not add a package, the web kit works in any Svelte template. Copy it into static/ with npx hubtoolify-icons static/hubtoolify-icons (after npm install @hubtoolify/icons), or link it from the CDN, and do not import its stylesheet into the bundler.
<!-- src/app.html, after copying the kit to static/hubtoolify-icons -->
<link rel="stylesheet" href="/hubtoolify-icons/css/hubtoolify-icons.min.css">
<!-- any component -->
<i class="hti hti-home" aria-hidden="true"></i>
Pro styles#
With a Pro plan, @hubtoolify-pro/icons-svelte has every Pro style as Svelte components, one subpath per style, with the same props: import { HtiHome } from '@hubtoolify-pro/icons-svelte/slab'. It installs from HubToolify's own registry; see Pro packages.
© 2026 HubToolify. Documentation text and examples are HubToolify's own; code snippets may be copied into your projects.