ZStack
ZStack is the layered layout primitive.
It paints children in order from back to front: the first child is at the bottom and the last child is on top. This makes it the right tool for layered cards, image-plus-badge compositions, full-screen overlays, floating controls, and other interfaces where depth matters.
Use ZStack when layering is the real structural idea. Do not use it as a replacement for ordinary rows and columns. If the relationship between children is really sequential rather than layered, a stack on the z axis will make the code harder to understand.
Example
use fission::prelude::*;
let widget: Widget = ZStack {
children: vec![
Text::new("Base layer").into(),
Positioned {
bottom: Some(8.0),
right: Some(8.0),
child: Some(Text::new("Badge").into()),
..Default::default()
}
.into(),
],
..Default::default()
}
.into();
Field table
| | | |
|---|
| | | |
| | Layered children, painted in order. | Defaults to an empty list. First child is bottom, last child is top. |
Layout behavior
ZStack sizes itself from its non-absolute children and then lays those children into the same bounds. Children wrapped in Positioned or absolute_fill(...) are treated specially by the layout engine as absolute children relative to the stack's bounds.
This is what makes ZStack the natural parent for corner badges, floating overlays, and full-surface scrims.
Specific advice
If you only need exactly two layers with a simple "main content plus top layer" relationship, Overlay is often easier to read. Use ZStack when you really need the general layered layout model.
Production checklist
For ZStack, review the fields that change behavior before treating the widget as finished: id, children. The goal is to make the product rule visible in state and actions, not hidden inside ad-hoc construction code.
If this widget appears inside an interactive flow, keep the surrounding action binding in the parent component and test that the flow still has one clear reducer path.
When child widgets are generated from data, give reordered or filtered rows an explicit WidgetId so retained local state and scroll behavior do not drift between items.
Set id only when identity must be stable across filtering, reordering, diagnostics, or tests; otherwise let Fission derive identity from structure.
Check the semantics tree for the user-facing label or role that makes this widget understandable without relying only on pixels.
Add at least one component or harness test that confirms the visible text, semantic role, action dispatch, and layout constraint that matter for this widget in context.
If a screen starts repeating the same ZStack setup, extract a named component around this widget. That keeps the reference API small while making product code easier to read and safer for generated code to copy.
Overlay, Positioned, and absolute_fill(...).