Elements and Text
User interfaces are assembled by combining text and UI elements together in a useful and visually appealing tree. An example of some text and elements with RSX may look like:
let author = "Dioxus Labs"; let content = "Build cool things ✌️"; rsx! { h1 { "Welcome to Dioxus!" } h3 { "Brought to you by {author}" } p { class: "main-content", {content} } }
Welcome to Dioxus!
Brought to you by Dioxus Labs
Build cool things ✌️
Text Nodes
Any content surrounded by quotes is rendered as a text node in RSX:
rsx! { "Hello world" }
Text nodes in Dioxus automatically implement the same rules as Rust's format! macro, including Display and Debug printing.
let world = "earth"; rsx! { "Hello {world}!" }
Unlike Rust's format macro, rsx! lets us embed entire Rust expressions which can be quite handy when working with complex objects or calling functions inline.
let user = use_signal(|| User { name: "Dioxus".to_string(), }); rsx! { "Hello {user.read().name}" }
Elements
The most basic building block of HTML is an element. In RSX, an element is declared with a name and then curly braces. One of the most common elements is the input element. The input element creates an interactive input box:
rsx! { input {} }
Elements can take additional parameters called attributes that modify how the element is rendered. Attributes are added inline, similar to adding fields to a struct instantiation:
rsx! { input { placeholder: "type something cool!" } }
There are a huge number of HTML elements available, including, but not limited to:
- Text and Content:
p,h1,span,div,a,pre, etc. - Forms and Input:
form,input,textarea,select,button, etc. - Media and Content:
img,video,audio,source,canvas,svg,iframe, etc. - Tables:
table,thead,tbody,tfoot,tr,th,td, etc. - Semantic Elements:
details,summary,dialog,progress,meter,time, etc.
Check the HTML Element reference for the full list.
The Element type
The rsx! macro returns an object with the type of Element. These objects can be assigned to variables, cheaply cloned, and stored in state.
let header: Element = rsx! { div { h1 { "Dioxus!" } } }
We can even create functions that return an Element:
fn create_description(content: &str) -> Element { rsx! { span { class: "description", "{content}" } } }
Under the hood, the Element type is actually an alias for Result<VNode>. In Rust, a Result is an enumerated value that can either be an Ok(value) or an Err(error). This means we can match on an Element, or even throw errors while rendering it:
fn create_description(content: &str) -> Element { if content.is_empty() { return Err("Missing description".into()); } rsx! { span { class: "description", "{content}" } } }
Dioxus defines its own error based on the anyhow error which then composes with other utilities like Error Boundaries and Server Functions.