Sizing custom widgets
You may have noticed that every custom widget chapter sets flex: templateData.size on the widget’s host element. That single line is what lets your widget participate in the Flex layout’s sizing system — without it, a custom widget inside a flex container won’t honour size: 1, size: 2, etc.
This page explains the why, and clarifies when you don’t need it.
The two layout systems
Section titled “The two layout systems”GolemUI ships two layout widgets that arrange children differently:
- Flex — children share space along a main axis using CSS
flex. Each child’ssizebecomes itsflexvalue. - Grid — children land in named grid cells using CSS Grid. Sizing is decided by the grid template, not by the child.
Built-in widgets read templateData.size automatically; the framework adapters apply it to the rendered element. Custom widgets opt in explicitly — the engine sets size on templateData, but only your render code can apply it to the DOM.
Inside a Flex parent
Section titled “Inside a Flex parent”When the parent is gui.layouts.flex(...), the rendered <form-flex> element is a CSS flex container. Every direct child is a flex item, so any custom widget you drop in there needs a CSS flex value that matches what the form definition asked for. That’s exactly what templateData.size carries — the engine resolves the widget’s size prop (defaulting to 1) and exposes it through templateData.
So in every chapter you’ll see one of these:
<div className="my-widget" style={{ flex: templateData.size }}> {/* widget body */}</div>@Component({ host: { '[style.flex]': 'this.adapter.templateData().size', }, // ...})override connectedCallback() { super.connectedCallback(); this.classList.add('my-widget'); // ...}
// and in your CSS:// :host { flex: var(--size, 1); }// — or set style.flex programmatically from templateData.size.The Lit examples in this section read templateData.size and bind flex directly on the host element instead of via CSS variables — either is fine.
<template> <div class="my-widget" :style="{ flex: templateData.size }"> <!-- widget body --> </div></template>override connectedCallback() { super.connectedCallback(); this.classList.add('my-widget'); this.style.flex = String(this.adapter.templateData.size ?? 1); // Re-apply on every templateData change so size overrides stay live: this.subscriptions.push( this.adapter.templateDataChanged$.subscribe(() => { this.style.flex = String(this.adapter.templateData.size ?? 1); }), );}
// and in your CSS:// .my-widget { /* base styles */ }Read templateData.size (default 1) and assign it to this.style.flex on the host element. Subscribe to templateDataChanged$ so size overrides from prop-state mappings stay applied as the form state changes.
That single line is what lets a consumer write:
gui.layouts.flex([ gui.inputs.custom('productRating', 'rating', { size: 1 }), gui.actions.custom('productShare', { size: 2, onClick: 'shareEvent' }),]);{ "kind": "layout", "type": "flex", "children": [ { "kind": "input", "type": "productRating", "path": "rating", "props": { "size": 1 } }, { "kind": "action", "type": "productShare", "props": { "size": 2 }, "on": { "click": "shareEvent" } } ]}…and have the rating widget take 1 part of the row while the share widget takes 2.
Inside a Grid parent
Section titled “Inside a Grid parent”When the parent is gui.layouts.grid(...), sizing flips. The grid widget itself owns the column template — each child lands in a cell that’s been pre-sized by the grid, so the child shouldn’t try to grow into the row.
You can leave flex: templateData.size in your widget code; it just has no visual effect inside a grid because the parent isn’t a flex container. There’s no harm and no need for branching — write the line once and your widget works in both layouts.
Skipping size entirely
Section titled “Skipping size entirely”The only widgets that genuinely don’t need to read size are ones that are never rendered as a flex item — for example, a widget that always lives at the form root and stretches to 100% width. In practice that’s rare, and reading templateData.size costs nothing. When in doubt, include it.
See also
Section titled “See also”- Flex layout — the widget that gives
sizemeaning. - Grid layout — the alternative that ignores
size. - Custom Widgets Overview — the full Product Card example.