effcss
Version:
Self-confident CSS-in-JS
212 lines (180 loc) • 6.39 kB
Markdown
<p align="center">
<a href="https://effnd.tech/css/">
<img alt="effcss" src="https://effnd.tech/css/logo.svg" height="256px" />
</a>
</p>
<h1 align="center">EffCSS</h1>
<div align="center">
[](https://gitverse.ru/msabitov/effcss/content/master/LICENSE)
[](https://www.npmjs.com/package/effcss)


</div>
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
- [Docs](https://effnd.tech/css/)
- [Repository](https://gitverse.ru/msabitov/effcss)
- [Github mirror](https://github.com/msabitov/effcss)
## Devtools
- [Mozilla Firefox](https://addons.mozilla.org/ru/firefox/addon/effcss-developer-tools/)
- [zip for Chromium based browsers](https://storage.yandexcloud.net/effcss-devtools/chromium-based.zip), that can be installed using [chrome://extensions](https://www.geeksforgeeks.org/installation-guide/how-to-add-extensions-in-google-chrome-browser/)
## Examples
- [Vanilla TS](https://stackblitz.com/edit/effcss-ts-vitejs?file=src%2Fmain.ts)
- [React](https://stackblitz.com/edit/effcss-react-vitejs?file=src%2FApp.tsx)
- [Svelte](https://stackblitz.com/edit/effcss-svelte-vitejs?file=src%2FApp.svelte)
- [Vue](https://stackblitz.com/edit/effcss-vue-vitejs?file=src%2FApp.vue)
- [Angular](https://stackblitz.com/edit/effcss-angular-vitejs?file=src%2Fmain.ts)
- [SolidJS](https://stackblitz.com/edit/effcss-solidjs-vitejs?file=src%2FApp.tsx)
- [Preact](https://stackblitz.com/edit/effcss-preact-vitejs?file=src%2Fapp.tsx)
- [Qwik](https://stackblitz.com/edit/effcss-qwik-vitejs?file=src%2Fapp.tsx)
- [Lit](https://stackblitz.com/edit/effcss-lit-vitejs?file=src%2Fmy-element.ts)
- [React SSR](https://stackblitz.com/edit/effcss-react-ssr-vitejs?file=src%2FApp.tsx)
- [Svelte SSR](https://stackblitz.com/edit/effcss-svelte-ssr-vitejs?file=src%2FApp.svelte)
- [Vue SSR](https://stackblitz.com/edit/effcss-vue-ssr-vitejs?file=src%2FApp.vue)
- [Astro SSG](https://stackblitz.com/edit/effcss-ts-astro?file=src%2Fpages%2Findex.astro)
## Installation
Type in your terminal:
```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(<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**
```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 interface TCardMaker {
/**
* Card block
*/
card: {
/**
* Card modifiers
*/
'': {
/**
* Card border radius
*/
rounded: '';
/**
* Card height
*/
h: 'full' | 'half';
};
/**
* Card logo
*/
logo: {},
/**
* Card footer
*/
footer: {
/**
* Footer visibility
*/
visible: '';
/**
* Footer size
*/
sz: 's' | 'm' | 'l';
};
};
}
const myStyleSheetMaker: TStyleSheetMaker = ({ bem, pseudo, at: { keyframes }, merge, palette, coef, size }) = {
// specify selector variants via generic
const selector = bem<TCardMaker>;
// create unique keyframes identifier
const spin = keyframes({
from: {
transform: 'rotate(0deg)',
},
to: {
transform: 'rotate(360deg)',
},
});
// deeply merge objects
const cardLogoStyles = merge({
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 {
...spin,
[selector('card')]: { ... },
[selector('card.logo')]: cardLogoStyles,
[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.