Hover, focus, and other states
Every utility class in Style can be applied conditionally by adding a variant prefix that targets a specific state. Variants are separated from the utility by a colon — for example, hover:bg-sky-700 only applies bg-sky-700 when the element is hovered.
Style('bg-violet-500 hover:bg-violet-600 focus:outline-2 focus:outline-offset-2 focus:outline-violet-500 active:bg-violet-700 ...', child: Text('Save changes'))The Style widget manages hover, focus, and active state tracking internally — you don’t need setState, MouseRegion, or GestureDetector.
Hover, focus, and active
Section titled “Hover, focus, and active”Style these states with the hover:, focus:, and active: prefixes:
| Variant | Applies when |
|---|---|
hover: | Mouse pointer is over the widget |
focus: | Widget has keyboard focus |
active: | Widget is being pressed |
// Background changes on hoverStyle('bg-sky-500 hover:bg-sky-700', child: ...)
// Outline appears on focusStyle('focus:outline-2 focus:outline-sky-500', child: ...)
// Darker shade while pressedStyle('bg-violet-500 active:bg-violet-700', child: ...)You can combine all three on a single widget — they compose naturally:
Style( 'bg-violet-500 hover:bg-violet-600 focus:outline-2 focus:outline-offset-2 focus:outline-violet-500 active:bg-violet-700 cursor-pointer', child: ...,)Disabled state
Section titled “Disabled state”Use the disabled: prefix for styling disabled elements. Pass disabled: true to the Style widget:
Style('bg-indigo-500 hover:bg-indigo-600 ...', child: Text('Enabled'))Style('bg-indigo-500 disabled:bg-gray-400 disabled:cursor-not-allowed ...', disabled: true, child: Text('Disabled'))When disabled: true is set, disabled: prefixed classes activate and hover/active states are suppressed.
Focus ring
Section titled “Focus ring”A common pattern is showing a visible outline when an element receives keyboard focus:
Style('focus-within:border-sky-500 focus-within:outline focus-within:outline-sky-500 ...', child: TextField())The focus:border-sky-500 focus:outline focus:outline-sky-500 classes apply a blue border and outline ring when the element is focused.
Group hover
Section titled “Group hover”Use the group class on a parent and group-hover: on children to style children based on the parent’s hover state:
Style('group ...', children: [ Style('stroke-sky-500 group-hover:stroke-white ...', children: [ // ... ]), Style('text-gray-900 group-hover:text-white ...', child: Text('New project')), Style('text-gray-500 group-hover:text-white ...', child: Text('Create a new project from a variety of starting templates.')),])When you hover anywhere on the card (the group), the background turns sky-500, and the text turns white via group-hover:text-white.
Other group variants available:
group-focus:— when the group has focusgroup-active:— when the group is pressedgroup-focus-within:— when the group or any descendant has focus
Peer state
Section titled “Peer state”Use the peer class on a sibling and peer-hover:, peer-focus:, or peer-active: on other siblings to style based on the peer’s state:
Style('flex flex-col gap-2 max-w-sm p-8', children: [ Text('Email'), Style('peer ...', child: TextField()), Style('invisible peer-focus:visible ...', child: Text('Enter your email address.')),])The helper text is invisible by default and becomes visible via peer-focus:visible when the peer element (the input) receives focus.
Other peer variants available:
peer-hover:— when the peer is hoveredpeer-focus:— when the peer has focuspeer-active:— when the peer is pressedpeer-focus-within:— when the peer or its descendants have focus
Dark mode
Section titled “Dark mode”Use the dark: prefix to style elements differently in dark mode:
Style( 'bg-white dark:bg-gray-800 text-gray-900 dark:text-white', child: ...,)Dark mode classes activate based on the app’s ThemeMode. See Dark mode for more details.
Responsive variants
Section titled “Responsive variants”Breakpoint prefixes can be combined with state variants:
// On small screens and above, change background on hoverStyle('bg-white sm:hover:bg-sky-100', child: ...)Variants can be stacked — sm:hover:bg-sky-100 means “at the sm breakpoint and above, when hovered, apply bg-sky-100.”
See Responsive design for the full breakpoint system.
Structural variants
Section titled “Structural variants”Structural variants style a flex, grid, or block child based on its position among its siblings — mirroring the CSS structural pseudo-classes:
| Variant | Applies when the child is… |
|---|---|
first: | the first child (:first-child) |
last: | the last child (:last-child) |
only: | the only child (:only-child) |
odd: | at an odd position (:nth-child(odd)) |
even: | at an even position (:nth-child(even)) |
nth-3: | the 3rd child (:nth-child(3)) |
nth-[2n+1]: | matches the An+B formula (:nth-child(2n+1)) |
Style('flex', children: [ for (final item in items) // first item gets extra left padding, last gets extra right padding Style('px-2 first:pl-6 last:pr-6', child: item),])The position is resolved against the direct children of the nearest Style layout container (flex / grid / block). It works whether a child is a Style directly or a custom StatelessWidget / StatefulWidget component that returns one — so you can factor a list item into its own widget and first: / last: still apply. Like CSS :nth-child, every sibling counts, including absolute-positioned ones.
Combining variants
Section titled “Combining variants”You can stack multiple variants on a single utility:
Style('dark:hover:bg-indigo-600', child: ...)This applies bg-indigo-600 only when both dark mode is active and the element is hovered.
Common combinations:
dark:hover:— dark mode + hoversm:hover:— breakpoint + hovergroup-hover:— parent hoverfocus:active:— focused and pressed
Available state variants
Section titled “Available state variants”| Variant | Description |
|---|---|
hover: | Mouse over the widget |
focus: | Widget has keyboard focus |
focus-within: | Widget or descendant has focus |
active: | Widget is being pressed |
disabled: | Widget has disabled: true |
dark: | Dark mode is active |
group-hover: | Parent with group class is hovered |
group-focus: | Parent with group class is focused |
group-active: | Parent with group class is pressed |
peer-hover: | Sibling with peer class is hovered |
peer-focus: | Sibling with peer class is focused |
peer-active: | Sibling with peer class is pressed |
Structural variants (first:, last:, only:, odd:, even:, nth-*:) are also supported — see Structural variants above.