Self-confident CSS-in-JS
sh
npm
npm i effcss
pnpm
pnpm add effcss
yarn
yarn add effcss
`
Quick start
Just call useStyleProvider in your code:
main.js
`jsx
import { useStyleProvider } from "effcss";
const consumer = useStyleProvider({
attrs: {
min: true // to create minified selectors
}
});
const root = createRoot(document.getElementById("root"));
root.render( );
`
Each CSS stylesheet corresponds to a single Stylesheet maker. Stylesheet maker is a JS function that should return object or string with style rules:
maker.ts
`ts
import { TStyleSheetMaker } from 'effcss';
// you can describe your styles
// so that other people can use them via TypeScript generics
export type TMyMaker = {
/**
* Font-size utility
*/
fsz: 16 | 20 | 24;
/**
* Card scope
*/
card: {
/**
* Card border radius
*/
rounded: '';
/**
* Card height
*/
h: 'full' | 'half';
/**
* Card logo scope
*/
logo: {
/**
* Logo width
*/
w: 's' | 'l';
},
/**
* Card footer scope
*/
footer: {
/**
* Footer visibility
*/
visible: '';
/**
* Footer size
*/
sz: 's' | 'm' | 'l';
};
};
}
export const myMaker: TStyleSheetMaker = ({ select, pseudo: {h}, at: { keyframes, property }, merge, palette, coef, size, units: {px} }) = {
// specify selector variants via generic
const selector = select;
// create property with unique identifier
const widthProperty = property({
ini: px(200),
inh: false,
def: px(200) // will be used as fallback value in var() expression
});
// create keyframes with unique identifier
const spin = keyframes({
from: {
transform: 'rotate(0deg)',
},
to: {
transform: 'rotate(360deg)',
},
});
// deeply merge objects
const cardLogoStyles = merge({
width: widthProperty,
animation: 20s linear infinite ${spin},
...h({
filter: "drop-shadow(0 0 2em #61dafbaa)",
})
}, {
border: 'none',
background: palette.pale.xl.alpha(0.8),
aspectRatio: 1,
...h({
opacity: 0.5
})
});
return {
...sizeProperty,
...spin,
[selector('fsz:16')]: { ... },
[selector('card')]: { ... },
[selector('card.logo')]: cardLogoStyles,
[selector('card.logo.w:s')]: {
...widthProperty(px(100))
},
[selector('card.logo.w:l')]: widthProperty(px(300)),
[selector('card.rounded:')]: { ... },
[selector('card.h:full')]: { ... },
[selector('card.footer')]: { ... },
[selector('card.footer.visible:')]: { ... },
...each(coef.short, (k, v) => ({
[selector(card.footer.sz:${k})]: {
height: size(v)
}
}))
};
};
`
To use Stylesheet maker just pass it to cx (creates classnames string) or dx (creates data attributes object) methods of Style provider:
App.tsx
`tsx
import { useRef } from 'react';
import { useStyleProvider } from 'effcss';
import type { TMyMaker } from './maker';
import { myMaker } from './maker';
export const App = (props: {
css: IStyleProvider;
}) => {
const styleProvider = useStyleProvider();
const stylesRef = useRef();
// put it inside ref to avoid recalculations
if (!stylesRef.current) {
const [card] = css.use(myStyleSheetMaker);
// thanks to the TMyMaker type,
// you don't need to look at the implementation - just create the necessary attributes
stylesRef.current = {
// you can apply list of selectors
card: styleProvider.dx('card.rounded:', 'fsz:24'),
// or you can apply object with selectors
footer: styleProvider.dx({
card: {
footer: {
visible: '',
size: 'm'
}
}
})
};
}
const styles = stylesRef.current;
// just apply attributes to appropriate elements
return (
...
);
};
``