Skip to Content
Mix 2.0 is in development! You can access the Mix 1.0 docs here.
DocsGuidesStyling with Mix

Styling with Mix

Mix separates visual style definitions from widget structure. You define styles using Styler classes, compose them through method chaining, and apply them to widgets — keeping presentation logic out of your widget tree.

Understanding Style and Styler

In Mix, Style is an abstract class that defines the contract for visual semantics outside of widget builds. Classes that extend Style typically follow the naming convention of ending with Styler (for example, BoxStyler, TextStyler). These styler classes act as declarative style builders, resolving with BuildContext to access theme data, media queries, and other contextual information—enabling adaptive, context-aware styling for your app.

By using stylers, you separate presentation logic from your widget tree, making your codebase more maintainable and your styles more reusable.

Fluent and Familiar API

Mix provides a chainable builder API that mirrors Flutter’s naming conventions and behavior, making styles predictable and easy to read for Flutter developers:

import 'package:flutter/material.dart'; import 'package:mix/mix.dart'; final style = BoxStyler() .width(240) .height(100) .color(Colors.blue) .borderRounded(12);

This familiar approach reduces the learning curve and makes your styling code feel natural within the Flutter ecosystem.

Style Composition and Override

One of Mix’s most powerful features is the ability to build new styles on top of existing ones. This composition pattern promotes reusability and maintains consistency across your application:

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);

Order Matters: The sequence in which you chain styling attributes directly affects the final result. Attributes are merged in order, so later attributes will override earlier ones when there are conflicts.

Default Constructor vs .create()

Styler classes have two constructors:

  • Default constructor (BoxStyler()) — use for fluent chaining with concrete values
  • .create() constructor (BoxStyler.create(...)) — use when passing Prop<T> values (tokens, directives)
// Default: concrete values via fluent API final style = BoxStyler() .color(Colors.blue) .paddingAll(16); // .create(): Prop<T> values for tokens and directives final $primaryColor = ColorToken('primary'); final style = BoxStyler.create( padding: Prop.token($spacingMd), ).color($primaryColor());

style vs styleSpec

All Mix widgets accept both style and styleSpec:

  • style — pass a Styler instance (e.g., BoxStyler()). This is the standard approach.
  • styleSpec — pass a pre-resolved StyleSpec<T>. Use only with StyleBuilder when you need manual state control.
// Standard usage Box(style: BoxStyler().color(Colors.blue)) // With StyleBuilder for manual state control StyleBuilder( style: myStyle, builder: (context, spec) => Box(styleSpec: StyleSpec(spec: spec)), )

Dynamic and Context-Aware Styling

Mix styles can adapt to user interactions and context changes using variants. This enables responsive designs that react to hover states, theme changes, and other contextual factors:

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