0

Heading

A semantic heading whose visual size can be set independently of its level.

Build faster with ondo

Components you own, styled with your own theme tokens.

import { Heading } from "@/components/ui/heading"

export default function HeadingDemo() {

Installation

bunx --bun shadcn@latest add @ondo-ui/heading

Usage

import { Heading } from "@/components/ui/heading"
<Heading
  level={1 | 2 | 3 | 4 | 5 | 6}
  size="1 | 2 | 3 | 4 | 5 | 6"
  wrap="normal | nowrap | balance | pretty"
>
  Heading
</Heading>

level sets the rendered tag. size sets the visual scale and defaults to level, so most of the time you only pass level.

Examples

Levels

level renders the matching h1–h6 tag and picks the matching size.

Heading level 1

Heading level 2

Heading level 3

Heading level 4

Heading level 5
Heading level 6
import { Heading } from "@/components/ui/heading"

export default function HeadingLevels() {

Sizes

Use size to pick a scale step directly. 1 is the largest and 6 the smallest.

Size 1

Size 2

Size 3

Size 4

Size 5

Size 6

import { Heading } from "@/components/ui/heading"

export default function HeadingSizes() {

Level and size apart

Document outlines and visual hierarchy do not always agree. Set size to keep the heading rank the page needs while showing the size the design needs.

<h2> rendered large, for a hero

Ship faster

<h1> rendered small, for a sidebar

Recent activity

import { Heading } from "@/components/ui/heading"

export default function HeadingLevelAndSize() {

Wrap

wrap controls how the text breaks across lines. It defaults to normal, the browser's own wrapping. nowrap keeps the heading on a single line. balance evens out the length of every line, which suits short headings. pretty instead fills lines normally and only tidies the last one, so it does little more than avoid an orphaned final word.

On a short two-line heading balance and pretty land on the same result — the difference only shows once the text runs to three or more lines, as below.

wrap="normal" (default)

Build a design system your whole team enjoys using

wrap="nowrap"

Build a design system your whole team enjoys using

wrap="balance"

Build a design system your whole team enjoys using

wrap="pretty"

Build a design system your whole team enjoys using

import { Heading } from "@/components/ui/heading"

export default function HeadingWrap() {

For per-breakpoint wrapping, reach for className instead — text-* wrap utilities merge cleanly, so <Heading wrap="pretty" className="md:text-balance" /> is pretty on small screens and balance from md up.

Each value maps to the matching Tailwind utility. See the text-wrap documentation for the details behind each one.

Custom element

Use the render prop when the markup needs a different element — a legend inside a fieldset, for example — but you still want heading styles.

Billing details

The render prop keeps the heading styles while swapping the element for the one the markup actually needs.

import { Heading } from "@/components/ui/heading"

export default function HeadingRender() {

API reference

Heading

Renders an h1–h6 element styled from the heading scale.

PropTypeDefault
level1 | 2 | 3 | 4 | 5 | 61
size1 | 2 | 3 | 4 | 5 | 6level
wrap"normal" | "nowrap" | "balance" | "pretty"normal
renderReactElement | (props, state) => ReactElement-
classNamestring-

Scale

SizeClasses
1text-[2.25rem]/[1.25] font-bold tracking-[-0.02em]
2text-[1.75rem]/[1.3] font-bold tracking-[-0.017em]
3text-[1.5rem]/[1.35] font-bold tracking-[-0.014em]
4text-[1.375rem]/[1.4] font-bold tracking-[-0.011em]
5text-[1.25rem]/[1.4] font-bold tracking-[-0.008em]
6text-[1.125rem]/[1.45] font-bold tracking-[-0.005em]

Every size also gets font-heading text-foreground, plus a wrap utility from wrap (text-wrap by default).