Styling
Every component takes the same flat style object RN components take
(ViewStyle/TextStyle/ImageStyle, all aliases of one style bag on this
platform). The pipeline splits that object in two: StyleSheet.flatten →
splitStyle divides it into a layout half and a visual half. Layout
keys go to the Yoga engine (LayoutNodeApi.setStyle) and never reach CSS;
visual keys are turned into GTK CSS (visualStyleToCss) and applied through a
memoized class registry, one class per unique declaration. overflow is the
one key that crosses both halves — see below.
Layout fidelity is exact: every container runs its own layout manager that
obeys only what Yoga computes, so a GTK widget's own minimum size never leaks
into the layout, a window shrinks as freely as Yoga allows, and
Dimensions.get("window") reports the same thing RN's app window reports —
the window's content area under its header bar.
A property's status is one of:
- supported — works fully;
- partial — works, with the caveat in its note;
- ignored — outside the frozen style contract; a value is accepted, a warning fires once per key, and the value is dropped.
Layout (routed to Yoga)

alignContent, alignItems, alignSelf, aspectRatio, bottom,
columnGap, direction, display, flex, flexBasis, flexDirection,
flexGrow, flexShrink, flexWrap, gap, height, justifyContent,
left, margin, marginBottom, marginHorizontal, marginLeft,
marginRight, marginTop, marginVertical, maxHeight, maxWidth,
minHeight, minWidth, overflow, padding, paddingBottom,
paddingHorizontal, paddingLeft, paddingRight, paddingTop,
paddingVertical, position, right, rowGap, top, width — all
supported, with behavior defined by the layout engine itself.

overflow is the one key that does not stop at Yoga: Yoga needs it while
measuring (a scroll node's main axis is unconstrained), and the widget needs
it to clip. GTK4 CSS has no overflow property, so this is a direct widget
call rather than a CSS declaration — the only style outside transform whose
GTK half is not CSS. hidden clips paint and hit-testing to the widget's CSS
padding box, rounded by borderRadius; scroll clips the same way and adds
no scrolling of its own — matching RN, where only a ScrollView scrolls;
visible (the default) lets children paint past the container, as in RN.
Visual (routed to GTK CSS)
backgroundColor— supported:background-color.opacity— supported:opacity, clamped to[0, 1].boxShadow— supported:box-shadow, from either RN form — a CSS string or aBoxShadowValue[]array. A string is parsed rather than forwarded, so colors go through the same color parser (aPlatformColorworks inside a shadow) and a malformed shadow is dropped with one development warning instead of corrupting the declaration block. Lengths follow RN's own grammar — a bare number orpx, nothing else; blur may not be negative. Differs from react-native: an omittedcolorrenders as black, notcurrentColor— RN's own documented deviation from CSS, kept here on purpose. Shadow order is CSS's: the first one paints on top.outlineWidth— supported:outline-width; an unsetoutlineStylebecomessolidautomatically once the width is greater than 0 (GTK, like the web, otherwise defaults tonone). Takes no layout space, so unlikeborderWidthit never reaches Yoga.outlineColor/outlineOffset/outlineStyle— supported:outline-color/outline-offset(px, negative allowed) /outline-style(solid/dotted/dashed); an explicit style always wins over the automatic solid.borderWidth— supported:border-width; an unsetborderStylebecomessolidautomatically once any border width is greater than 0 (GTK otherwise defaults tonone).borderTopWidth/borderRightWidth/borderBottomWidth/borderLeftWidth— supported: per-sideborder-*-width, emitted after the shorthand and overriding it; each also triggers the automatic solid style.borderColor— supported:border-color; with no width the border stays invisible, since the default width is 0, as in RN.borderTopColor/borderRightColor/borderBottomColor/borderLeftColor— supported: per-sideborder-*-color, emitted after the shorthand and overriding it.borderStyle— supported:border-style(solid/dotted/dashed); an explicit value wins over the automatic solid.borderRadius— supported:border-radius.borderTopLeftRadius/borderTopRightRadius/borderBottomRightRadius/borderBottomLeftRadius— supported: per-cornerborder-*-radius, emitted after the shorthand and overriding it.color— supported:color.fontFamily— supported:font-family(a name containing spaces is quoted).fontSize— supported:font-size, in px.fontStyle— supported:font-style.fontWeight— supported:font-weight(both keyword and numeric-string forms,"100"–"900").letterSpacing— supported:letter-spacing, in px.lineHeight— partial:line-height, in px (GTK ≥ 4.6). Matches RN's "line height in points" semantics; RN's multiplier form is not supported.textAlign— partial: applied byTextdirectly rather than through CSS, since GTK4 CSS has notext-align— resolved to a label's ownxalign/justificationproperties.textDecorationLine— partial: applied byTextdirectly rather than through CSS, since GTK4 has no widget-leveltext-decoration— resolved to Pango's ownunderline/strikethroughattributes, which also reserve room below the baseline for an underline where one is measured.transform— partial: never reaches CSS (GTK4 has no widgettransformproperty) — the array is folded into one matrix and handed to the container's own allocation.translateX/translateY,scale,scaleX,scaleY,rotate/rotateZonly; no 3D, no skew, nomatrix, notransformOrigin— see Components.
Colors
| Format | Status | Note |
|---|---|---|
named colors (CSS Color 4), transparent | supported | normalized to rgb()/rgba() |
#rgb / #rgba / #rrggbb / #rrggbbaa | supported | normalized to rgb()/rgba() |
rgb() / rgba() | supported | both comma and space syntax (rgb(255 0 0 / 0.5)); channels as numbers or percentages |
hsl() / hsla() | supported | hue as a number or with deg; saturation/lightness strictly as percentages; converted to rgb()/rgba() |
PlatformColor("accent-bg-color", ...) | supported | resolves to var(--accent-bg-color, ...) — Adwaita theme variables (libadwaita ≥ 1.6); @name reaches a legacy GTK named color as the fallback |
var(--...) / @name as a plain string | supported | passed through without normalization |
| an invalid string | ignored | the color parses to nothing; the declaration is dropped, with one development warning per distinct value |
Not part of the style contract
Any key outside LayoutStyle/VisualStyle/BehavioralStyle — elevation,
filter, mixBlendMode, textTransform, tintColor, and the like — is
accepted, warned about once per key, and dropped. pointerEvents and
zIndex are BehavioralStyle: each is read by the component that implements
the behavior, not by either half of this pipeline (see
Components for both).