W3C CSS Alignment
Silvery's layout engine follows W3C CSS Flexbox specifications more closely than Ink/Yoga in several key areas, while making intentional adaptations for terminal environments.
More CSS-Correct Than Ink/Yoga
flexShrink Defaults to 1
The CSS Flexbox spec (W3C CR) defines flex-shrink with an initial value of 1. Silvery follows this:
// Silvery: items shrink by default (CSS spec behavior)
<Box flexDirection="row" width={20}>
<Box width={15}>
<Text>Shrinks</Text>
</Box>
<Box width={15}>
<Text>Shrinks</Text>
</Box>
</Box>
// Both items shrink proportionally to fit 20 columnsYoga (used by Ink and React Native) defaults flexShrink to 0, meaning items overflow their container by default. This is a deliberate deviation from the CSS spec that React Native chose for mobile layouts, but it creates surprising behavior in terminal UIs where overflow is often invisible.
// Ink/Yoga: items overflow by default (flexShrink: 0)
<Box flexDirection="row" width={20}>
<Box width={15}>
<Text>Overflows</Text>
</Box>
<Box width={15}>
<Text>Overflows</Text>
</Box>
</Box>
// Total 30 columns in a 20-column container -- content clipsoverflow: hidden with flexShrink: 0
CSS section 4.5 specifies that the automatic minimum size of a flex item is 0 when overflow is not visible. This means overflow: hidden combined with flexShrink: 0 produces a box that respects its container's bounds.
Silvery follows this behavior. Yoga does not consistently apply the auto minimum size rule, which can cause items to overflow their containers even when clipping is expected.
// Silvery: overflow hidden + flexShrink 0 works as CSS spec dictates
<Box height={10}>
<Box flexShrink={0} overflow="hidden" height={20}>
<Text>Clipped content that respects parent bounds</Text>
</Box>
</Box>Position Offsets
Silvery supports position="absolute" and position="relative" as layout properties, matching CSS positioning:
<Box position="relative" width={40} height={10}>
<Text>Background content</Text>
<Box position="absolute">
<Text>Overlaid content</Text>
</Box>
</Box>Silvery also extends CSS positioning with position="sticky" for scroll containers and normal parents, including stickyTop and stickyBottom offsets.
Overflow Modes
CSS defines three overflow values. Silvery supports all three:
<Box overflow="visible"> {/* Default: content extends beyond bounds */}
<Box overflow="hidden"> {/* Content clipped at box boundaries */}
<Box overflow="scroll"> {/* Content clipped with scroll support */}Ink supports only visible and hidden. Scrolling -- the #1 feature request since 2019 -- requires manual virtualization.
CSS-Aligned Defaults
flexDirection Defaults to row
CSS defaults flex-direction to row (horizontal). Silvery follows the W3C CSS spec here:
// Horizontal row (silvery default -- no prop needed)
<Box>
<Text>Left</Text>
<Text>Right</Text>
</Box>
// Vertical stack (explicit)
<Box flexDirection="column">
<Text>Top</Text>
<Text>Bottom</Text>
</Box>This aligns with both the CSS spec and Ink's behavior.
Box-in-Text Nesting
CSS strictly separates block and inline formatting contexts. A <div> inside a <span> is technically invalid HTML. Silvery is more permissive: nesting a Box inside Text produces a warning rather than an error, since terminal layouts frequently mix block and inline content in ways that would violate strict W3C rules.
Comparison Table
| Property | CSS Spec | Silvery | Ink/Yoga |
|---|---|---|---|
flexShrink default | 1 | 1 | 0 |
flexDirection default | row | row | row |
overflow values | visible, hidden, scroll, auto | visible, hidden, scroll | visible, hidden |
Auto min-size when overflow: hidden | 0 (CSS 4.5) | Follows spec | Inconsistent |
position values | static, relative, absolute, fixed, sticky | relative, absolute, sticky | relative, absolute |
gap | Supported | Supported | Not supported (Ink) |
display: none | Supported | Supported | Supported |
flexWrap | Supported | Supported | Supported |
alignItems / justifyContent | Supported | Supported | Supported |
Reading the Table
- Silvery matches CSS spec on
flexShrink, overflow behavior, and auto minimum sizing. - Silvery matches CSS on
flexDirection: rowdefault. The only TUI adaptation is permissive nesting. - Ink/Yoga deviates from CSS on
flexShrinkdefault (React Native convention), lacks scroll overflow, and does not supportgap.
For Ink Migrators
Import from silvery/ink to get Ink-compatible defaults (flexShrink: 1). Silvery and Ink now share the same flexDirection: row default.