Utilities
It is not necessary to use utilities, but in some cases they make life easier. Each StyleSheet maker function takes an object with utilities as an argument.
dash
Combines primitives using a hyphen.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ dash }) => {
const width = {
none: '0',
half: '50%',
full: '100%'
};
const widthRules = Object.entries(width).reduce((acc, [key, val]) => {
const selector = dash('w', key);
acc[selector] = {
width: val,
};
return acc;
}, {});
return {
...widthRules
};
};comma
Combines primitives using a comma.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ comma }) => {
const fonts = ['Georgia', 'serif'];
return {
html: {
fontFamily: comma(...fonts)
}
};
};space
Combines primitives using the space.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ space }) => {
const borderStyle = 'solid';
const borderWidth = {
s: '2px',
l: '4px'
};
return {
'.container': {
border: space(borderWidth.s, borderStyle)
}
};
};range
Iterates over a sequence of numbers of a specified length.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ range }) => {
const rules = range(5, (sz) => {
return {
[`.h-${sz}`]: {
height: sz + 'rem'
}
};
});
return {
...rules
};
};each
Iterates over the key-value pairs of an object or the values of an array.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ each }) => {
const rules = range(5, (sz) => {
return {
[`.h-${sz}`]: {
height: sz + 'rem'
}
};
});
return {
...rules
};
};merge
Performs deep object merging.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ merge }) => {
const base = {
body: {
width: '100%'
},
div: {
width: '100%',
span: {
width: '100%'
}
}
};
const custom = {
body: {
width: '100vw',
height: '100%'
},
div: {
span: {
background: 'transparent'
}
}
};
return merge(base, custom);
};when
Returns the second argument if the first is true, otherwise returns empty object.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ when }) => {
const values = [1, 2, 3, 4, 5, 6];
const rules = values.reduce((acc, value) => {
return {
...acc,
...when(!(value % 2), {
[`sz-${value}`]: {
width: value + 'rem',
aspectRatio: 1
}
})
}
}, {})
return {
...rules
};
};themeVar
Creates a var() expression with global theme variables.
Example
import { TStyleSheetMaker } from 'effcss';
type TGlobalVars = {
sz: {
m: string;
l: string
}
};
export const maker: TStyleSheetMaker = ({ themeVar }) => {
return {
'.sz-m': {
width: themeVar<TGlobalVars>('sz.m', '100px') // '100px' - fallback value
}
};
};time
Caclulates time value depending on global time variable.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ time }) => {
return {
'.dur-2': {
// if global root time is 200ms (by default),
// then result will be 400ms
transitionDuration: time(2)
}
};
};size
Caclulates size value depending on global size variable.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ size }) => {
return {
'.w-2': {
// if global root size is 16px (by default),
// then result will be 32px
width: size(2)
}
};
};angle
Caclulates angle value depending on global angle variable.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ angle }) => {
return {
'.w-2': {
// if global root angle is 30deg (by default),
// then result will be 60deg
transform: `skew(${angle(2)})`
}
};
};easing (^4.4.0)
Calculates a value of type <easing-function>. When called without an argument, it returns the global value; when called with an argument, it returns the configured value of the cubic-bezier function.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ easing }) => {
return {
[`.cust`]: {
transitionTimingFunction: easing({
x1: 0.42,
x2: 0.58
}) // transition-timing-function:cubic-bezier(0.42,0,0.58,1)
},
[`.global`]: {
transitionTimingFunction: easing() // transition-timing-function:var(--f0-easing)
},
};
};select (^4.6.0)
Generates a unique selector with the prefix of this stylesheet.
Example
import { TStyleSheetMaker } from 'effcss';
export type TCustomStyles = {
w: 's' | 'm';
full: '';
rad: 12 | 16;
header: Record<string, never>;
footer: {
empty: '';
lh: 24 | 28;
left: {
ext: Record<string, never>;
};
right: {
full: '';
}
};
};
export const maker: TStyleSheetMaker = ({select}) => {
const selector = select<TCustomStyles>;
return {
[selector('w:s')]: {
width: '12px'
},
[selector('header')]: {
order: 1
},
[selector('footer.empty:')]: {
display: 'none'
}
};
};bem
Resolves scoped BEM-selector.
Example
import { TStyleSheetMaker } from 'effcss';
export type TStyleSheet = {
block: {
'': {
hidden: '';
};
elem: {
sz: 's' | 'm';
};
};
};
export const maker: TStyleSheetMaker = ({ bem }) => {
const block = bem<TStyleSheet>({
block: {}
});
const blockHidden = bem<TStyleSheet>({
block: {
'': {
hidden: ''
}
}
});
const elementSzS = bem<TStyleSheet>('block.elem.sz.s');
const elementSzM = bem<TStyleSheet>({
block: {
elem: {
sz: 'm'
}
}
});
return {
[block]: {
overflow: 'hidden'
},
[blockHidden]: {
visibility: 'hidden'
},
[elementSzS]: {
width: '2rem'
},
[elementSzM]: {
width: '5rem'
}
};
};units
Group of CSS-units functions.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ units }) => {
const { px, rem } = units;
return {
'.custom': {
width: px(100),
height: rem(1.5)
}
};
};pseudo
Group of pseudoclass/pseudoelement functions.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ pseudo }) => {
const { h, aft, has, is } = pseudo;
return {
// .custom::after:hover
[h(aft('.custom'))]: {
color: 'transparent'
},
// .custom:hover
['.custom' + h]: {
border: '2px solid gray'
},
// you can pass styles as arg
'.custom': {
// &:hover {...}
...h({
background: 'white'
})
},
// button:is(.custom):has(image)
[has('image', is('.custom', 'button'))]: {
cursor: 'pointer'
},
// you can pass styles as arg
button: {
...is('.custom', {
...has('image', {
cursor: 'pointer'
})
})
} // -> button{&:is(.custom){&:has(image){cursor:pointer;}}}
};
};color
A group of functions for working with color.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ units }) => {
const { fadeout, darken } = color;
const baseColor = 'green';
const additionalColor = fadeOut(baseColor);
return {
'.custom': {
background: additionalColor,
color: darken(baseColor)
}
};
};palette
An instance of the palette class. It allows you to use colors in the oklch format with predefined brightness, chromaticity, and hue values that are taken from theme variables.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ palette }) => {
// `palette.fg` returns the foreground color, while `palette.bg" returns the background color.
// The background and foreground have different brightness and chromaticity values for each option.
// The options for shades are `pri`, `sec`, `suc`, `inf`, `war`, `dan`.
// The options for chromaticity are `grey`, `pale`, `base`, `rich`
// The options for brightness are `xs`, `s`, `m`, `l`, `xl`.
// The brightness settings increase as you approach the contrast (0 in light mode and 1 in dark mode), so "xs" = .48, "xl" = 0.24 on a dark background, and "xs" = 0.78, "xl" = 0.98 on a light background
return {
'.palette-complex': {
color: palette.fg.gray.inf.l,
backgroundColor: palette.bg.pale.sec.xl,
borderColor: palette.fg.rich.xs.suc.alpha(0.75)
}
};
};coef
An instance of the coefficient class. Allows you to use coefficient ranges with predefined values that are taken from theme variables.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ coef, size }) => {
return each(coef.$m.short, (k, v) => ({
[`.size-` + k]: {
width: size(v)
}
}));
};at.property
Creates scoped @property rule.
Example
import { TStyleSheetMaker } from 'effcss';
// all the @property names don't make any sense - the provider will create them unique for each utility call
export const maker: TStyleSheetMaker = ({ at: { property } }) => {
const firstProperty = property();
const secondProperty = property({
ini: '25px',
inh: false,
def: '10px' // will be used as reserve value in `var()` expression
});
const thirdProperty = property();
// you can create a non-inherited variable by passing only the default value
const fourthProperty = property('20px');
return {
...firstProperty, // => @property --first-property-name {...}
...secondProperty,
...fourthProperty,
'.mod': firstProperty('150px'), // => '.mod': {'--first-property-name': '150px'}
'.full': {
...secondProperty('100px'),
...thirdProperty('red'),
aspectRatio: 1
},
'.cls': {
width: firstProperty, // => width: `var(--first-property-name)`
height: `calc(2 * ${secondProperty})` // => height: `calc(2 * var(--second-property-name,10px))`
},
'.cls2': {
height: `calc(2 * ${secondProperty.fallback('35px')})`,
width: fourthProperty
}
};
};at.keyframes
Creates scoped @keyframes rule.
Example
import { TStyleSheetMaker } from 'effcss';
// all the @keyframes names don't make any sense - the provider will create them unique for each utility call
export const maker: TStyleSheetMaker = ({ at: { keyframes } }) => {
const widthKf = keyframes({
from: { width: '10px' },
to: { width: '20px' }
});
const heightKf = keyframes({
from: { height: '10px' },
to: { height: '20px' }
});
return {
...widthKf, // => `@keyframes width-kf-name`: {...}
...heightKf,
'.cls1': {
...widthKf()
}, // => `.cls1`: {animationName: 'width-kf-name'}
'.cls2': {
animation: `3s linear 1s ${heightKf}` // => animation: `3s linear 1s height-kf-name`
},
'.cls3': heightKf({
dur: '300ms',
tf: 'ease'
}) // => `.cls3`: {animation: `300ms ease height-kf-name`}
};
};at.scope
Creates @scope rule.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ at: { scope } }) => {
// set root selector
const baseScope = scope.root('.base');
// set limit selector
const limitedScope = baseScope.limit('.limit');
return {
// put rules in base scope
...baseScope({
span: {
textOverflow: 'hidden'
}
}),
// let's put the rules in a limited field of view
...limitedScope({
div: {
width: '100%'
}
}),
// let's put the rules in a limited area of visibility, excluding both borders
...limitedScope.none()({
p: {
fontSize: '1.5rem'
}
}),
// put rules in limited scope including low bound
...limitedScope.low()({
p: {
fontSize: '2rem'
}
}),
// put rules in limited scope including both bounds
...limitedScope.both()({
p: {
fontSize: '0.5rem'
}
})
};
};at.media
Creates @media rule.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ at: { media } }) => {
const firstCondition = or('width < 600px', 'width > 1000px');
const firstQuery = media(firstCondition);
const secondQuery = media.where(and(firstCondition, 'orientation: landscape'));
return {
// @media (width < 600px) or (width > 1000px) {...}
...firstQuery({
'.cls': {
width: '100%'
}
}),
// @media ((width < 600px) or (width > 1000px)) and (orientation: landscape) {...}
...secondQuery({
'.cls': {
width: '50%'
}
})
};
};at.container
Creates @container rule.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ at: { container, $logic: {or} } }) => {
const firstQuery = container.where(or('width < 600px', 'width > 1000px'));
const secondQuery = container.named.where('width > 100px');
return {
'.container': {
...secondQuery // container: cust-cq-1 / normal
},
// @container (width < 600px) or (width > 1000px) {...}
...firstQuery({
'.cls': {
width: '100%'
}
}),
// @container cust-cq-1 (width > 100px) {...}
...secondQuery({
'.cls': {
width: '50%'
}
})
};
};at.startingStyle
Creates @starting-style rule.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ at: { startingStyle } }) => {
return {
'.target': {
transition: 'background-color 1.5s',
backgroundColor: 'green',
...startingStyle({opacity: 0})
},
...startingStyle({
'.target': {
backgroundColor: 'transparent'
}
})
};
};at.supports
Creates @supports rule.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ at: { supports } }) => {
const supportsRule = supports.where('not (text-align-last:justify)');
return supportsRule({
div: {
textAlignLast: 'justify'
}
});
};at.layer
Creates @layer rule.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ at: { layer } }) => {
const layer1 = layer.named;
const layer2 = layer.named;
return {
...layer.list(layer1, layer2), // @layer cust-lay-1, cust-lay-2;
...layer1({ // @layer cust-lay-1{
'.padding-sm': {
padding: '0.5rem'
}
}),
...layer2({ // @layer cust-lay-2{
'.padding-sm': {
padding: '0.75rem'
}
})
};
};at.$logic
A set of functions for specifying complex logical conditions using @container and @media.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ at: { media, $logic: {and, or, not} } }) => {
const logic1 = and('prefers-reduced-motion: reduce', 'hover');
const query = media.where(or(logic1, 'width > 600px'));
return {
...query12({ // @media (prefers-reduced-motion: reduce) and (hover) or (width > 600px)
'.cls': {
maxWidth: '130px'
}
})
};
};at.$width, at.$height, at.$inline, at.$block
A set of functions for creating the width/height/inline size/block size conditions of @container and @media.
Example
import { TStyleSheetMaker } from 'effcss';
export const maker: TStyleSheetMaker = ({ at: { media, $width: {between} } }) => {
return media.where(between(30,80))({ // @media (min-width:30rem) and (max-width:80rem)
'.cls': {
flexShrink: 0
}
});
};