Skip to content

公用事业

虽然并非必须使用工具函数,但在某些情况下,它们可以简化操作。每个 StyleSheet maker 函数都接受一个工具函数对象。

dash

使用连字符连接基本元素。

Example
ts
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

使用逗号连接基本元素。

Example
ts
import { TStyleSheetMaker } from 'effcss';

export const maker: TStyleSheetMaker = ({ comma }) => {
    const fonts = ['Georgia', 'serif'];
    return {
        html: {
            fontFamily: comma(...fonts)
        }
    };
};

space

利用空间组合基本元素。

Example
ts
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

遍历指定长度的数字序列。

Example
ts
import { TStyleSheetMaker } from 'effcss';

export const maker: TStyleSheetMaker = ({ range }) => {
    const rules = range(5, (sz) => {
        return {
            [`.h-${sz}`]: {
                height: sz + 'rem'
            }
        };
    });
    return {
        ...rules
    };
};

each

遍历对象的键值对或数组的值。

Example
ts
import { TStyleSheetMaker } from 'effcss';

export const maker: TStyleSheetMaker = ({ each }) => {
    const rules = range(5, (sz) => {
        return {
            [`.h-${sz}`]: {
                height: sz + 'rem'
            }
        };
    });
    return {
        ...rules
    };
};

merge

执行深度对象合并。

Example
ts
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

如果第一个参数为真,则返回第二个参数;否则返回空对象。

Example
ts
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(已弃用)

该工具已被弃用,将在下一个主要版本中移除。要获取变量的值,请使用 theme.variable 工具。

创建一个包含全局主题变量的 var() 表达式。

Example
ts
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 (deprecated)

The utility has been deprecated and will be removed in the next major release. To get the value of this variable, use the theme.time utility.

根据全局时间变量计算时间值。

Example
ts
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(已弃用)

该工具已被弃用,将在下一个主要版本中移除。要获取此变量的值,请使用 theme.size 工具。

根据全局尺寸变量计算尺寸值。

Example
ts
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(已弃用)

该工具已被弃用,将在下一个主要版本中移除。要获取此变量的值,请使用 theme.angle 工具。

根据全局角度变量计算角度值。

Example
ts
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)(已弃用)

该工具已被弃用,将在下一个主要版本中移除。要获取此变量的值,请使用 theme.easing 工具。

计算类型为 <easing-function> 的值。当不带参数调用时,它返回全局值;当带参数调用时,它返回 cubic-bezier 函数的配置值。

Example
ts
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)

生成一个以该样式表为前缀的唯一选择器。

Example
ts
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(已弃用)

该工具已被弃用,将在下一个主要版本中移除。请改用 select 工具。

解析作用域 BEM 选择器。

Example
ts
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'
        }
    };
};

theme (^4.12.0)

一组用于检索 CSS 主题变量值的实用工具:

Example
ts
import { TStyleSheetMaker } from 'effcss';

type TMakerTunings = {
    size: string;
    card: {
        color: string;
    }
};

export const maker: TStyleSheetMaker = ({ theme }) => {
    const {size, space, angle, time, easing, neutral, color, contrast, variable, tuning } = theme;
    // only tuning variables are available to external code
    // so they can configure the stylesheet from the outside 
    const tune = tuning<TMakerTunings>; // ^4.13.0
    return {
        '.base': {
            background: neutral, // var(--f-neutral);
            borderColor: contrast, // var(--f-contrast);
            color, // var(--f-color);
            // measurable variables add units automatically
            width: size, // calc(var(--f-size) * 1px);
            padding: space, // calc(var(--f-space) * 1px);
            transform: `skew(${angle})`, // skew(calc(var(--f-angle) * 1deg));
            transitionDuration: time, // calc(var(--f-time) * 1ms);
            transitionTimingFunction: easing // var(--f-easing);
        },
        '.scalable': {
            // the second argument of `variable` is fallback value
            opacity: variable('opacity.main', 0.5), // var(--f-opacity-main,0.5);
            // measurable variables are scalable
            width: size(10), // calc(var(--f-size) * 10px);
            padding: space(2), // calc(var(--f-space) * 2px);
            transform: `skew(${angle(2)})`, // skew(calc(var(--f-angle) * 2deg));
            transitionDuration: time(1.5)
        },
        '.indexed': {
            // this is how you can access array values
            // with zero index value as fallback
            background: neutral[2],
            borderColor: contrast[5],
            color: color[3], // var(--f-color-3,var(--f-color));
            width: size[5], // calc(var(--f-size-5,var(--f-size)) * 1px);
            padding: space[2], // calc(var(--f-space-2,var(--f-space)) * 1px);
            transform: `skew(${angle[1]})`,
            transitionDuration: time[8],
            transitionTimingFunction: easing[2]
        },
        '.scalable-indexed': {
            opacity: variable('opacity.main.2', variable('opacity.main', 1)), // var(--f-opacity-main-2,var(--f-opacity-main,1));
            // you can also scale indexed values
            width: size[5](10), // calc(var(--f-size-5,var(--f-size)) * 10px);
            padding: space[2](3), // calc(var(--f-space-2,var(--f-space)) * 3px);
            transform: `skew(${angle[1](5)})`, // skew(calc(var(--f-angle-1,var(--f-angle)) * 5deg));
            transitionDuration: time[8](3) // calc(var(--f-time-8,var(--f-time)) * 3ms);
        },
        '.with-tuning': {
            background: tune('card.color', 'aqua'), // background:var(--f1-card-color,aqua);
            width: tune('size', '16px') // width: var(--f1-size,16px);
        }
    };
};

units

CSS单元函数组。

Example
ts
import { TStyleSheetMaker } from 'effcss';

export const maker: TStyleSheetMaker = ({ units }) => {
    const { px, rem } = units;
    return {
        '.custom': {
            width: px(100),
            height: rem(1.5)
        }
    };
};

pseudo

一组伪类/伪元素函数。

Example
ts
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

一组用于处理颜色的函数。

Example
ts
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

调色板类的一个实例。它允许您使用 oklch 格式的颜色,其亮度、色度和色调值均取自主题变量。

Example
ts
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

系数类的一个实例。允许您使用取自主题变量的预定义值的系数范围。

Example
ts
import { TStyleSheetMaker } from 'effcss';

export const maker: TStyleSheetMaker = ({ coef, size }) => {
    return each(coef.$m.short, (k, v) => ({
        [`.size-` + k]: {
            width: size(v)
        }
    }));
};

at.property

创建 @property 规则。

Example
ts
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

创建 @keyframes 规则。

Example
ts
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

创建 @scope 规则。

Example
ts
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

创建 @media 规则。

Example
ts
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

创建 @container 规则。

Example
ts
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

创建 @starting-style 规则。

Example
ts
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

创建 @supports 规则。

Example
ts
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

创建 @layer 规则。

Example
ts
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

一组用于使用 @container@media 指定复杂逻辑条件的函数。

Example
ts
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

一组用于创建 @container@media 的宽度/高度/行内大小/块大小条件的函数。

Example
ts
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
        }
    });
};

根据 Apache-2.0 许可证发布。