Expand description
§bevy_markup — HTML + CSS + Fluent + Tera as Bevy UI
Write UI as HTML templates; get Bevy UI nodes.
.html (Tera template) ──render(TemplateContext)──▶ HTML ──tl──▶ DOM
──Fluent (data-l10n-id, ActiveLocale)──▶ localized DOM
──CSS (DefaultStylesheet / HtmlStylesheet, FontFamilies)──▶ Bevy UI nodes§Quick start
use bevy::prelude::*;
use bevy_markup::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, BevyMarkupPlugin))
.add_systems(Startup, setup)
.run();
}
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut fonts: ResMut<FontFamilies>,
) {
commands.spawn(Camera2d);
// CSS `font-family: Spectral` → these files.
fonts.insert(
"Spectral",
FontFaces::new(asset_server.load("fonts/Spectral-Regular.ttf"))
.with_bold(asset_server.load("fonts/Spectral-Bold.ttf")),
);
// Applies to every `HtmlUi` without its own `HtmlStylesheet`.
commands.insert_resource(DefaultStylesheet::new(asset_server.load("ui/theme.css")));
// `data-l10n-id` attributes resolve against this Fluent bundle.
commands.insert_resource(ActiveLocale::new(
asset_server.load("locales/en-US/main.ftl.ron"),
));
// One component: the template. `Node`, `TemplateContext`, … are required
// components; override any of them in the same bundle.
commands.spawn((
HtmlUi::new(asset_server.load("ui/hud.html")),
TemplateContext::new().with("player", "Ada").with("coins", &3),
Node { flex_direction: FlexDirection::Column, ..default() },
));
}Mutating TemplateContext re-renders; swapping
ActiveLocale re-localizes; swapping
DefaultStylesheet restyles — all at runtime.
After every (re)build an HtmlUiBuilt event fires on
the HtmlUi entity; use HtmlElements to find
elements by id/class and attach behaviour. Style-only changes
(stylesheets, fonts) restyle the existing children in place and fire
HtmlUiRestyled instead, keeping what you attached.
§Supported subset
- HTML (
html): blocksh1–h6,p,li,pre, loose text; containersdiv,section,ul, … as nested column nodes; other elements are inline text (inside a block) or walked through. Each block becomes aTextnode with aTextSpanper styled run; blocks and containers carry anHtmlElement(tag, id, classes). - CSS (
style): type,.class,#idand compound selectors with specificity;color,font-family,font-size,font-weight,font-style(inherited);border-image(9-slice),border-width,padding,background-coloron blocks, containers and theHtmlUinode (htmlrule, except background);gapon containers; flex layout, sizes, margins andbox-sizingon blocks and containers. - Fluent (
l10n):data-l10n-id/data-l10n-args/data-l10n-name(fluent-dom convention) on any element; translations may contain inline markup. - Tera (
template): full Tera 2 syntax in.htmlfiles, rendered with the entity’sTemplateContext. - 9-slice frames: in CSS via
border-image(seestyle), or for nodes outside HTML via*.slice.ronassets andNineSliceFrame(nine_slice).
§Cargo features
system_fonts: fall back to installed system fonts per script (e.g. CJK) when the chosen font lacks glyphs.
Re-exports§
pub use bevy_fluent;pub use lightningcss;pub use tera;pub use tl;
Modules§
- fonts
- Font families for CSS
font-family. - html
- The
HtmlUicomponent and what it produces. - l10n
- Fluent localization of HTML via
data-l10n-id/data-l10n-args, the attribute convention from Fluent’s DOM bindings (fluent-dom): - nine_
slice - 9-slice styles as assets, for nodes outside HTML. Inside HTML, use CSS
border-imageinstead (seecrate::style). - prelude
- Everything needed to build HTML UIs:
use bevy_markup::prelude::*;. - style
.cssstylesheets and how they’re assigned.- template
.htmlfiles as Tera templates, and the parsed result.
Structs§
- Bevy
Markup Plugin - Adds the asset loaders (
.html,.css,*.slice.ron, Fluent’s*.ftl.ron), theDefaultStylesheet,ActiveLocaleandFontFamiliesresources, and the systems that turnHtmlUientities into Bevy UI.
Enums§
- Html
UiSystems - Pipeline stages, in
PostUpdatebefore Bevy UI layout (chained in this order). Order your systems against these to see a stage’s output the same frame.