Skip to Content
DocsGuidesStyling

Styling with Mix

In Flutter, styling lives inside your widget tree — a Container owns its color, padding, and border. This makes styles hard to reuse, share, or override without duplicating widget code. Mix solves this by pulling style declarations out of the tree into composable, chainable objects called stylers.

Defining and Applying Styles

A styler is a declarative builder that describes how a widget should look. Each Mix widget has a matching styler: BoxStyler for Box, TextStyler for StyledText, IconStyler for StyledIcon, and so on.

Define a style with a fluent chain, then pass it to the widget via the style parameter:

final boxStyle = BoxStyler() .width(240) .height(100) .color(Colors.blue) .borderRounded(12); Box(style: boxStyle, child: Text('Hello'));
Resolving preview metadata...

The same pattern works across all Mix widgets:

// Text final textStyle = TextStyler().fontSize(24).fontWeight(.bold).color(Colors.blue); StyledText('Hello Mix', style: textStyle); // Icon final iconStyle = IconStyler().size(32).color(Colors.blue); StyledIcon(icon: Icons.favorite, style: iconStyle); // FlexBox (row/column layout + box decoration) final rowStyle = FlexBoxStyler() .direction(.horizontal) .spacing(12) .paddingAll(16) .color(Colors.grey.shade100); FlexBox(style: rowStyle, children: [...]);

Callable stylers

Every styler also works as a widget factory. Call it directly instead of passing it to a constructor:

final box = BoxStyler().color(Colors.blue).size(100, 100); final label = TextStyler().fontSize(18).color(Colors.white); // Calling the styler creates the widget box(child: label('Hello Mix'));

This is equivalent to Box(style: box, child: StyledText('Hello Mix', style: label)), but more concise. Use whichever form you prefer.

Style Composition and Override

Build new styles on top of existing ones. Define a base once, then create variations by chaining additional properties:

final base = BoxStyler() .paddingX(16) .paddingY(8) .borderRounded(8) .color(Colors.black); final solid = base.color(Colors.blue); final soft = base.color(Colors.blue.shade100);
Resolving preview metadata...

How merging works

Each chained method internally merges a new property into the existing styler. Later values override earlier ones for the same property, while unrelated properties are preserved:

final a = BoxStyler().color(Colors.red).padding(.all(16)); final b = a.color(Colors.blue); // b has color: blue (overridden) + padding: 16 (preserved)

You can also merge two separate stylers explicitly:

final layout = BoxStyler().padding(.all(16)).borderRounded(12); final visual = BoxStyler().color(Colors.blue).shadow(blurRadius: 10); final card = layout.merge(visual); // combines both

Dynamic and Context-Aware Styling

Styles can adapt to user interactions and context using variants. Instead of writing conditional logic in your widget tree, you declare what changes and when:

final button = BoxStyler() .color(Colors.blue) .onHovered(.color(Colors.blue.shade700)) .onDark(.color(Colors.blue.shade200));

Variants are covered in depth in the Dynamic Styling guide.

See Also