Unity UPM package that imports HTML/CSS into UI Toolkit UXML/USS and ships the runtime bridge elements, custom filters, shaders, and rendering resources needed to display the conversion output faithfully.
Package id: au.com.oddgames.html2uxml
Use Unity Package Manager's Add package from git URL option:
https://github.com/oddgames/html2uxml.git#v0.1.0
Or add it directly to Packages/manifest.json:
{
"dependencies": {
"au.com.oddgames.html2uxml": "https://github.com/oddgames/html2uxml.git#v0.1.0"
}
}{
"dependencies": {
"au.com.oddgames.html2uxml": "file:C:/Workspaces/html2uxml"
}
}ODDGames.Html2Uxml.Html2UxmlPanel- Renders bridged CSS features that Unity USS does not cover directly:
inset and multi-layer
box-shadow,linear-gradient(...),radial-gradient(...), axis-alignedrepeating-linear-gradient(...)patterns, tiled radial dot fields,clip-path: polygon(...), and complex linearmask-imageedge fades. - Simple outer
box-shadow,filter: drop-shadow(...), and two-stop percentage linear masks use package custom filter assets instead of panel promotion. - CSS gradients use the package mesh renderer, including one linear layer plus two radial layers. This avoids assigning hand-written materials that Unity rejects as non-UITK-compatible.
- Supports up to eight inset or multi-layer shadow records for glows, bevel, and emboss. These remain approximations, not full browser shadow compositing.
- Static CSS variables can resolve before parsing bridged gradients, shadows, filters, clip paths, and mask fades. Runtime custom property changes and variables that resolve to unsupported syntax are still outside the package contract.
- Native Unity 6.3
filterfunctions such asblur(...)pass through as USS.drop-shadow(...),brightness(...),saturate(...), and simple masks use package custom filter assets.
- Renders bridged CSS features that Unity USS does not cover directly:
inset and multi-layer
- ODD runtime element types
- Converted UXML emits ODD subclasses for core UI Toolkit elements:
Html2UxmlElement,Html2UxmlLabel,Html2UxmlButton,Html2UxmlScrollView, fields, toggles, dropdowns, foldouts, and progress/group containers. Html2UxmlElementinherits the paint-capable panel path. Typed controls install dormant manipulators for animation and lightweight paint hooks without scanning the visual tree.
- Converted UXML emits ODD subclasses for core UI Toolkit elements:
- CSS animation bridge
@keyframesandanimationare bridged foropacity,translate,scale,rotate,color, andbackground-color.- The runtime uses one shared ticker for active animated elements. Elements
with no
--odd-animation-*custom properties do not tick. - The bridge is implemented as
Manipulatorclasses attached by the ODD element constructors, not as hidden overlay children.
ODDGames.Html2Uxml.Html2UxmlButton- Button subclass used when a converted
<button>needs runtime bridge behavior such as flexgapwhile still being queryable as a normalButtonby controllers.
- Button subclass used when a converted
- Flex
gap- Static converted containers bake
gap,row-gap, andcolumn-gapinto generated child margins where possible, avoiding runtime custom elements. - Elements that already need
Html2UxmlPanelfor paint effects can still apply gap through the same--odd-row-gap/--odd-column-gapruntime path.
- Static converted containers bake
ODDGames.Html2Uxml.ShaderPanel- Material-backed UI Toolkit quad for authored shader fills and complex gradients that should not be approximated with geometry.
- Can instantiate package material templates with
material-resource="ODDGames/html2uxml/Materials/ODDGamesComplexGradient".
ODDGames.Html2Uxml.BackdropBlurPanel- RenderTexture/camera-backed frosted glass panel using the bundled Gaussian blur shader. The project supplies the camera or render texture that represents the backdrop.
capture-each-framedefaults tofalse. CallRefresh()after a meaningful backdrop change, or explicitly enable per-frame capture only for live blur effects.
ODDGames.Html2Uxml.BackdropCaptureSource- Optional scene component for shared live backdrop blur. It captures and
blurs one source camera/render texture, then
BackdropBlurPanelinstances can sample it withsource-id="<id>". CaptureEachFramealso defaults tofalse; callRefresh()for static captures or set it totruefor live camera-backed blur.- Use this for several frosted panels over the same scene instead of enabling a per-panel capture loop.
- Optional scene component for shared live backdrop blur. It captures and
blurs one source camera/render texture, then
ODDGames.Html2Uxml.UXMLController- Base MonoBehaviour for generated UI controllers.
- Owns UIDocument setup, delayed visual-tree wiring, callback unwiring, and transient Unity object disposal.
- Package assets
- Reusable material templates ship inside
Runtime/Resources/ODDGames/html2uxml/Materials. - The
ODDGamesColorAdjust,ODDGamesBoxShadow, andODDGamesLinearMaskfilter definitions ship insideRuntime/Filters, referencing package materials. Generated USS references them through package paths; no project-local filter assets are generated underAssets/ODDGames.
- Reusable material templates ship inside
HTML conversion is manual and runs in the Editor. With one or more .html /
.htm files selected in the Project window, either:
- Use the HTML to UXML panel in the Inspector header (toggles for font download, TextCore SDF font bake, and bundle layout, plus a Convert button), or
- Right-click ▸ Convert HTML to UXML.
Each conversion's outcome (timestamp, warnings, errors, and resulting
.uxml / .uss paths) is cached under Library/Html2UxmlResults/ and
re-rendered in the inspector panel after domain reloads, so failures don't
get lost in the Console.
Converted UXML that uses bridged CSS emits:
xmlns:odd="ODDGames.Html2Uxml"and uses ODD element types. Complex static paint uses the paint-capable
Html2UxmlPanel / Html2UxmlElement path; typed controls use manipulators
for bridge behavior.
Current converter output emits ODD element subclasses for all supported
HTML/UI Toolkit element mappings, so generated UXML depends on this package
even when a screen does not contain a gradient or shadow bridge.
The package must compile before Unity imports those UXML files. If UI Builder
shows Unknown Type Html2Uxml..., first clear any package compile errors, then
reimport the UXML or reopen the project.
Use a shared capture when several panels need live frosted glass over the same scene:
var source = gameObject.AddComponent<BackdropCaptureSource>();
source.SourceId = "main";
source.SourceCamera = Camera.main;
source.CaptureEachFrame = true;Then reference it from UXML:
<odd:BackdropBlurPanel source-id="main" use-screen-space-uv="true" />The source captures and blurs once; each panel draws one screen-space shader quad sampling that shared texture.
Generated controllers should derive from UXMLController:
using UnityEngine;
using UnityEngine.UIElements;
using ODDGames.Html2Uxml;
public partial class MyScreenController : UXMLController
{
[SerializeField] VisualTreeAsset visualTree;
Button closeButton;
protected override void ConfigureDocument(UIDocument doc)
{
if (visualTree != null)
doc.visualTreeAsset = visualTree;
}
protected override bool WireUI(VisualElement root)
{
closeButton = root.Q<Button>("closeButton");
if (closeButton == null)
return false;
WireClick(closeButton, OnCloseClicked);
return true;
}
private void OnCloseClicked()
{
Close();
}
partial void Close();
}Put hand-written behavior in a separate partial class file so generated controllers can be replaced safely.
Long-form documentation lives in Documentation~/ (the trailing tilde is the
Unity UPM convention for files Unity should not import as project assets):
Documentation~/design-guide.md— source-authoring contract and conversion rules.Documentation~/unity-ui-toolkit-rendering.md— Unity rendering and shader notes.Documentation~/unsupported.md— browser CSS support matrix and bridge behavior.
Copyright (c) 2026 ODD Games. All rights reserved. This package is
proprietary — see LICENSE.md for terms.
Bundled precompiled .NET libraries (AngleSharp, ExCSS) under
Editor/Plugins/ ship under the MIT licence. Their copyright notices and
full licence text are in
Editor/Plugins/THIRD-PARTY-NOTICES.md.