effcss
v4.5.1
Published
Self-confident CSS-in-JS
Maintainers
Readme
EffCSS is a self-confident CSS-in-JS library based only on the browser APIs. Use the full power of JS and TS to create styles.
Some features
- zero-dependency,
- framework agnostic,
- selectors isolation and minification out of the box,
- BEM based stylesheet types,
- compatible with any rendering (CSR, SSR, SSG).
Links
Devtools
- Mozilla Firefox
- zip for Chromium based browsers, that can be installed using chrome://extensions
Examples
Installation
Type in your terminal:
# npm
npm i effcss
# pnpm
pnpm add effcss
# yarn
yarn add effcssQuick start
Just call useStyleProvider in your code:
main.js
import { useStyleProvider } from "effcss";
const consumer = useStyleProvider({
attrs: {
min: true // to create minified selectors
}
});
const root = createRoot(document.getElementById("root"));
root.render(<App css={consumer} />);Each CSS stylesheet corresponds to a single Stylesheet maker. Stylesheet maker is a JS function that should return object with style rules:
App.tsx
import { useRef } from 'react';
import { IStyleProvider, TStyleSheetMaker } from 'effcss';
// you can describe your styles using BEM notation
// so that other people can use them via TypeScript generics
export type TCardMaker = {
/**
* Card block
*/
card: {
/**
* Card modifiers
*/
'': {
/**
* Card border radius
*/
rounded: '';
/**
* Card height
*/
h: 'full' | 'half';
};
/**
* Card logo
*/
logo: {
/**
* Logo width
*/
w: 's' | 'l';
},
/**
* Card footer
*/
footer: {
/**
* Footer visibility
*/
visible: '';
/**
* Footer size
*/
sz: 's' | 'm' | 'l';
};
};
}
const myStyleSheetMaker: TStyleSheetMaker = ({ bem, pseudo, at: { keyframes }, merge, palette, coef, size, units: {px} }) = {
// specify selector variants via generic
const selector = bem<TCardMaker>;
// 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}`,
[pseudo.h()]: {
filter: "drop-shadow(0 0 2em #61dafbaa)",
}
}, {
border: 'none',
background: palette.pale.xl.alpha(0.8),
aspectRatio: 1,
[pseudo.h()]: {
opacity: 0.5
}
});
return {
...sizeProperty,
...spin,
[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)
}
}))
};
};
export const App = (props: {
css: IStyleProvider;
}) => {
const { css } = props;
const stylesRef = useRef();
if (!stylesRef.current) {
const [card] = css.use(myStyleSheetMaker)<TCardMaker>;
// thanks to the TCardMaker type,
// you don't need to look at the implementation - just create the necessary attributes
stylesRef.current = {
card: card('card..rounded'),
// element with modifiers
footer: card({
card: {
footer: {
visible: '',
size: 'm'
}
}
})
};
}
const styles = stylesRef.current;
// just apply attributes to appropriate elements
return (
<div {...styles.card}>
<div {...styles.footer}>...</div>
</div>
);
};That's all. Enjoy simplicity.
