wgpu-html vs RmlUI — Capability Comparison
Date: 2026-05-03 Purpose: Comparison of two GPU-accelerated HTML/CSS UI rendering engines aimed at game/application UI. wgpu-html is a Rust alternative to the C++ RmlUI library.
Project Overview
| wgpu-html | RmlUI | |
|---|---|---|
| Language | Rust | C++ (C++17) |
| License | MIT | MIT |
| Architecture | Parser → Style Cascade → Layout → Paint → Renderer (5-stage pipeline) | Document → Style → Layout → Render (traditional UI engine) |
| GPU Backend | wgpu (Vulkan/Metal/DX12 via wgpu::Backends::PRIMARY) | OpenGL 2/3, Vulkan, SDL GPU, SDLrenderer, DirectX 12 (all optional backends) |
| Rendering Model | Display-list with draw commands (Quads + Glyphs + Images + Clip ranges) | Geometry generation (vertices, indices, textures) via RenderInterface |
| Font Engine | cosmic-text + CPU rasterization to glyph atlas | FreeType (replaceable via custom FontEngineInterface) |
| External Dependencies | wgpu, winit, cosmic-text, resvg, image, arboard | FreeType only (core). Optional: Lua, LunaSVG, rlottie, HarfBuzz |
| Target Use Case | Application UI, game HUD/menus, desktop tools | Game UI, embedded applications, installers, game menus |
| First Release | 2025–2026 (active development) | 2008 (as libRocket), forked as RmlUi in 2019 |
| Maturity | Alpha/beta — core pipeline works, some gaps | Production-grade — used in commercial games |
| Platforms | Windows, Linux, macOS (winit + wgpu) | Windows, Linux, macOS, Android, iOS, Switch, Emscripten |
| JavaScript | 🚫 Permanently out of scope | Not native; Lua plugin available |
Markup Language
| wgpu-html | RmlUI | |
|---|---|---|
| Format | Standard HTML5 (.html) | RML (XHTML1-like .rml) |
| Element Count | ~100 typed HTML element structs | ~20 custom elements + <script>/<lottie>/<svg> via plugins |
| HTML5 Semantic Tags | All major elements: <div>, <span>, <p>, <h1>–<h6>, <img>, <a>, <button>, <input> (22 types), <form>, <textarea>, <select>, <table>, <ul>/<ol>/<li>, etc. | Functional tags: <body>, <div>, <span>, <p>, <h1>–<h6>, <br>, <img>, <a>, <input>, <textarea>, <select>, <option>, <label>, <form> + custom |
| HTML Serialization | ✅ Node::to_html(), Tree::to_html() | ✅ InnerRML get/set |
| Entity Decoding | ✅ &, <, >, ", ', , &#NN;, &#xNN; | ✅ XML entities |
| Global Attributes | id, class, style, title, lang, hidden, tabindex, contenteditable, draggable, dir, accesskey, spellcheck, translate, role, aria-*, data-* | id, class, style, data-* |
CSS / RCSS Support
Selectors
| wgpu-html | RmlUI | |
|---|---|---|
Tag, #id, .class, universal * | ✅ | ✅ |
Descendant | ✅ | ✅ |
Comma-list A, B | ✅ | ✅ |
Child > | ❌ cascade only (✅ query engine) | ✅ |
Next-sibling + | ❌ cascade only (✅ query engine) | ✅ |
Subsequent-sibling ~ | ❌ cascade only (✅ query engine) | ✅ |
| Attribute selectors | ❌ cascade only (✅ query engine) | ✅ |
:hover / :active / :focus | ✅ cascade; :focus exact-match only | ✅ (+ propagates to parents) |
:focus-visible | ❌ cascade only (✅ query engine) | ✅ |
:checked, :disabled/:enabled | ❌ cascade only (✅ query engine) | ✅ (partial) |
:first-child/:last-child/:only-child | ❌ cascade only (✅ query engine) | ✅ |
:nth-child()/:nth-last-child() | ❌ cascade only (✅ query engine) | ✅ |
:nth-of-type()/:nth-last-of-type() | ❌ cascade only (✅ query engine) | ✅ |
:not() | ❌ cascade only (✅ query engine) | ✅ |
:is() / :where() / :has() | ❌ cascade only (✅ query engine) | ❌ |
:empty | ❌ | ✅ |
:placeholder-shown | ❌ cascade only (✅ query engine) | ✅ |
| Pseudo-elements | ❌ | ❌ |
!important | ✅ (4-band cascade) | ✅ (2-band cascade) |
| Specificity | (id<<16) | (class<<8) | tag | Standard CSS specificity (a,b,c) |
Cascade System
| wgpu-html | RmlUI | |
|---|---|---|
| UA stylesheet | ✅ (~50 rules) | ❌ (recommended stylesheet available separately) |
| Author stylesheet | ✅ (<style> blocks + <link> parsed) | ✅ (<link type="text/rcss"> + inline) |
| Inline style | ✅ (style="..." attribute) | ✅ |
| Inheritance | ✅ (color, font-, text-, visibility, cursor, pointer-events, user-select) | ✅ |
inherit / initial / unset | ✅ | ✅ |
@media queries | ✅ (width/height/orientation with min/max + not prefix) | ✅ (width, height, orientation, resolution, prefers-color-scheme, prefers-reduced-motion) |
| Dynamic pseudo recalc | ✅ Incremental re-cascade of dirty paths only | ✅ |
<link rel="stylesheet"> | ⚠️ Parsed but no HTTP fetch | ✅ File-based loading |
CSS Properties Summary
| Property Area | wgpu-html | RmlUI |
|---|---|---|
display | block, inline, inline-block, flex, grid, none | inline, block, inline-block, flow-root, flex, inline-flex, table, inline-table, table-row-group, table-row, table-column-group, table-column, table-cell, none |
position | static, relative, absolute, fixed | static, relative, absolute, fixed |
| Box Model | width/height, min-/max-, margin, padding, box-sizing, border | width/height, min-/max-, margin, padding, box-sizing, border |
float | ❌ Not parsed | ✅ left, right, none |
clear | ❌ | ✅ |
border-radius | ✅ Elliptical, per-corner H+V, CSS-3 corner clamping | ✅ Single-radius per corner only |
background-clip | ✅ border-box/padding-box/content-box | ❌ Uses decorators instead |
background-image | ✅ URL + tiling + rounded-clip | ❌ Uses decorators instead |
border-style | solid/dashed/dotted/none/hidden; double/groove/ridge/inset/outset→solid fallback | ❌ Not a property (only width+color) |
box-shadow | ❌ Parsed as raw string, never consumed | ✅ |
| Gradients | ❌ Parsed as raw string, skipped | ✅ Linear, radial, conic gradients via decorators |
opacity | ✅ (inherited multiplicatively) | ✅ |
visibility | ✅ | ✅ |
z-index | ❌ Parsed, not consumed (tree DFS paint order) | ✅ |
overflow / overflow-x / overflow-y | ✅ hidden/scroll/auto/visible | ✅ hidden/scroll/auto/visible |
pointer-events | ✅ auto/none | ✅ auto/none |
user-select | ✅ auto/none/text/all | ❌ Not applicable |
cursor | ✅ Parsed, not applied to OS cursor | ✅ (application-defined cursor names) |
transform | ❌ Parsed as raw string only | ✅ Full 2D/3D transforms with interpolation |
transition | ❌ Parsed as raw string only | ✅ Full transitions with tweening |
animation / @keyframes | ❌ Not parsed | ✅ Full keyframe animations |
filter | ❌ Not parsed | ✅ All CSS filter functions |
backdrop-filter | ❌ | ✅ |
mask-image | ❌ | ✅ |
text-overflow | ❌ | ✅ clip/ellipsis/custom string |
white-space | ✅ normal/pre | ✅ normal/pre/nowrap/pre-wrap/pre-line |
word-break | ❌ | ✅ normal/break-all/break-word |
Custom Properties --foo | ✅ Full var() with inheritance + cycle detection |