API

Style reference

This page lists every key of the style prop, and the method of Styled that sets it in Rust. Rust components style elements with typed methods named after Tailwind’s utilities (.p_4(), .rounded(px(12.0)), .bg(color), from nsh_core::ui::prelude), which lower to the same keys; TSX passes style objects (and classes). The Rust column names the method; a value, a signal or a closure goes to most of them, and .style_when(…) / .style_with(…) make any of them conditional. The keys and their types come from the generated declarations in .nsh/types/nsh/types.d.ts, so your editor checks them as you type. Layout is flexbox with a column default, numbers are points, and the CSS features are there too: grid, gradients, box shadows, filters, blend modes, outlines, transitions and keyframe animations.

For how to apply styles, combine them with classes and inherit text styles, see Styling. For the class syntax, see the Tailwind reference.

#The four interfaces

Each interface extends the one before it:

InterfaceExtendsUsed by
LayoutStyleLayout of every element (flexbox, grid, sizes, spacing, position)
ViewStyleLayoutStyle<View>, <Scroll>, <List>, controls and every other element
TextStyleViewStyle<Text> and <Input> (and views, whose text styles pass to the text inside them)
ImageStyleViewStyle<Image>
use nsh_core::ui::prelude::*;

fn card() -> View {
    view().p_4().rounded(px(12.0)).bg(white()).shadow([BoxShadow {
        offset_y: px(4.0),
        blur: px(12.0),
        color: rgba(0x00000014).into(),
        ..BoxShadow::default()
    }])
}

fn title(label: &str) -> Text {
    text(label.to_string()).text_size(px(17.0)).font_weight(FontWeight::SEMIBOLD).text_color(rgb(0x111111))
}

card().child(title("Hello"))

style also takes an array; entries merge left to right and falsy entries are skipped, so conditional styles need no spreading. In Rust, .style_when(condition, …) adds styles while the condition holds:

card().style_when(selected, |s| s.border_color(rgb(0x2563eb)).border(px(2.0)))

#Value types

TypeAcceptsRust
numberPoints (density-independent). 1 is one point on iOS and one dp on Android.Points: px(16.0)
DimensionValuenumber (points), `${number}%` (of the parent), or "auto".Length: px(…), relative(0.5), auto()
LengthValuenumber (points) or `${number}%`. No "auto".DefiniteLength: px(…), relative(0.5)
ColorValueA CSS color string: #rgb, #rgba, #rrggbb, #rrggbbaa, rgb(), rgba(), hsl(), hsla(), oklch(), oklab(), or a named CSS color (black, white, transparent, rebeccapurple, …).Hsla / AdaptiveColor: rgb(0x2563eb), hsla(…), theme colors (theme().primary)
AnimatedNodeA native animated value or a node derived from it (see nsh/animated). Accepted by backgroundColor, opacity and the steps of transform; the value then animates on the UI thread without JS.AnimatedValue / AnimatedNode, bound with .bind_opacity(&v), .bind_background(&v), .bind_translate_x(&v), …

Strings with CSS syntax (boxShadow, backgroundImage, filter, gridTemplateColumns, …) take lengths in px and bare numbers (both points), pt, or rem (16 points).

#LayoutStyle

Layout is computed in Rust (flexbox and CSS grid). The defaults differ from CSS’s: display: "flex", flexDirection: "column", flexShrink: 0, alignContent: "flex-start" (grids: CSS’s "normal"), alignItems: "stretch", and no automatic minimum size. See Layout.

#Display and position

KeyTypeRustDescription
display"flex" | "grid" | "block" | "none".flex(), .grid(), .hidden()The layout of the children. "none" removes the element from layout and hides it. "block" stacks children as CSS block layout does. Default "flex".
position"relative" | "absolute".relative(), .absolute()"absolute" takes the element out of the flow and places it by top / right / bottom / left relative to its parent. Default "relative".
topDimensionValue.top(…), .inset(…)Offset from the parent’s top edge (absolute) or from the element’s own position (relative).
rightDimensionValue.right(…)Offset from the right edge. In right-to-left layouts it means the end edge.
bottomDimensionValue.bottom(…)Offset from the bottom edge.
leftDimensionValue.left(…)Offset from the left edge. In right-to-left layouts it means the start edge.
startDimensionValueLeft in left-to-right layouts, right in right-to-left ones.
endDimensionValueRight in left-to-right layouts, left in right-to-left ones.
zIndexnumber.z_index(z)Order among siblings (stable for equal values); also the native stacking order.
direction"inherit" | "ltr" | "rtl"Layout direction, inherited by default. Right to left, left and right properties mean start and end.

#Flexbox

KeyTypeRustDescription
flexDirection"row" | "column" | "row-reverse" | "column-reverse".flex_row(), .flex_col(), .flex_row_reverse(), .flex_col_reverse()The main axis. Default "column".
flexWrap"wrap" | "nowrap" | "wrap-reverse".flex_wrap()Whether children wrap onto several lines. Default "nowrap".
flexnumber.flex_1(), .flex_auto(), .flex_none()One number, not the CSS shorthand: a positive number sets flexGrow to it, flexShrink: 1 and flexBasis: 0; 0 makes the element inflexible; a negative number shrinks it down to its minimum size.
flexGrownumber.flex_grow(f)How much of the free space the element takes. Default 0.
flexShrinknumber.flex_shrink(f), .flex_shrink_0()How much the element shrinks when space runs out. Default 0, not 1 as in CSS.
flexBasisDimensionValue.basis(…)The main-axis size before free space is distributed.
justifyContent"flex-start" | "flex-end" | "start" | "end" | "center" | "space-between" | "space-around" | "space-evenly" | "stretch" | "normal".justify_start(), .justify_center(), .justify_end(), .justify_between(), .justify_around(), .justify_evenly()Distribution of children along the main axis. Default "normal": "flex-start" in flex containers; in grids, tracks sized auto stretch.
alignItems"flex-start" | "flex-end" | "start" | "end" | "self-start" | "self-end" | "center" | "stretch" | "baseline" | "normal".items_start(), .items_center(), .items_end(), .items_stretch(), .items_baseline()Alignment of children on the cross axis. Default "stretch".
alignSelf"auto" | "flex-start" | "flex-end" | "start" | "end" | "self-start" | "self-end" | "center" | "stretch" | "baseline" | "normal".self_start(), .self_center(), .self_end(), .self_stretch()Overrides the parent’s alignItems for this element.
alignContent"flex-start" | "flex-end" | "start" | "end" | "center" | "stretch" | "space-between" | "space-around" | "space-evenly" | "normal"Distribution of wrapped lines (and grid tracks) on the cross axis. Default "flex-start" in flex containers and "normal" in grids, where tracks sized auto stretch. "start" / "end" follow the writing direction.
gapLengthValue.gap(…), .gap_4()Space between rows and columns of children.
rowGapLengthValue.gap_y(…)Space between rows.
columnGapLengthValue.gap_x(…)Space between columns.

#Grid

Set display: "grid" to lay out children in a CSS grid. Track lists use CSS syntax.

KeyTypeRustDescription
gridTemplateColumnsstring.grid_template_columns(…), .grid_cols(n)Column tracks: "repeat(3, 1fr)", "200px 1fr", minmax(), auto-fill / auto-fit, line names ("[a] 40px [b c] 1fr [d]").
gridTemplateRowsstring.grid_template_rows(…), .grid_rows(n)Row tracks, same syntax.
gridAutoColumnsstringSize of implicitly created columns.
gridAutoRowsstringSize of implicitly created rows.
gridAutoFlow"row" | "column" | "dense" | "row dense" | "column dense".grid_flow_col(), .grid_flow_dense()How items without a placement fill the grid.
gridColumnnumber | string.col_span(n), .col_span_full()Column placement: "1 / 3", "span 2", a line number or a line name ("content-start / content-end", "2 col", "span col").
gridColumnStartnumber | string.col_start(…)Start column line.
gridColumnEndnumber | string.col_end(…)End column line.
gridRownumber | string.row_span(n), .row_span_full()Row placement, same syntax as gridColumn.
gridRowStartnumber | string.row_start(…)Start row line.
gridRowEndnumber | string.row_end(…)End row line.
justifyItems"flex-start" | "flex-end" | "start" | "end" | "self-start" | "self-end" | "center" | "stretch" | "baseline" | "normal"How grid items sit in their areas along the row.
justifySelf"auto" | "flex-start" | "flex-end" | "start" | "end" | "self-start" | "self-end" | "center" | "stretch" | "baseline" | "normal"Overrides justifyItems for this item.
view()
    .grid()
    .grid_template_columns("repeat(3, 1fr)")
    .gap_2()
    .child(view().col_span(2).h(px(60.0)).bg(rgb(0xc7d2fe)))
    .child(view().h(px(60.0)).bg(rgb(0xa5b4fc)))

#Size

KeyTypeRustDescription
widthDimensionValue.w(…), .w_full(), .size(…)Width.
heightDimensionValue.h(…), .h_full()Height.
minWidthLengthValue.min_w(…)Minimum width.
minHeightLengthValue.min_h(…)Minimum height.
maxWidthLengthValue.max_w(…)Maximum width.
maxHeightLengthValue.max_h(…)Maximum height.
aspectRationumber.aspect_ratio(r), .aspect_square()Width divided by height; the missing dimension is computed from the other one.

#Margin

Margins accept "auto" (absorbs free space, as in flexbox) and negative values.

KeyTypeRustDescription
marginDimensionValue.m(…), .m_4()All four sides.
marginHorizontalDimensionValue.mx(…)Left and right.
marginVerticalDimensionValue.my(…)Top and bottom.
marginTopDimensionValue.mt(…)Top.
marginRightDimensionValue.mr(…)Right.
marginBottomDimensionValue.mb(…)Bottom.
marginLeftDimensionValue.ml(…)Left.
marginStartDimensionValue.ms(…)Left in left-to-right layouts, right in right-to-left ones.
marginEndDimensionValue.me(…)The opposite of marginStart.

#Padding

KeyTypeRustDescription
paddingLengthValue.p(…), .p_4()All four sides.
paddingHorizontalLengthValue.px(…)Left and right.
paddingVerticalLengthValue.py(…)Top and bottom.
paddingTopLengthValue.pt(…)Top.
paddingRightLengthValue.pr(…)Right.
paddingBottomLengthValue.pb(…)Bottom.
paddingLeftLengthValue.pl(…)Left.
paddingStartLengthValue.ps(…)Left in left-to-right layouts, right in right-to-left ones.
paddingEndLengthValue.pe(…)The opposite of paddingStart.

#ViewStyle

Everything drawn by a view. All keys of LayoutStyle apply too.

#Background

KeyTypeRustDescription
backgroundColorColorValue | AnimatedNode.bg(color), .bind_background(&node)The fill color. Takes a native animated color.
backgroundImagestring.bg_linear(angle), .bg_radial(), .bg_conic() with .gradient_from / _via / _toCSS gradients drawn over the background color: linear-gradient(...), radial-gradient(...), conic-gradient(...), several separated by commas.
view().h(px(120.0)).rounded(px(16.0)).bg_linear(deg(135.0)).gradient_from(rgb(0x6366f1)).gradient_to(rgb(0xec4899))

#Borders

KeyTypeRustDescription
borderWidthnumber.border(w), .border_1(), .border_2()Width of all four sides.
borderTopWidthnumber.border_t(w)Top side.
borderRightWidthnumber.border_r(w)Right side.
borderBottomWidthnumber.border_b(w)Bottom side.
borderLeftWidthnumber.border_l(w)Left side.
borderStartWidthnumber.border_s(w)Start side (left in left-to-right layouts).
borderEndWidthnumber.border_e(w)End side.
borderColorColorValue.border_color(c)Color of all four sides.
borderTopColorColorValue.border_t_color(c)Top side.
borderRightColorColorValue.border_r_color(c)Right side.
borderBottomColorColorValue.border_b_color(c)Bottom side.
borderLeftColorColorValue.border_l_color(c)Left side.
borderStartColorColorValue.border_s_color(c)Start side.
borderEndColorColorValue.border_e_color(c)End side.
borderStyle"solid" | "dashed" | "dotted".border_solid(), .border_dashed(), .border_dotted()Line style. Default "solid".

#Corners

KeyTypeRustDescription
borderRadiusnumber.rounded(r), .rounded_lg()Radius of all four corners.
borderTopLeftRadiusnumber.rounded_tl(r)Top-left corner.
borderTopRightRadiusnumber.rounded_tr(r)Top-right corner.
borderBottomRightRadiusnumber.rounded_br(r)Bottom-right corner.
borderBottomLeftRadiusnumber.rounded_bl(r)Bottom-left corner.
borderTopStartRadiusnumber.rounded_ss(r)Top corner on the start side.
borderTopEndRadiusnumber.rounded_se(r)Top corner on the end side.
borderBottomStartRadiusnumber.rounded_es(r)Bottom corner on the start side.
borderBottomEndRadiusnumber.rounded_ee(r)Bottom corner on the end side.
borderCurve"circular" | "continuous".border_curve(curve)"continuous": corners whose curvature eases into the edges, like iOS app icons. Where the box is too small the curve falls back to circular, so pills stay pills. Works on both platforms.

#Outline

An outline is drawn outside the border and takes no space in layout.

KeyTypeRustDescription
outlineWidthnumber.outline(w)Line width.
outlineColorColorValue.outline_color(c)Line color.
outlineStyle"solid" | "double" | "dashed" | "dotted" | "none" | "hidden".outline_dashed(), .outline_dotted(), .outline_none()Line style.
outlineOffsetnumber.outline_offset(o)Distance from the border edge; negative values move it inside.

#Shadows

Two ways to cast a shadow: the CSS boxShadow (several layers, spread, inset) or the four shadow* keys.

KeyTypeRustDescription
boxShadowstring.shadow([BoxShadow { … }]), .shadow_md()CSS box-shadow: offsets, blur, spread and color, several layers separated by commas, inset for inner shadows.
shadowColorColorValue.shadow_color(c)Shadow color.
shadowOffset{ width: number; height: number }.shadow_offset(point)Offset. Default { width: 0, height: -3 }.
shadowOpacitynumber.shadow_opacity(o)Opacity, 0 to 1. Default 0 (no shadow).
shadowRadiusnumber.shadow_radius(r)Blur radius. Default 3.
view().p_4().rounded(px(12.0)).bg(white()).shadow([
    BoxShadow { offset_y: px(1.0), blur: px(2.0), color: rgba(0x0000000f).into(), ..BoxShadow::default() },
    BoxShadow { offset_y: px(8.0), blur: px(24.0), spread: px(-4.0), color: rgba(0x0000001f).into(), ..BoxShadow::default() },
])

#Opacity, visibility and overflow

KeyTypeRustDescription
opacitynumber | AnimatedNode.opacity(o), .bind_opacity(&value)0 (invisible) to 1. Takes a native animated value.
visibility"visible" | "hidden" | "collapse"Hidden views keep their space in layout (unlike display: "none").
overflow"visible" | "hidden".overflow_hidden()"hidden" clips children to the view’s bounds (and corners).
backfaceVisibility"visible" | "hidden".backface_hidden(), .backface_visible()"hidden": invisible while a 3D rotation turns it away.
verticalAlign"baseline" | "text-top" | "text-bottom" | "middle".align_baseline(), .align_text_top(), .align_text_bottom(), .align_middle()Where a view or image inside a <Text> sits in its line, as CSS’s vertical-align: its bottom on the baseline (default), its top or bottom at the text font’s top or bottom, or its middle half the x height above the baseline. The line grows to hold it.

#Transforms

KeyTypeRustDescription
transformTransformStep[].translate_x(…), .scale(…), .rotate(…), … (below)A list of steps, applied right to left like CSS.
transformOriginstring | (number | string)[].transform_origin(…), .origin_top_left(), …The point transform acts around: keywords, percentages and lengths ("top left", "50% 0", [10, 20]). Default the center.

A TransformStep is an object with one key:

StepValueRustNative animated
translateX, translateYnumber (points).translate_x(…), .translate_y(…); .bind_translate_x(&v)yes
scale, scaleX, scaleYnumber (factor).scale(f), .scale_x(f), .scale_y(f); .bind_scale(&v)yes
rotate, rotateZ, rotateX, rotateYnumber (degrees) or string ("45deg", "0.5rad").rotate(deg(…)), .rotate_x(…), .rotate_y(…); .bind_rotate(&v)yes
skewX, skewYnumber (degrees) or string.skew_x(…), .skew_y(…)no
perspectivenumber.perspective(d)no
view().perspective(px(600.0)).rotate_y(deg(20.0)).scale(0.95)

#Filters and blending

KeyTypeRustDescription
filterstring.blur(r), .brightness(…), .contrast(…), .grayscale(…), .hue_rotate(…), .invert(…), .saturate(…), .sepia(…)CSS filters of the view and its content: brightness(), contrast(), grayscale(), hue-rotate(), invert(), saturate(), sepia(), opacity(), blur(), drop-shadow().
backdropFilterstring.backdrop_blur(r), .backdrop_brightness(…), …CSS filters of what is behind the view, such as "blur(10px)" for frosted glass.
mixBlendMode"normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "color" | "luminosity" | "plus-darker" | "plus-lighter".mix_blend_mode(mode)How the view blends with what is behind it.

#Transitions

When a transitioned property changes (from a new style, a class or a variant such as active:), the platform animates it natively. No JS runs during the animation.

KeyTypeRustDescription
transitionPropertystring.transition(), .transition_all(), .transition_colors(), .transition_opacity(), .transition_shadow(), .transition_transform(), .transition_none()Comma-separated properties that animate: "all", "colors" (color, backgroundColor, borderColor, …), "opacity", "transform", "boxShadow", "borderRadius", "borderWidth", or "none".
transitionDurationnumber | "${number}ms" | "${number}s".duration(ms)Milliseconds as a number, or "150ms" / "0.2s".
transitionDelaynumber | "${number}ms" | "${number}s".delay(ms)Delay before the transition starts.
transitionTimingFunction"linear" | "ease" | "ease-in" | "ease-out" | "ease-in-out" | "cubic-bezier(...)".ease_linear(), .ease_in(), .ease_out(), .ease_in_out(), .ease_bezier(…)The easing curve.
view()
    .on_press(move || open.update(|o| *o = !*o))
    .h(move || px(if open.get() { 160.0 } else { 56.0 }))
    .opacity(move || if open.get() { 1.0 } else { 0.8 })
    .transition()
    .duration(200.0)

#Keyframe animations

Built-in keyframe animations, run natively (Tailwind’s animate-*).

KeyTypeRustDescription
animationName"none" | "spin" | "ping" | "pulse" | "bounce".animate_spin(), .animate_ping(), .animate_pulse(), .animate_bounce(), .animate_none()The animation.
animationDurationnumber | "${number}ms" | "${number}s".animation(KeyframeAnimation { … })Length of one iteration.
animationDelaynumber | "${number}ms" | "${number}s".animation(KeyframeAnimation { … })Delay before the first iteration.
animationTimingFunction"linear" | "ease" | "ease-in" | "ease-out" | "ease-in-out" | "cubic-bezier(...)".animation(KeyframeAnimation { … })The easing curve.
animationIterationCountnumber | "infinite".animation(KeyframeAnimation { … })How many times it runs.

For animations driven by values, gestures or springs, use nsh/animated instead.

#Pointer

KeyTypeRustDescription
cursor"auto" | "default" | "pointer" | "text" | "grab" | "grabbing" | "not-allowed" | ... (every CSS cursor keyword, and "none").cursor(Cursor), .cursor_pointer()The pointer shape over the view, for pointers (iPad trackpads, Mac Catalyst, desktops).

#TextStyle

Text styles apply to <Text> and <Input>. They are also inherited, as in CSS: text properties set on a view pass to the texts and inputs inside it, and nested <Text> spans inherit from their parent text. All keys of ViewStyle apply too. See Text.

#Font

KeyTypeRustDescription
colorColorValue.text_color(c)Text color.
fontSizenumber.text_size(s), .text_sm(), .text_lg(), …Size in points.
fontWeight"normal" | "bold" | number | "${number}".font_weight(FontWeight::SEMIBOLD)"normal" (400), "bold" (700) or 100–900.
fontFamilystring.font_family(name)A system family, or the name an imported font evaluates to (import Inter from "./Inter.ttf"). See Fonts.
fontStyle"normal" | "italic".italic()Italic.
fontVariant("small-caps" | "oldstyle-nums" | "lining-nums" | "tabular-nums" | "proportional-nums")[].small_caps(), .oldstyle_nums(), .lining_nums(), .tabular_nums(), .proportional_nums()OpenType number and letter forms. tabular-nums keeps digits the same width, useful for counters and timers.

#Spacing and alignment

KeyTypeRustDescription
lineHeightnumber.line_height(h)Line height in points.
letterSpacingnumber.letter_spacing(s)Extra space between characters, in points.
textAlign"auto" | "left" | "center" | "right" | "justify".text_left(), .text_center(), .text_right(), .text_justify()Horizontal alignment.
textAlignVertical"auto" | "top" | "center" | "bottom"Where text shorter than its box sits (a <Text> with a height).
writingDirection"auto" | "ltr" | "rtl".writing_direction(d)Base direction of the text; "auto" takes it from the content.
textTransform"none" | "uppercase" | "lowercase" | "capitalize".uppercase(), .lowercase(), .capitalize(), .normal_case()Case transformation.

#Decoration

KeyTypeRustDescription
textDecorationLine"none" | "underline" | "line-through" | "underline line-through".underline(), .line_through(), .no_underline()Lines drawn with the text.
textDecorationColorColorValue.text_decoration_color(c)Color of the lines (default the text color).
textDecorationStyle"solid" | "double" | "dotted" | "dashed" | "wavy".text_decoration_solid(), _double(), _dotted(), _dashed(), _wavy()Line style.
textDecorationThicknessnumber | "auto" | "from-font".text_decoration_thickness(t)Line thickness.
textUnderlineOffsetnumber | "auto".underline_offset(o)Distance of the underline from the baseline.

#Placeholder and selection

KeyTypeRustDescription
placeholderColorColorValue.placeholder_color(c) of an inputThe color of an <Input>’s placeholder (placeholder:text-*).
selectionColorColorValue.selection_color(c) of an input or a textAn <Input>’s caret and selection, a selectable <Text>’s selection highlight and handles (selection:text-*); the platform’s accent by default.

#Text shadow

KeyTypeRustDescription
textShadowColorColorValue.text_shadow_color(c)Shadow color.
textShadowOffset{ width: number; height: number }.text_shadow_offset(point)Shadow offset.
textShadowRadiusnumber.text_shadow_radius(r)Blur radius.

#ImageStyle

All keys of ViewStyle, plus:

KeyTypeRustDescription
tintColorColorValue.tint_color(c) of an imageRecolors a template image (every opaque pixel takes this color), for monochrome icons.

How an image fills its box is the resizeMode prop of <Image>, not a style; see image.

#Props that look like styles

Some settings are props in NSH, not style keys. Their Tailwind classes exist, but an explicit prop wins over the class:

SettingPropRustClass
Line limitnumberOfLines on <Text>.number_of_lines(n)line-clamp-*, truncate
Ellipsis positionellipsizeMode on <Text>.ellipsize_mode(mode)text-ellipsis, text-clip
Touch pass-throughpointerEvents.pointer_events(…)pointer-events-none, pointer-events-auto
Image fitresizeMode on <Image>.resize_mode(mode)object-cover, object-contain, …
Selectable textselectable on <Text>.selectable(true)select-text, select-none
Material shadow (Android)android={{ elevation }}.elevation(e)