Overview
The Link component creates navigation links that integrate with the router. Unlike standard HTML anchors, Link enables client-side routing without full page reloads.
Basic Usage
use dioxus::prelude::*;
#[derive(Clone, Routable, PartialEq)]
enum Route {
#[route("/")]
Home {},
#[route("/about")]
About {},
}
#[component]
fn Home() -> Element {
rsx! {
Link { to: Route::About {}, "Go to About" }
}
}
#[component]
fn About() -> Element {
rsx! {
Link { to: Route::Home {}, "Go to Home" }
}
}
Props
The target route or URL. Can be a route enum variant or a string path.// Internal route
Link { to: Route::Home {}, "Home" }
// String path
Link { to: "/about", "About" }
// External URL
Link { to: "https://dioxuslabs.com", "Dioxus Labs" }
The content to render inside the link.Link { to: Route::Home {},
"Home"
}
// Or with complex content
Link { to: Route::About {},
img { src: "/icon.png" }
span { "About Us" }
}
CSS class applied when the link’s target matches the current route.Link {
to: Route::Home {},
active_class: "active",
"Home"
}
CSS class always applied to the link.Link {
to: Route::About {},
class: "nav-link",
"About"
}
Open the link in a new tab.Link {
to: "https://dioxuslabs.com",
new_tab: true,
"Dioxus Labs"
}
onclick
Option<EventHandler<MouseEvent>>
Custom click handler. By default, the handler runs after navigation.Link {
to: Route::Home {},
onclick: move |evt| {
println!("Link clicked!");
},
"Home"
}
When true, only the custom onclick handler runs (navigation is disabled).Link {
to: Route::Home {},
onclick_only: true,
onclick: move |_| {
println!("Custom action only");
// Navigation does NOT occur
},
"Custom Action"
}
The rel attribute for the generated anchor tag.For external links, defaults to "noopener noreferrer".Link {
to: "https://example.com",
rel: "nofollow",
"External Site"
}
onmounted
Option<EventHandler<MountedEvent>>
Handler called when the anchor element is mounted.Link {
to: Route::Home {},
onmounted: move |evt| {
println!("Link mounted");
},
"Home"
}
Active Links
Links automatically receive an aria-current="page" attribute when their target matches the current route. You can style active links using the active_class prop:
rsx! {
style { "
.nav-link {{ color: gray; }}
.nav-link.active {{ color: blue; font-weight: bold; }}
" }
nav {
Link {
to: Route::Home {},
class: "nav-link",
active_class: "active",
"Home"
}
Link {
to: Route::About {},
class: "nav-link",
active_class: "active",
"About"
}
}
}
Navigation Types
Internal Routes
Internal routes use client-side navigation:
Link { to: Route::Home {}, "Home" }
Link { to: "/about", "About" }
External URLs
External URLs are detected automatically and use standard browser navigation:
Link { to: "https://dioxuslabs.com", "Dioxus" }
Link { to: "mailto:[email protected]", "Email Us" }
HTML Output
The Link component renders as an HTML <a> tag:
Link {
to: Route::About {},
class: "btn",
active_class: "active",
id: "about-link",
"About"
}
Generates:
<a href="/about" class="btn active" aria-current="page" id="about-link">
About
</a>
Advanced Examples
Dynamic Routes
#[derive(Clone, Routable, PartialEq)]
enum Route {
#[route("/user/:id")]
UserProfile { id: usize },
}
#[component]
fn UserList() -> Element {
let users = vec![1, 2, 3];
rsx! {
ul {
for user_id in users {
li {
Link {
to: Route::UserProfile { id: user_id },
"User {user_id}"
}
}
}
}
}
}
Links with Icons
Link {
to: Route::Settings {},
class: "nav-link",
active_class: "active",
svg { class: "icon", /* ... */ }
span { "Settings" }
}
Conditional Navigation
#[component]
fn Home() -> Element {
let is_authenticated = use_signal(|| false);
rsx! {
Link {
to: Route::Dashboard {},
onclick: move |evt| {
if !is_authenticated() {
evt.prevent_default();
// Show login modal instead
}
},
"Dashboard"
}
}
}
Accessibility
- Links automatically receive
aria-current="page" when active
- The underlying
<a> tag is keyboard accessible
- Screen readers announce links correctly
- Modifier keys (Cmd/Ctrl + click) work as expected for opening in new tabs
Important Notes
Link must be used within a Router component. Using it outside a router context will panic in debug builds and render an inactive link in release builds.
For external URLs, the router lets the browser handle navigation. The new_tab prop has no effect on whether a link is considered active.
Source
View the source code: packages/router/src/components/link.rs