fast af css-in-js in 1kb
const rule = cxs(`color: tomato`)
cxs is a minimal CSS-in-JS solution with an API that closely follows the native CSSStyleSheet API to maximize performance and reduce bloat.
- 1 KB
- Zero dependencies
- High performance
- Style encapsulation
- Deduplicates repeated styles
- Dead-code elimination
- Framework independent
- Media queries
- Pseudoclasses
- Nested selectors
- No CSS files
- Use plain CSS strings
- Optional React component API
- Optional Atomic mode
npm install cxs
cxs works with any framework, but this example uses React for demonstration purposes.
import React from 'react'
import cxs from 'cxs'
const Box = (props) => {
return (
<div {...props} className={className} />
)
}
const className = cxs(`
padding: 32px;
backgroundColor: tomato;
`)
export default Box
The cxs API works similarly to how native CSS works, by inserting one ruleset at a time.
// Insert a CSS rule and return a cxs rule object
const rule = cxs('color: tomato')
// return the generated classname
rule.toString()
To add a pseudoclass to the generated cxs classname, pass a string to options.child
.
const rule = cxs('color: lime', { child: ':hover' })
Commonly used pseudoclasses include chainable methods to hook multiple rules to the same classname. Just as native CSS does not have any notion of nesting, each chained method call creates a CSS ruleset.
const rule = cxs('color: tomato')
.hover('color: red')
.focus('outline: 1px solid blue')
.active('color: blue')
.disabled('opacity: .5')
To create a rule scoped by a media query, pass a string to options.media
.
const rule = cxs('color: tomato', { media: '@media screen and (min-width: 40em)' })
The chainable .media()
method can also be used to reuse a classname.
const rule = cxs('color: tomato')
.media('@media (min-width: 40em)', 'color: red')
})
Any valid CSS child selector syntax can be passed to options.child
, which will be concatenated with the generated classname.
cxs('color: tomato', { child: ' > h1' })
The chainable .child()
method can also be used to reuse a classname.
const rule = cxs('color: tomato')
.child(' > h1', 'color: black')
.child(' > h1:hover', 'color: blue')
The .push()
method can be used like the other chainable methods with the same options argument as the core cxs
function.
const rule = cxs('color: tomato')
.push('color: black', { child: ':checked' })
.push('color: blue', { child: ' > h1' })
To add rules without the generated classname, use options.selector
. This can be useful for global base styles.
cxs('box-sizing: border-box', { selector: '*' })
cxs('font-family: sans-serif; margin: 0', { selector: 'body' })
For Node.js environments, use the css
getter to return the static CSS string after rendering a view.
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import cxs from 'cxs'
import App from './App'
const html = ReactDOMServer.renderToString(<App />)
const css = cxs.css
const doc = `<!DOCTYPE html>
<style>${css}</style>
${html}
`
// Reset the cache for the next render
cxs.reset()
Note: cxs does not currently have a mechanism for rehydrating styles on the client, so use with caution in universal JavaScript applications.
Calling the cxs
function returns a cxs rule object.
import cxs from 'cxs'
const rule = cxs(cssDeclarationBlock, options)
The first argument to cxs
should be a string containing a valid CSS declaration block.
The second argument is an options object, where:
options.media
is a CSS media query stringoptions.child
is a pseudoclass or child selector string that follows the class selectoroptions.selector
is any valid CSS selector string, this will replace the generated classnameoptions.className
is a string for internal use to manually set the classname
The .toString()
method on the rule object returns a classname for use in HTML.
rule.toString() // '_0'
The rule object also includes chainable methods to add multiple rulesets with the same classname.
// Adds a pseudoclass rule with the same classname
rule.hover(declarations)
rule.focus(declarations)
rule.active(declarations)
rule.disabled(declarations)
// Adds any child selector with the same classname
rule.child(selector, declarations)
// Adds a media query rule with the same classname
rule.media(mediaQuery, declarations)
// Adds another rule with the same classname
rule.push(declarations, options)
// Gets a CSS string of CSS rules. Useful for server-side rendering
cxs.css
// Clear the cache and flush the stylesheet.
// This is useful for cleaning up in server-side contexts.
cxs.reset()
Additional exports
import {
Sheet, // create stylesheet function
css, // string of rendered CSS - same as cxs.css
reset // same as cxs.reset
} from 'cxs'
cxs also has an alternative higher order component API for creating styled React components, similar to the styled-components API.
import cxs from 'cxs/component'
const Heading = cxs('h1')`
margin: 0;
font-size: 32px;
line-height: 1.25;
`
cxs components can also handle dynamic styling based on props by passing a function in to the tagged template literal.
To remove non-HTML attribute props used for styling a component, pass an array of keys as the removeProps
option.
const removeProps = [
'color'
]
const Heading = cxs('h1', { removeProps })`
color: ${props => props.color};
`
For an alternative JavaScript object-based API that creates atomic CSS rules – similar to those found in Basscss or Tachyons , import the atomic module.
import cxs from 'cxs/atomic'
const className = cxs({
fontSize: 16,
color: 'tomato',
':hover': {
color: 'black'
},
'@media screen and (min-width: 32em)': {
fontSize: 20
}
})
For performance reasons, and since nesting is not part of native CSS, the default mode in cxs does not support nesting like some preprocessors do.
cxs does not handle vendor prefixing to keep the module size at a minimum.
For the previous version of cxs, see the v3 branch