Link
A styled anchor component for navigation with built-in icon support
Import
import { Link } from '@heroui/react';Usage
import {Link} from "@heroui/react";
export function LinkBasic() {
return (
<Link href="#">
Call to action
<Link.Icon />
</Link>
);
}Anatomy
Import the Link component and access all parts using dot notation.
import { Link } from '@heroui/react';
export default () => (
<Link href="#">
Call to action
<Link.Icon />
</Link>
);Custom Icon
import {Link} from "@heroui/react";
import {Icon} from "@iconify/react";
export function LinkCustomIcon() {
return (
<div className="flex flex-col gap-3">
<Link href="#">
External link
<Link.Icon className="ml-1.5 size-3">
<Icon icon="gravity-ui:arrow-up-right-from-square" />
</Link.Icon>
</Link>
<Link className="gap-1" href="#">
Go to page
<Link.Icon className="size-3">
<Icon icon="gravity-ui:link" />
</Link.Icon>
</Link>
</div>
);
}Icon Placement
import {Link} from "@heroui/react";
export function LinkIconPlacement() {
return (
<div className="flex flex-col gap-3">
<Link href="#">
Icon at end (default)
<Link.Icon />
</Link>
<Link className="gap-1" href="#">
<Link.Icon />
Icon at start
</Link>
</div>
);
}Underline Variants
Control the underline behavior with the underline prop:
Underline on hover (default)
Hover to see underline animationAlways visible underline
Underline always visibleNo underline
Link without any underlineimport {Link} from "@heroui/react";
export function LinkUnderlineVariants() {
return (
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-2">
<p className="text-muted text-sm font-medium">Underline on hover (default)</p>
<Link href="#" underline="hover">
Hover to see underline animation
<Link.Icon />
</Link>
</div>
<div className="flex flex-col gap-2">
<p className="text-muted text-sm font-medium">Always visible underline</p>
<Link href="#" underline="always">
Underline always visible
<Link.Icon />
</Link>
</div>
<div className="flex flex-col gap-2">
<p className="text-muted text-sm font-medium">No underline</p>
<Link href="#" underline="none">
Link without any underline
<Link.Icon />
</Link>
</div>
</div>
);
}underline="hover"(default) - Animated underline appears on hoverunderline="always"- Underline always visible (50% opacity, 100% on hover)underline="none"- No underline
Underline Offset
Adjust the spacing between text and underline with the underlineOffset prop:
import {Link} from "@heroui/react";
export function LinkUnderlineOffset() {
return (
<div className="flex flex-col gap-4">
<Link href="#" underline="hover" underlineOffset={1}>
Offset 1 (default)
<Link.Icon />
</Link>
<Link href="#" underline="hover" underlineOffset={2}>
Offset 2
<Link.Icon />
</Link>
<Link href="#" underline="hover" underlineOffset={3}>
Offset 3
<Link.Icon />
</Link>
</div>
);
}underlineOffset={1}(default) - No spaceunderlineOffset={2}- 2px spacingunderlineOffset={3}- 4px spacing
Using with Routing Libraries
Use the asChild prop to compose Link with framework-specific links like Next.js:
import { Link } from '@heroui/react';
import NextLink from 'next/link';
export default function Demo() {
return (
<Link asChild underline="hover">
<NextLink href="/about">
About Page
<Link.Icon />
</NextLink>
</Link>
);
}Direct Class Application
Since HeroUI uses BEM classes, you can apply Link styles directly to any link element without using asChild:
import NextLink from 'next/link';
// Apply classes directly
export default function Demo() {
return (
<NextLink href="/about" className="link link--underline-hover link--offset-1">
About Page
</NextLink>
);
}
// Or with a native anchor
export default function NativeLink() {
return (
<a href="/about" className="link link--underline-always link--offset-2">
About Page
</a>
);
}Available BEM classes:
- Base:
link - Underline:
link--underline-none,link--underline-hover,link--underline-always - Offset:
link--offset-1,link--offset-2,link--offset-3
Styling
Passing Tailwind CSS classes
import { Link } from '@heroui/react';
function CustomLink() {
return (
<Link
href="#"
className="text-lg font-bold text-accent hover:text-accent/80"
>
Custom styled link
</Link>
);
}Customizing the component classes
To customize the Link component classes, you can use the @layer components directive.
Learn more.
@layer components {
.link {
@apply font-semibold no-underline hover:underline;
}
}HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.
CSS Classes
The Link component uses these CSS classes (View source styles):
Base Classes
.link- Base link styles
Underline Variants
.link--underline-none- No underline.link--underline-hover- Animated underline on hover (default).link--underline-always- Always visible underline
Underline Offset
.link--offset-1- No spacing (default).link--offset-2- 2px spacing.link--offset-3- 4px spacing
Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- Focus:
:focus-visibleor[data-focus-visible="true"] - Disabled:
:disabledor[aria-disabled="true"]
API Reference
Link Props
| Prop | Type | Default | Description |
|---|---|---|---|
href | string | - | Destination URL for the anchor |
target | string | "_self" | Controls where to open the linked document |
rel | string | - | Relationship between the current and linked documents |
download | boolean | string | - | Prompts file download instead of navigation |
underline | "none" | "hover" | "always" | "hover" | Controls underline visibility and behavior |
underlineOffset | 1 | 2 | 3 | 1 | Spacing between text and underline |
asChild | boolean | false | Merge props with child element (useful for routing libraries) |
isDisabled | boolean | false | Disables pointer and keyboard interaction |
className | string | - | Custom classes merged with the default styles |
children | React.ReactNode | - | Content rendered inside the link |
onPress | (e: PressEvent) => void | - | Fired when the link is activated |
autoFocus | boolean | - | Whether the element should receive focus on render |
Link.Icon Props
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Merge props with child element |
children | React.ReactNode | - | Custom icon element; defaults to the built-in arrow icon when omitted |
className | string | - | Additional CSS classes |