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.