Skip to content

Style Builder

Use the fluent builder to write CSS objects, selectors, at-rules, and composition.

The default style export is created from React CSS property types and the default selector preset.

import { style } from '@fluentic/style';
const root = style({
display: 'grid',
gap: 12,
});

Values are React CSS values, plus Fluentic tokens and priority tuples.

The default selector preset includes common pseudo classes, pseudo elements, argument selectors, and at-rules.

const button = style({
color: 'white',
})
.hover({
opacity: 0.86,
})
.focusVisible({
outline: '2px solid royalblue',
})
.before({
content: '""',
});

Use .select(...) for selectors that still target the element receiving the generated class:

const tab = style({
border: 0,
}).select('&[aria-selected="true"]', {
fontWeight: 700,
});

Do not use .select(...) to style descendant elements. Publish descendant parts as slots, then target those slots from a scope:

const menuStyles = {
root: style.slot({
display: 'grid',
}),
item: style.slot(),
};
const comfortableMenu = style.scope([
menuStyles.item({
padding: 8,
}),
]);

Use .attr(...) for attribute-like selector strings:

const input = style().attr('[aria-invalid="true"]', {
borderColor: 'crimson',
});
const panel = style({
padding: 20,
}).media('(max-width: 700px)', {
padding: 12,
});

Media and container functions also accept an explicit priority number:

const panel = style().media(2, '(max-width: 700px)', {
padding: 12,
});

Use .merge(...) when you want to combine generated rule data.

const base = style({ borderRadius: 6 });
const elevated = style()
.merge(base)
.hover({ transform: 'translateY(-1px)' });

In most component code, prefer slots and scopes for component parts because they preserve override targets.