The html! macro allows you to write HTML and SVG code declaratively. It is similar to JSX (an extension to JavaScript which allows you to write HTML-like code inside of JavaScript).

Important notes

  1. The html! macro only accepts one root html node (you can counteract this by using fragments or iterators)
  2. An empty html! {} invocation is valid and will not render anything
  3. Literals must always be quoted and wrapped in braces: html! { <p>{ "Hello, World" }</p> }
  4. The html! macro will make all tag names lower case. To use upper case characters (which are required for some SVG elements) use dynamic tag names: html! { <@{"myTag"}></@> }

HTML - 图1note

The html! macro can reach the default recursion limit of the compiler. If you encounter compilation errors, add an attribute like #![recursion_limit="1024"] in the crate root to overcome the problem.

Tag Structure

Tags are based on HTML tags. Components, Elements, and Lists are all based on this tag syntax.

Tags must either self-close <... /> or have a corresponding end tag for each start tag.

  • Open - Close
  • Invalid
  1. use yew::prelude::*;
  2. html! {
  3. <div id="my_div"></div>
  4. };
  1. use yew::prelude::*;
  2. html! {
  3. <div id="my_div"> // <- MISSING CLOSE TAG
  4. };
  • Self-closing
  • Invalid
  1. use yew::prelude::*;
  2. html! {
  3. <input id="my_input" />
  4. };
  1. use yew::prelude::*;
  2. html! {
  3. <input id="my_input"> // <- MISSING SELF-CLOSE
  4. };

HTML - 图2tip

For convenience, elements which usually require a closing tag are allowed to self-close. For example, writing html! { <div class="placeholder" /> } is valid.


Create complex nested HTML and SVG layouts with ease:

  • HTML
  • SVG
  1. use yew::prelude::*;
  2. html! {
  3. <div>
  4. <div data-key="abc"></div>
  5. <div class="parent">
  6. <span class="child" value="anything"></span>
  7. <label for="first-name">{ "First Name" }</label>
  8. <input type="text" id="first-name" value="placeholder" />
  9. <input type="checkbox" checked=true />
  10. <textarea value="write a story" />
  11. <select name="status">
  12. <option selected=true disabled=false value="">{ "Selected" }</option>
  13. <option selected=false disabled=true value="">{ "Unselected" }</option>
  14. </select>
  15. </div>
  16. </div>
  17. };
  1. use yew::prelude::*;
  2. html! {
  3. <svg width="149" height="147" viewBox="0 0 149 147" fill="none" xmlns="">
  4. <path d="M60.5776 13.8268L51.8673 42.6431L77.7475 37.331L60.5776 13.8268Z" fill="#DEB819"/>
  5. <path d="M108.361 94.9937L138.708 90.686L115.342 69.8642" stroke="black" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
  6. <g filter="url(#filter0_d)">
  7. <circle cx="75.3326" cy="73.4918" r="55" fill="#FDD630"/>
  8. <circle cx="75.3326" cy="73.4918" r="52.5" stroke="black" stroke-width="5"/>
  9. </g>
  10. <circle cx="71" cy="99" r="5" fill="white" fill-opacity="0.75" stroke="black" stroke-width="3"/>
  11. <defs>
  12. <filter id="filter0_d" x="16.3326" y="18.4918" width="118" height="118" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
  13. <@{"feGaussianBlur"} stdDeviation="2"/>
  14. <@{"feColorMatrix"} in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
  15. </filter>
  16. </defs>
  17. </svg>
  18. };


If you compile Yew using a nightly version of the Rust compiler, the macro will warn you about some common pitfalls that you might run into. Of course, you may need to use the stable compiler (e.g. your organization might have a policy mandating it) for release builds, but even if you’re using a stable toolchain, running cargo +nightly check might flag some ways that you could improve your HTML code.

At the moment the lints are mostly accessibility-related. If you have ideas for lints, please feel free to chime in on this issue.

Specifying attributes and properties

Attributes are set on elements in the same way as in normal HTML:

  1. use yew::prelude::*;
  2. let value = "something";
  3. html! { <div attribute={value} /> };

Properties are specified with ~ before the element name:

  1. use yew::prelude::*;
  2. html! { <my-element ~property="abc" /> };

HTML - 图3tip

The braces around the value can be ommited if the value is a literal.

HTML - 图4What classifies as a literal

Literals are all valid literal expressions in Rust. Note that negative numbers are not literals and thus must be encosed in curly-braces {-6}

HTML - 图5Component properties

Component properites are passed as Rust objects and are different from the element attributes/properties described here. Read more about them at Component Properties

Special properties

There are special properties which don’t directly influence the DOM but instead act as instructions to Yew’s virtual DOM. Currently, there are two such special props: ref and key.

ref allows you to access and manipulate the underlying DOM node directly. See Refs for more details.

key on the other hand gives an element a unique identifier which Yew can use for optimization purposes.

HTML - 图6info

Read more at Lists

Conditional Rendering

Markup can be rendered conditonally by using Rust’s conditional structures. ‘ + ‘Currently only if and if let are supported.

  1. use yew::prelude::*;
  2. html! {
  3. if true {
  4. <p>{ "True case" }</p>
  5. }
  6. };

HTML - 图7info

Read more at Conditonal Rendering