DACS
DACS brings Tailwind-inspired utility classes to Flutter. Write concise string expressions to define text styles, padding, colors, borders, shadows, transforms, gradients, and more.
Text('Hello, World!', style: 'text-2xl font-medium text-sky-500'.dText)
Features
-
Zero-config — just install and use
-
Tailwind v3 color palette — 22 colors × 11 shades
-
Spacing scale — 0 to 384px in Tailwind increments
-
Text utilities — size, weight, color, letter spacing, line height, decoration
-
Background & border — colors, border width, border radius with directional variants
-
Sizing, shadows & opacity — width, height, box shadows, opacity
-
Position — inset-, top-, right-, bottom-, left-, start-, end-*
-
Transform — scale, rotate, translate, skew
-
Gradient — linear gradients from Tailwind color tokens
-
Theme colors from
ColorScheme—text-primary,bg-surface,border-error -
Arbitrary values —
text-[#ff0000],p-[20],w-[50%],rounded-[12] -
Material widget extensions — style any Material widget:
.dButton(context),.dCheckbox(context),.dCard(context), etc. -
WidgetState variants —
hover:,focus:,disabled:,pressed:,selected:,error:,dragged:,scrolledUnder: -
Chained compound variants — combine any prefixes:
dark:hover:,dark:md:focus:,light:lg:disabled: -
Dark/Light, accessibility & responsive variants —
dark:,light:,high-contrast:,motion-reduce:,sm:,md:, etc. -
Material 3 theme coverage — includes buttons, inputs, menus, navigation, drawers, badges, sliders, date pickers, and time pickers
-
Semantic design tokens — configure
bg-brand-primary,p-content,rounded-card,shadow-floating,font-brand,text-body, and aliases liketype-hero -
Static validation — run
dart run dacs:dacs analyzeto catch invalid utility strings before UI execution
Documentation
- Getting started
- Core concepts
- Utilities
- Static validation
- Material widgets
- Inputs
- Public API
- Widget support matrix
- Versioning policy
- Contributing guide
Installation
dependencies:
dacs: ^0.6.0
Usage
Configuration and compilation
DACS works without configuration, but you can enable diagnostics for unknown utilities and tune the parser cache:
Dacs.configure(
strictMode: false,
cacheSize: 500,
onUnknownUtility: (utility) {
debugPrint('Unknown DACS utility: $utility');
},
onDiagnostic: (diagnostic) {
debugPrint('${diagnostic.code}: ${diagnostic.utility}');
},
config: const {
'policy': {
'arbitraryValues': 'allow', // allow | warn | reject
'failFast': false,
},
'theme': {
'extend': {
'colors': {
'brand-primary': {
'DEFAULT': '#0057B8',
'dark': '#8AB4F8',
},
'brand-muted': {
'DEFAULT': '#6B7280',
'dark': '#CBD5E1',
},
},
'spacing': {'content': '24'},
'borderRadius': {'card': '16'},
'boxShadow': {
'floating': '0 8 24 rgba(0, 0, 0, 0.18)',
},
'screens': {
'compact': '0',
'medium': '600',
'expanded': '840',
},
'fontFamily': {
'brand': 'Inter, Roboto, Arial, sans-serif',
},
'fontSize': {
'body': [
'16',
{'lineHeight': '24', 'letterSpacing': '0'},
],
},
'transitionDuration': {
'standard': '200ms',
'short': '100ms',
},
'transitionTimingFunction': {
'standard': 'cubic-bezier(0.2, 0, 0, 1)',
},
'motion': {
'standard': 'duration-standard ease-standard',
'fade-short': 'duration-short ease-out',
},
'typography': {
'hero': 'font-brand text-2xl font-bold text-brand-primary',
'body': 'font-brand text-body text-brand-muted',
},
},
},
},
);
final sheet = DacsCompiler.compile('text-sm dark:md:hover:bg-red-500');
Static validation
Use the CLI to validate constant DACS strings in Dart files before the UI path is executed:
dart run dacs:dacs analyze lib test
It reports unknown utilities, malformed arbitrary values, rejected arbitrary
values, and utilities that are valid but not consumed by a specific adapter such
as .dText or .dPads. Add --format json for editor/CI integrations and
--fatal-warnings when warnings should fail CI.
For custom tokens and policies, create a dacs.config.dart with a const
dacsConfig map using the same string-first shape accepted by
Dacs.configure(config: ...).
Compilation is context-free: DacsCompiler.compile only parses the string into
a DacsStyleSheet. Runtime values such as BuildContext, theme colors,
brightness, breakpoints, and widget states are applied later by methods such as
.dTextOf(context), .dBoxOf(context), and .dButton(context).
The config object is deliberately Tailwind-like: use plain Map, List,
String, bool, and num values. DACS converts those strings to Flutter
objects internally.
Text styles
Text('Heading', style: 'text-3xl font-bold text-gray-900'.dText)
Text('Body', style: 'text-base leading-relaxed text-gray-600'.dText)
Padding & Margin
Container(
padding: 'px-4 py-2'.dPads,
margin: 'mt-4'.dPads,
child: Text('Content', style: 'text-base'.dText),
)
For direction-aware UI, use logical spacing:
Container(
padding: 'ps-4 pe-2 py-3'.dPadsGeometry,
child: Text('RTL-aware spacing'),
)
Box decoration
Container(
decoration: 'bg-blue-500 rounded-lg shadow-md'.dBox,
child: Text('Button', style: 'text-white font-medium'.dText),
)
Gradients
Container(
decoration: 'bg-gradient-to-r from-sky-400 to-blue-600'.dBox,
child: Text('Gradient', style: 'text-white text-xl'.dText),
)
Shadows
Container(decoration: 'bg-white rounded-xl shadow-lg'.dBox)
// Or just the shadow list:
final shadows = 'shadow-lg'.dShadow;
Sizing
final (width, height) = 'w-64 h-48'.dSize;
Position (for Stack)
final (top, right, bottom, left) = 'inset-0'.dPosition;
final logical = 'top-2 start-4 end-2'.dPositionDirectional;
Transform
Transform(
transform: 'scale-125 rotate-45'.dTransform,
child: Text('Styled'),
)
Dark / Light mode variants
// Resolves automatically from the active Flutter Theme:
Text(
'Responsive text',
style: 'text-gray-900 dark:text-white'.dTextOf(context),
)
Container(
decoration: 'bg-white dark:bg-gray-900'.dBoxOf(context),
child: Text(
'Content',
style: 'text-base text-gray-600 dark:text-gray-300'.dTextOf(context),
),
)
Responsive variants
// Applies breakpoints based on screen width from MediaQuery:
Text(
'Responsive heading',
style: 'text-base sm:text-lg md:text-xl lg:text-2xl'.dTextOf(context),
)
Container(
padding: 'p-4 md:p-8 lg:p-12'.dPadsOf(context),
decoration: 'bg-white dark:bg-gray-900 rounded-lg'.dBoxOf(context),
child: Text(
'Content',
style: 'text-sm md:text-base'.dTextOf(context),
),
)
Configure custom breakpoints through theme.screens or
theme.extend.screens:
Dacs.configure(
config: const {
'theme': {
'extend': {
'screens': {
'medium': '600',
'expanded': '840',
},
},
},
},
);
Text(
'Responsive heading',
style: 'text-base medium:text-xl expanded:text-2xl'.dTextOf(context),
)
theme.screens replaces the default sm/md/lg/xl/2xl set. theme.extend.screens
keeps the defaults and adds or overrides individual names.
Accessibility variants
DACS can resolve high-contrast and motion preferences from MediaQuery through
context-aware APIs:
Container(
decoration:
'border-gray-300 high-contrast:border-black'.dBoxOf(context),
)
ElevatedButton(
style: 'motion-standard motion-reduce:motion-none'.dButton(context),
onPressed: () {},
child: const Text('Motion-aware'),
)
Supported accessibility prefixes:
high-contrast:whenMediaQueryData.highContrastis true.normal-contrast:when high contrast is false.motion-safe:when no reduced-motion preference is active.motion-reduce:when motion is reduced or disabled.motion-disabled:only when animations are disabled.
Use DacsResolveContext(motionPreference: DacsMotionPreference.reduce) when an
integration can distinguish reduced motion from disabled animations. Flutter's
default MediaQueryData.disableAnimations maps to motion-disabled:.
Theme colors
Use any ColorScheme key as a color — no need to import or reference the theme directly:
Text('Primary', style: 'text-primary font-bold'.dTextOf(context))
Container(decoration: 'bg-surface rounded-lg border-outline'.dBoxOf(context))
CheckboxTheme(
data: 'checked:bg-primary unchecked:bg-surface'.dCheckbox(context),
child: Checkbox(value: true, onChanged: (_) {}),
)
Supported keys: primary, onPrimary, primaryContainer, onPrimaryContainer, secondary, onSecondary, secondaryContainer, onSecondaryContainer, tertiary, onTertiary, tertiaryContainer, onTertiaryContainer, error, onError, errorContainer, onErrorContainer, surface, onSurface, surfaceVariant, onSurfaceVariant, outline, outlineVariant, inverseSurface, onInverseSurface, inversePrimary, shadow, scrim
Semantic tokens
Register app-specific names in Dacs.configure(config: ...) and use them as
normal utility strings:
Dacs.configure(
config: const {
'theme': {
'extend': {
'colors': {
'brand-primary': {
'DEFAULT': '#0057B8',
'dark': '#8AB4F8',
},
'brand-surface': {
'DEFAULT': '#F3F7FC',
'dark': '#111827',
},
'brand-muted': {
'DEFAULT': '#6B7280',
'dark': '#CBD5E1',
},
},
'spacing': {'content': '24'},
'borderRadius': {'card': '16'},
'boxShadow': {'floating': '0 8 24 rgba(0, 0, 0, 0.18)'},
'screens': {'medium': '600', 'expanded': '840'},
'fontFamily': {
'brand': 'Inter, Roboto, Arial, sans-serif',
},
'fontSize': {
'body': [
'16',
{'lineHeight': '24'},
],
},
'transitionDuration': {
'standard': '200ms',
'short': '100ms',
},
'transitionTimingFunction': {
'standard': 'cubic-bezier(0.2, 0, 0, 1)',
},
'motion': {
'standard': 'duration-standard ease-standard',
'fade-short': 'duration-short ease-out',
},
'typography': {
'hero': 'font-brand text-2xl font-bold text-brand-primary',
'body': 'font-brand text-body text-brand-muted',
},
},
},
},
);
Container(
padding: 'p-content'.dPads,
decoration: 'bg-brand-surface rounded-card shadow-floating'.dBoxOf(context),
child: Text('Brand', style: 'type-hero'.dTextOf(context)),
)
Use theme.extend to add or override individual names while keeping DACS
defaults. Use theme.colors, theme.spacing, theme.borderRadius, or
theme.boxShadow, theme.screens, theme.fontFamily, or theme.fontSize to
replace that whole section.
Configured typography remains string-first:
'font-brand text-body'
'type-body'
'motion-standard'
fontFamily values may be a comma-separated string, a list, or a map with a
package field. DACS applies them to Flutter's TextStyle.fontFamily,
fontFamilyFallback, and package.
DACS does not bundle, install, download, or preload fonts. The app remains responsible for making each configured family available to Flutter:
- declare local font assets in
pubspec.yaml; - depend on a package that exposes the font and use the configured
package; - preload/load external fonts in app code, for example when using
google_fonts; - or rely on a platform/system font when that is acceptable.
Example with local assets:
flutter:
fonts:
- family: Inter
fonts:
- asset: assets/fonts/Inter-Regular.ttf
- asset: assets/fonts/Inter-Bold.ttf
weight: 700
Then reference the family in DACS:
Dacs.configure(
config: const {
'theme': {
'extend': {
'fontFamily': {
'brand': 'Inter, sans-serif',
'mono': 'JetBrains Mono, monospace',
},
'typography': {
'body': 'font-brand text-base',
'code': 'font-mono text-sm',
},
},
},
},
);
With packages such as google_fonts, call/preload the desired families in your
app; DACS only references those family names through utilities like
font-brand.
Motion tokens
Motion is also string-first. Configure durations, curves, and aliases:
Dacs.configure(
config: const {
'theme': {
'reducedMotionFallback': 'motion-none',
'extend': {
'transitionDuration': {
'standard': '200ms',
'short': '100ms',
},
'transitionTimingFunction': {
'standard': 'cubic-bezier(0.2, 0, 0, 1)',
},
'motion': {
'standard': 'duration-standard ease-standard',
'fade-short': 'duration-short ease-out',
},
},
},
},
);
Use configured aliases like normal utilities:
final motion = 'motion-standard motion-reduce:motion-none'
.dStyleOf(context)
.motion;
AnimatedContainer(
duration: motion?.duration ?? Duration.zero,
curve: motion?.curve ?? Curves.linear,
// ...
)
duration-<ms> remains supported and animationDuration still reflects the
resolved motion duration. Built-in curves are ease-linear, ease-in,
ease-out, and ease-in-out. In motion-disabled contexts DACS resolves
declared motion to zero duration and a linear curve unless an explicit
motion-disabled:* override is present.
Arbitrary values
Use square brackets for one-off values:
'text-[#ff0000]' // exact color
'bg-[rgb(255,0,0)]' // rgb syntax
'p-[20]' // 20px padding
'w-[50%]' // 50% width
'rounded-[12]' // 12px border radius
'opacity-[0.75]' // 75% opacity
'scale-[200]' // 2x scale
Design systems can discourage or reject arbitrary values centrally:
Dacs.configure(
config: const {
'policy': {
'arbitraryValues': 'reject',
'failFast': true,
},
},
onDiagnostic: (diagnostic) {
debugPrint('${diagnostic.severity}: ${diagnostic.utility}');
},
);
Policies:
allowis the default and preserves the previous behavior.warnreportsDacsDiagnosticCode.arbitraryValueDisallowedand still compiles the utility.rejectreports an error diagnostic and does not materialize the arbitrary value.
When failFast is true, rejected arbitrary values throw
DacsArbitraryValueException. Malformed bracket syntax such as p-[],
p-[20]x, or bg-[#ff0000 always emits
DacsDiagnosticCode.malformedUtility; with failFast, it throws
DacsMalformedUtilityException.
The policy applies to every utility that uses [...], including text/input
helpers such as label-[Email] and image utilities such as
image-asset-[assets/card.png].
Material widget extensions
Style Material widgets via context-aware methods. WidgetState variant support
(hover:, focus:, disabled:, etc.) varies by adapter — see the table below.
ElevatedButton(
style: 'bg-primary text-white rounded-lg'.dButton(context),
onPressed: () {},
child: const Text('Submit'),
)
CheckboxTheme(
data: 'bg-primary hover:bg-primaryContainer'.dCheckbox(context),
child: Checkbox(value: true, onChanged: (_) {}),
)
CardTheme(
data: 'bg-surface rounded-xl shadow-md'.dCard(context),
child: Card(child: Text('Content', style: 'text-base'.dText)),
)
All 37 Material adapters are supported: dButton, dIconButton, dSegmentedButton, dCheckbox, dSwitch, dRadio, dChip, dBadge, dAppBar, dCard, dListTile, dTabBar, dBottomNav, dNavBar, dNavRail, dDrawer, dBottomAppBar, dInput, dProgress, dTooltip, dDivider, dScrollbar, dSnackBar, dDialog, dBottomSheet, dExpansionTile, dFab, dDataTable, dSearchBar, dMenu, dPopupMenu, dDropdownMenu, dSlider, dDatePicker, dTimePicker, dIcon, dShape.
For the detailed per-widget property matrix, see the widget support matrix.
TextField inputs
TextField.style and TextField.decoration are different Flutter APIs.
Use .dTextOf(context) for the typed text and .dInputOf(context) for the
input chrome: label, hint, helper, error, prefix/suffix, fill, density, padding,
and borders.
const classes = 'text-onSurface label-[Email] hint-[you@example.com] '
'helper-[Use your work email] filled dense bg-surface '
'border-outline focus:border-primary error:border-error '
'focus:error:border-primaryContainer rounded-lg p-4';
TextField(
style: classes.dTextOf(context),
decoration: classes.dInputOf(context),
)
Date and time picker themes
Picker adapters use explicit semantic color channels, so DACS does not guess hover, selected, disabled, or overlay colors for you. Declare every visual state you want to control:
Theme(
data: Theme.of(context).copyWith(
datePickerTheme:
'bg-surface text-onSurface rounded-lg shadow-md '
'date-header-bg-primary date-header-text-onPrimary '
'date-day-text-onSurface selected:date-day-bg-primary '
'hover:date-day-overlay-secondary date-today-text-secondary'
.dDatePicker(context),
timePickerTheme:
'bg-surface text-onSurface rounded-lg shadow-md '
'time-dial-bg-surfaceVariant time-dial-hand-primary '
'time-hour-minute-bg-surfaceVariant '
'selected:time-hour-minute-bg-secondary '
'time-hour-minute-text-onSurface '
'selected:time-hour-minute-text-onSecondary'
.dTimePicker(context),
),
child: const SizedBox.shrink(),
)
WidgetState variants
For Material widgets, use interactive state variants:
ElevatedButton(
style: 'bg-primary hover:bg-primaryContainer disabled:bg-surface
rounded-lg hover:rounded-xl'.dButton(context),
onPressed: () {},
child: const Text('Submit'),
)
State order: base → disabled → pressed → hover → focus → selected → error → dragged → scrolledUnder.
Shape variants (hover:rounded-xl, pressed:rounded-sm) resolve dynamically via _stateProp.
Chained compound variants
Combine any variant prefixes with ::
// Applies only in dark mode AND when hovered
Text(
'Styled text',
style: 'text-white dark:hover:text-primary'.dTextOf(context),
)
// Triple compound: dark mode, medium breakpoint, hover
Container(
decoration: 'bg-primary dark:md:hover:bg-error'.dBoxOf(context),
)
Parsed style access
final sheet = 'text-lg font-bold text-red-600 dark:text-white'.dStyle;
final base = sheet.base;
print(base.fontSize); // 18
print(base.fontWeight); // FontWeight.w700
print(base.color); // Color(0xFFDC2626)
final resolved = sheet.resolveFor(context); // DacsResolvedStyle
Extension methods
Simple getters (no context)
These parse classes and convert immediately. Useful when you don't need variant resolution.
| Getter | Returns |
|---|---|
.dText |
TextStyle |
.dPads |
EdgeInsets |
.dPadsGeometry |
EdgeInsetsGeometry |
.dBox |
BoxDecoration |
.dStyle |
DacsStyleSheet |
.dBase |
DacsStyle |
.dShadow |
List<BoxShadow> |
.dSize |
(double?, double?) |
.dFixedSize |
Size? |
.dLayout |
DacsLayoutStyle |
.dPosition |
(double?, double?, double?, double?) |
.dPositionDirectional |
DacsPositionValues |
.dTransform |
Matrix4 |
.dGradient |
LinearGradient? |
.dBorder |
BoxBorder? |
.dBorderSide |
BorderSide? |
.dRadius |
BorderRadiusGeometry? |
.dConstraints |
BoxConstraints? |
.dAlignment |
AlignmentGeometry? |
.dShapeBorder |
ShapeBorder? |
.dMotion |
DacsMotionSpec? |
Context-aware methods (resolve variants)
These accept a BuildContext to resolve dark/light mode, responsive breakpoints, and theme colors from MediaQuery / Theme.
| Method | Returns |
|---|---|
.dTextOf(context) |
TextStyle |
.dPadsOf(context) |
EdgeInsets |
.dPadsGeometryOf(context) |
EdgeInsetsGeometry |
.dMarginOf(context) |
EdgeInsets |
.dMarginGeometryOf(context) |
EdgeInsetsGeometry |
.dBoxOf(context) |
BoxDecoration |
.dStyleOf(context) |
DacsResolvedStyle |
.dShadowOf(context) |
List<BoxShadow> |
.dSizeOf(context) |
(double?, double?) |
.dFixedSizeOf(context) |
Size? |
.dLayoutOf(context) |
DacsLayoutStyle |
.dPositionOf(context) |
(double?, double?, double?, double?) |
.dPositionDirectionalOf(context) |
DacsPositionValues |
.dTransformOf(context) |
Matrix4 |
.dGradientOf(context) |
LinearGradient? |
.dBorderOf(context) |
BoxBorder? |
.dBorderSideOf(context) |
BorderSide? |
.dRadiusOf(context) |
BorderRadiusGeometry? |
.dConstraintsOf(context) |
BoxConstraints? |
.dAlignmentOf(context) |
AlignmentGeometry? |
.dShapeBorderOf(context) |
ShapeBorder? |
.dMotionOf(context) |
DacsMotionSpec? |
Material widget extensions
These accept a BuildContext and return Material theme data with variant resolution.
WidgetState support is marked per method.
For property-level support, see the
widget support matrix.
| Method | Returns | WidgetState |
|---|---|---|
.dButton(context) |
ButtonStyle |
full |
.dIconButton(context) |
IconButtonThemeData |
full through ButtonStyle |
.dSegmentedButton(context) |
SegmentedButtonThemeData |
full through ButtonStyle |
.dCheckbox(context) |
CheckboxThemeData |
partial |
.dSwitch(context) |
SwitchThemeData |
partial |
.dRadio(context) |
RadioThemeData |
partial |
.dChip(context) |
ChipThemeData |
only color |
.dBadge(context) |
BadgeThemeData |
— |
.dScrollbar(context) |
ScrollbarThemeData |
partial |
.dNavBar(context) |
NavigationBarThemeData |
only label |
.dNavRail(context) |
NavigationRailThemeData |
— |
.dDrawer(context) |
DrawerThemeData |
— |
.dBottomAppBar(context) |
BottomAppBarThemeData |
— |
.dDataTable(context) |
DataTableThemeData |
partial |
.dSearchBar(context) |
SearchBarThemeData |
partial |
.dMenu(context) |
MenuStyle |
partial |
.dPopupMenu(context) |
PopupMenuThemeData |
partial |
.dDropdownMenu(context) |
DropdownMenuThemeData |
partial |
.dSlider(context) |
SliderThemeData |
partial |
.dDatePicker(context) |
DatePickerThemeData |
partial |
.dTimePicker(context) |
TimePickerThemeData |
partial |
.dAppBar(context) |
AppBarTheme |
— |
.dCard(context) |
CardTheme |
— |
.dListTile(context) |
ListTileThemeData |
— |
.dTabBar(context) |
TabBarTheme |
— |
.dBottomNav(context) |
BottomNavigationBarThemeData |
— |
.dInput(context) / .dInputOf(context) |
InputDecoration |
focus, disabled, error, focus:error border mappings |
.dProgress(context) |
ProgressIndicatorThemeData |
— |
.dTooltip(context) |
TooltipThemeData |
— |
.dDivider(context) |
DividerThemeData |
— |
.dSnackBar(context) |
SnackBarThemeData |
— |
.dDialog(context) |
DialogTheme |
— |
.dBottomSheet(context) |
BottomSheetThemeData |
— |
.dExpansionTile(context) |
ExpansionTileThemeData |
— |
.dFab(context) |
FloatingActionButtonThemeData |
— |
.dIcon(context) |
IconThemeData |
— |
.dShape(context) |
ShapeDecoration |
— |
Supported classes
Typography
| Class | Flutter property |
|---|---|
text-xs … text-9xl |
fontSize (12 … 128) |
text-{configured} |
configured fontSize, optional line height and letter spacing |
font-thin … font-black |
fontWeight (100 … 900) |
font-{configured} |
configured font family/fallback/package |
leading-3 … leading-10 |
height (line height) |
leading-none … leading-loose |
height (relative) |
tracking-tighter … tracking-widest |
letterSpacing |
italic / not-italic |
fontStyle |
underline / line-through / no-underline |
textDecoration |
decoration-solid / double / dotted / dashed / wavy |
textDecorationStyle |
decoration-{1..} |
textDecorationThickness |
decoration-{color}-{shade} |
textDecorationColor |
Motion
| Class | Flutter property |
|---|---|
duration-0, duration-75, duration-100, duration-150, duration-200, duration-300, duration-500, duration-700, duration-1000 |
DacsMotionSpec.duration and legacy animationDuration |
duration-{integer} |
duration in milliseconds |
duration-{configured} |
configured transitionDuration |
ease-linear, ease-in, ease-out, ease-in-out |
DacsMotionSpec.curve |
ease-{configured} |
configured transitionTimingFunction |
motion-none |
zero duration and linear curve |
motion-{configured} |
configured theme.motion alias |
Colors (text, background, border, decoration)
Format: {prefix}-{color}-{shade}
'text-sky-500' // text color
'bg-blue-200' // background color
'border-red-600' // border color
'decoration-green-500' // text decoration color
Supported colors: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose
Shades: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950
Also: text-black, text-white, text-transparent
Spacing
| Class | Output |
|---|---|
p-4 |
EdgeInsets.all(16) |
px-4 |
EdgeInsets.symmetric(horizontal: 16) |
py-2 |
EdgeInsets.symmetric(vertical: 8) |
pt-4, pr-4, pb-4, pl-4 |
Physical side padding |
ps-4, pe-4 |
Logical start/end padding |
m-*, mx-*, my-*, mt-*, mr-*, mb-*, ml-* |
Same for physical margin |
ms-4, me-4 |
Logical start/end margin |
Spacing keys: 0, px, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96
Border
| Class | Output |
|---|---|
rounded-none |
BorderRadius.circular(0) |
rounded-sm |
BorderRadius.circular(2) |
rounded |
BorderRadius.circular(4) |
rounded-md / rounded-lg / rounded-xl / rounded-2xl / rounded-3xl |
6 / 8 / 12 / 16 / 24 |
rounded-full |
BorderRadius.circular(9999) |
rounded-t-lg, rounded-b-sm, rounded-l-md, rounded-r-xl |
Directional |
rounded-tl-lg, rounded-tr-lg, rounded-bl-lg, rounded-br-lg |
Corner-specific |
border |
Border.all(width: 1) |
border-2 … border-8 |
Border.all(width: size) |
Sizing & opacity
'w-64' // width: 256
'h-32' // height: 128
'w-full' // width: double.infinity
'opacity-50' // opacity: 0.5
Shadows
| Class | BoxShadows |
|---|---|
shadow-sm |
1 shadow (subtle) |
shadow |
2 shadows (default) |
shadow-md / shadow-lg / shadow-xl / shadow-2xl |
Increasing blur/spread |
shadow-inner |
Inset shadow |
shadow-none |
Empty list |
Position
| Class | Properties |
|---|---|
inset-0 |
top=0, right=0, bottom=0, left=0 |
inset-x-4 |
left=16, right=16 |
inset-y-2 |
top=8, bottom=8 |
top-4, right-4, bottom-4, left-4 |
Individual inset |
inset-s-4, inset-e-4 |
Logical start/end inset |
start-4, end-4 |
Individual logical inset |
Transform
| Class | Property |
|---|---|
scale-125 |
scaleX=1.25, scaleY=1.25 |
scale-x-150 |
scaleX=1.5 |
scale-y-75 |
scaleY=0.75 |
rotate-45 |
rotateDegrees=45 |
translate-x-4 |
translateX=16 |
translate-y-2 |
translateY=8 |
skew-x-12 |
skewX=12 |
skew-y-6 |
skewY=6 |
Gradient
'bg-gradient-to-r from-red-500 to-blue-600'
'bg-gradient-to-tl from-amber-400 via-orange-500 to-red-600'
Directions: to-r, to-l, to-t, to-b, to-tr, to-tl, to-br, to-bl
Variants
Prefix any class with a variant to scope it:
| Variant | Trigger |
|---|---|
dark: |
Applies when Theme.of(context).brightness == Brightness.dark |
light: |
Applies when Theme.of(context).brightness == Brightness.light |
high-contrast: |
Applies when MediaQueryData.highContrast == true |
normal-contrast: |
Applies when high contrast is inactive |
motion-safe: |
Applies when motion preference is noPreference |
motion-reduce: |
Applies when motion preference is reduce or disabled |
motion-disabled: |
Applies only when motion preference is disabled |
sm: |
Applies at min-width: 640px |
md: |
Applies at min-width: 768px |
lg: |
Applies at min-width: 1024px |
xl: |
Applies at min-width: 1280px |
2xl: |
Applies at min-width: 1536px |
hover: |
WidgetState.hovered |
focus: |
WidgetState.focused |
active: / pressed: |
WidgetState.pressed |
disabled: |
WidgetState.disabled |
selected: |
WidgetState.selected |
error: |
WidgetState.error |
dragged: |
WidgetState.dragged |
scrolledUnder: |
WidgetState.scrolledUnder |
Resolution order (Material contexts): base → disabled → pressed → hover → focus → selected → error → dragged → scrolledUnder.
Chained compound variants: combine multiple prefix types with :.
'dark:hover:text-white' // dark mode + hover
'light:md:bg-primary' // light mode + md breakpoint
'dark:lg:focus:border-error' // dark + lg + focus
'dark:high-contrast:hover:border-black'
'motion-reduce:duration-0'
Compound variants match only when ALL conditions are met. WidgetState conditions re-map to simple keys for Material widget resolution.
Additional information
- Report issues
- View source
- Licensed under the MIT License
Libraries
- dacs
- DACS — Tailwind-like utility classes for Flutter.