CSS-in-JS compiler based on the ideas of Facebook's stylex
- Compiles to atomic CSS
- Typed styles using TypeScript
- Converts font-size to REM¹
- No selectors
# Yarn
yarn add style9
# npm
npm install style9
import style9 from 'style9';
// Styles are created by calling style9.create
const styles = style9.create({
blue: {
color: 'blue',
},
red: {
color: 'red'
}
});
// `styles` is now a function which can be called with the keys of the style
// object, and returns a string of class names.
// Ternary operator and logical AND is supported
document.body.className = styles('blue', isRed && 'red');
// `styles` can also be called with an object of booleans
styles({
blue: isBlue,
red: isRed
});
// To combine with external styles, style9 can be called with the style objects
style9(styles.blue, otherStyles.yellow);
// Styles have to be statically defined, but constants are supported
const RED = 'red';
const moreStyles = style9.create({
red: {
color: RED
},
margin: {
// All properties are written in camelcase
// Integers are converted to pixels where appropriate
marginTop: 8
},
padding: {
// Longhands take precedent over shorthands
// Will resolve to '12px 12px 12px 18px'
paddingLeft: 18,
// Shorthand values will be copied to longhands which means
// `padding: '12px 18px'` etc. is not supported
padding: 12
},
text: {
// Font size is converted to REMs to follow users settings
fontSize: 14
},
fadeIn: {
// Animation names are created by calling style9.keyframes
animationName: style9.keyframes({
from: {
opacity: 0
},
to: {
opacity: 1
}
}),
animationDuration: '1s'
},
mobile: {
// Media queries are supported as well
// They will be sorted mobile-first
// NOTE: Media queries are not supported in TypeScript due to issue #17867
'@media (min-width: 800px)': {
display: 'none'
}
},
pseudo: {
// Pseudo-classes and elements can be used
':hover': {
// They can be nested, as can media queries
':active': {
'::before': {
content: 'attr(title)'
}
}
}
}
});
minifyProperties
- minify the property names of style objects. Unless you pass custom objects tostyle9()
not generated bystyle9.create()
, this is safe to enable and will lead to smaller JavaScript output but mangled property names. Consider enabling it in production. Default:false
const babel = require('@babel/core');
const output = babel.transformFile('./file.js', {
plugins: [['style9/babel', { /* options */ }]]
});
// Generated CSS
console.log(output.metadata.style9);
import style9 from 'style9/rollup';
export default {
// ...
plugins: [
style9({
// include & exclude are supported according to rollup conventions
// Either fileName or name is required. It will be passed to emitFile
// fileName: unique name to for output file
// name: name to use for output.assetFileNames pattern
// ...Options
})
]
};
const Style9Plugin = require('style9/webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.(tsx|ts|js|mjs|jsx)$/,
use: Style9Plugin.loader,
options: { /* ...Options */ }
},
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new Style9Plugin(),
new MiniCssExtractPlugin()
]
};
const withTM = require('next-transpile-modules')(['style9']);
const withStyle9 = require('style9/next');
module.exports = withStyle9({ /* ...Options */ })(withTM());
module.exports = {
plugins: [
{
resolve: 'style9/gatsby',
options: { /* ...Options */ }
}
]
}
There is an example repo you can see to get started.