About this demo
Neural networks
with style...
...sheets. ONNX.css compiles a fixed-shape ONNX graph into a CSS stylesheet, then runs inference using your browser's style engine.
How it works:
- 01Decode
JavaScript reads the ONNX protobuf and resolves fixed tensor shapes, constants, weights, and graph topology.
model = decode(bytes) for (node of model.graph.node) css += expand(node) - 02Expand
Each tensor element in the graph becomes a typed CSS custom property. Operators become expressions referencing earlier properties.
--x0: 0; --x1: 0; --x2: max(0, calc(var(--x0) + var(--x1))); - 03Bind
Input numbers are written as inline custom properties on a hidden "engine" HTML element.
<div data-onnx-css-engine style="--x0:.7; --x1:-.2"></div> - 04Resolve
getComputedStyle()on the engine element triggers the browser to evaluate the dependency graph. The final properties are the model outputs.computed = getComputedStyle(engine) logits = ["--x3", "--x4"].map(name => Number(computed.getPropertyValue(name)))
Is this practically useful?
Not really :)
Real inference runtimes are faster, smaller, more precise, better supported, and easier to debug. Compiled CSS can grow to tens of megabytes for a tiny network, and not all ops are supported.
Regardless, it's cool that you can build a reactive numeric dataflow graph from CSS primitives. Once a model is flattened into scalar expressions, CSS functions provide the building blocks for neural network convolutions, activations, pooling, and matrix multiplication without JavaScript executing those operators.
Try your model
Fixed-shape .onnx protobuf
Models must use fixed tensor topology. Dynamic control flow, runtime-sized outputs, strings, sequences, and sparse or external tensors are not supported.
Compiled CSS
Waiting for a model
- 0
- nodes
- 0
- properties
- 0
- CSS size
Current coverage
Supported ONNX operators
Not all ONNX ops are supported, like those that require dynamic control flow.
AbsAddArgMaxArgMinAveragePoolBatchNormalizationCastClipConcatConstantConvDivEluEqualExpExpandFlattenGatherGemmGlobalAveragePoolGreaterGreaterOrEqualHardSigmoidHardSwishInstanceNormalizationLayerNormalizationLeakyReluLogMatMulMaxMaxPoolMinMulIdentityLessLessOrEqualNegNotPadPowReciprocalReduceL1ReduceL2ReduceMaxReduceMeanReduceMinReduceProdReduceSumReluReshapeSigmoidSoftmaxShapeSizeSoftplusSoftsignSqrtSqueezeSubSumTanhTileTransposeUnsqueezeSliceWhere