Svelte 5 component · fractalsvelte-ui · Typography
Heading
A semantic heading element spanning levels h1 through h6 with proportional typography sizing and optical letter tracking. Provides an optional brand gradient text treatment for high-impact titles.
Install
Heading is a Svelte 5 heading component in @fractaldesign/fractalsvelte-ui. It works in SvelteKit and in any Svelte 5 app.
pnpm add @fractaldesign/fractalsvelte-uiImport
import { Heading } from '@fractaldesign/fractalsvelte-ui';Usage
<Heading level={1}>Click me</Heading>Props
Also accepts every attribute of HTMLAttributes, spread onto
the root element.
| Name | Type | Default |
|---|---|---|
level | HeadingLevel | 1 |
as | HeadingTag 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'div' | — |
size | HeadingSize 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | — |
tracking | HeadingTracking 'tight' | 'normal' | 'wide' | 'tight' |
weight | HeadingWeight 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold' | — |
gradient | boolean | string | false |
class | string | '' |
Snippets
| Name | Type | Default |
|---|---|---|
children | Snippet | — |
Source
Show the Heading.svelte source
<script lang="ts">
import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
export type HeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'div';
export type HeadingSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';
export type HeadingTracking = 'tight' | 'normal' | 'wide';
export type HeadingWeight = 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold';
interface Props extends HTMLAttributes<HTMLHeadingElement> {
level?: HeadingLevel;
as?: HeadingTag;
size?: HeadingSize;
tracking?: HeadingTracking;
weight?: HeadingWeight;
gradient?: boolean | string;
class?: string;
children?: Snippet;
}
let {
level = 1,
as,
size,
tracking = 'tight',
weight,
gradient = false,
class: className = '',
children,
...restProps
}: Props = $props();
const tag = $derived<HeadingTag>(as ?? (`h${level}` as HeadingTag));
const computedSize = $derived.by<HeadingSize>(() => {
if (size) return size;
switch (level) {
case 1:
return '3xl';
case 2:
return '2xl';
case 3:
return 'xl';
case 4:
return 'lg';
case 5:
return 'md';
case 6:
default:
return 'sm';
}
});
const customGradient = $derived(
typeof gradient === 'string' ? gradient : undefined
);
</script>
<svelte:element
this={tag}
class="f-heading {className}"
data-size={computedSize}
data-tracking={tracking}
data-weight={weight}
data-gradient={gradient ? '' : undefined}
style:background-image={customGradient}
{...restProps}
>
{#if children}
{@render children()}
{/if}
</svelte:element>
<style>
@layer fractalsvelte-ui.components {
.f-heading {
margin: 0;
font-family: inherit;
color: var(--f-text);
line-height: 1.25;
box-sizing: border-box;
}
/* Sizes */
.f-heading[data-size='3xl'] {
font-size: var(--f-text-3xl);
line-height: 1.2;
font-weight: 700;
}
.f-heading[data-size='2xl'] {
font-size: var(--f-text-2xl);
line-height: 1.25;
font-weight: 700;
}
.f-heading[data-size='xl'] {
font-size: var(--f-text-xl);
line-height: 1.3;
font-weight: 600;
}
.f-heading[data-size='lg'] {
font-size: var(--f-text-lg);
line-height: 1.35;
font-weight: 600;
}
.f-heading[data-size='md'] {
font-size: var(--f-text-base);
line-height: 1.4;
font-weight: 600;
}
.f-heading[data-size='sm'] {
font-size: var(--f-text-sm);
line-height: 1.4;
font-weight: 600;
}
.f-heading[data-size='xs'] {
font-size: var(--f-text-xs);
line-height: 1.4;
font-weight: 600;
}
/* Tracking */
.f-heading[data-tracking='tight'] {
letter-spacing: -0.025em;
}
.f-heading[data-tracking='normal'] {
letter-spacing: 0;
}
.f-heading[data-tracking='wide'] {
letter-spacing: 0.05em;
}
/* Explicit Weights */
.f-heading[data-weight='normal'] {
font-weight: 400;
}
.f-heading[data-weight='medium'] {
font-weight: 500;
}
.f-heading[data-weight='semibold'] {
font-weight: 600;
}
.f-heading[data-weight='bold'] {
font-weight: 700;
}
.f-heading[data-weight='extrabold'] {
font-weight: 800;
}
/* Gradient Text */
.f-heading[data-gradient] {
background: linear-gradient(135deg, var(--f-primary) 0%, var(--f-accent) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
display: inline-block;
}
}
</style>Related components
Text A multi-variant typographical body element supporting lead paragraphs, muted labels, subtle metadata, and…Accordion A vertically stacked disclosure container supporting single or multi-panel expansion.Blockquote A styled quotation block featuring a left accent border, quotation mark iconography, and structured…Code An inline monospace code token designed for highlighting keywords, identifiers, and keystrokes within prose.CodeBlock A multi-line code display container with an integrated header bar, syntax language indicator, line…Collapsible A standalone expandable disclosure component that animates content height between open and closed states.