Package Exports
- simplestyle-js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (simplestyle-js) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
simplestyle-js

A super simple CSS-in-JS solution with friendly TypeScript support and zero dependencies
Installation
npm install simplestyle-js --save
Basic Usage
import { createStyles } from 'simplestyle-js';
const [styles] = createStyles({
myButton: {
'&:hover': {
backgroundColor: 'red',
},
'&:active, &:focus': {
borderColor: 'blue',
},
backgroundColor: 'black',
border: '1px solid',
boxSizing: 'border-box',
color: 'white',
},
});
const btn = document.createElement('button');
btn.classList.add(styles.myButton);
document.body.appendChild(btn);
// Or React / JSX style component
const Button = (props) => <button {...props} className={styles.myButton}>Awesome button</button>
Advanced Usage
simplestyle-js
provides three APIs out of the box: createStyles
, keyframes
and rawStyles
.
import { createStyles, rawStyles } from 'simplestyle-js`;
// Useful if you want to apply style resets or any other global styles
rawStyles({
html: {
fontFamily: 'Arial, Helvetica, sans-serif',
fontSize: '16px',
},
'body *': {
boxSizing: 'border-box',
},
a: {
'&:hover': {
color: 'red',
textDecoration: 'none',
},
},
});
const [animationName] = keyframes({
'0%': {
borderColor: 'red',
},
'50%': {
borderColor: 'blue',
},
'100%': {
borderColor: 'red',
},
});
const [styles] = createStyles({
myButton: {
'&:hover': {
backgroundColor: 'red',
},
'&:active, &:focus': {
borderColor: 'blue',
},
animation: `${animationName} 1s linear infinite`, // use the generated animation name from the `keyframes` call above
backgroundColor: 'transparent',
border: '1px solid',
color: 'white',
},
header: {
'@media (max-width: 960px)': {
'& > $myButton': {
padding: '12px', // special padding for header button on mobile
},
height: '50px', // target smaller height on mobile devices
},
'& > $myButton': {
padding: '4px 8px',
},
height: '100px',
left: 0,
position: 'fixed',
right: 0,
top: 0,
},
}); // A new <style /> tag will appear in the header immediately after calling this function
const myHeader = document.createElement('header');
myHeader.classList.add(styles.header); // Will have a generated CSS classname in the format of '.header<unique_identifier>' ex .headerumdoaudnaoqwu
import { createStyles } from 'simplestyle-js';
const [styles, sheetContents] = createStyles({
nav: {
backgroundColor: '#ccaa00',
width: '24em',
},
}, { flush: false }); // prevents immediate flushing of the <style /> tag to the DOM
const [moreStyles, moreSheetContents] = createStyles({
navButtons: {
padding: '.5em',
},
}, false); // prevents immediate flushing of the <style /> tag to the DOM
const styleTag = document.createElement('style');
styleTag.innerHTML = `${sheetContents}${moreSheetContents}`;
import { createStyles } from 'simplestyle-js';
const [style1] = createStyles({
nav: {
backgroundColor: '#ccaa00',
width: '24em',
},
}, { accumulate: true }); // will make this sheet, and any other sheets where "accumulate: true" is used, aggregated into a single output `<style />`
const [style2] = createStyles({
navButtons: {
padding: '.5em',
},
}, { accumulate: true }); // accumulating is useful if you want to minimize DOM writes
Authoring Plugins
There are two types of plugins:
prehook
- Called on all style rule objects before generating the CSS string to be used
posthook
- Called on all style rule objects after the CSS string has been generated, but before it has been written to the DOM in a
<style />
tag
- Called on all style rule objects after the CSS string has been generated, but before it has been written to the DOM in a
- When creating a plugin, for improved SEO, it is highly recommended that you prefix the plugin package name with
simplestyle-js-plugin-*
.- See the official
postcss
Simplestyle plugin as an example: simplestyle-js-plugin-postcss
- See the official
Prehook Plugin Example Poor Man's Autoprefixer
import { createStyles, registerPreHook } from 'simplestyle-js';
// Poor-man's autoprefixer
const prehook = toRender => Object.entries(toRender).reduce((prev, [key, obj]) => ({ ...prev, [key]: { ...obj, '-webkit-transform': obj.transform } }), toRender);
registerPrehook(prehook);
const styles = createStyles({
preHookRoot: {
boxSizing: 'border-box',
},
});
const div = document.createElement('div');
div.classList.add(styles.prehookRoot); // This div will have box-sizing: border-box; as well as the -webkit-box-sizing vendor prefix provided in the preHook transformation
document.body.appendChild(div);
// Or in a React / JSX-style component
const MyComponent = () => <div className={styles.preHookRoot}>Some stuff here</div>
Posthook Plugin Example Full Autoprefixer and PostCSS integration
import autoprefixer from 'autoprefixer';
import postcss from 'postcss';
import { createStyles, registerPostHook } from 'simplestyle-js';
const posthookVendorPrefix = sheetContents => postcss([autoprefixer()]).process(s.getStyles()).css;
registerPostHook(posthookVendorPrefix);
const styles = createStyles({
postHookRoot: {
userSelect: 'none',
},
});
const div = document.createElement('div');
div.classList.add(styles.posthookRoot); // This div will have all vendor prefixed CSS properties based on how PostCSS and Autoprefixer transform the CSS
document.body.appendChild(div);
// Or in a React / JSX-style component
const MyComponent = () => <div className={styles.postHookRoot}>Some stuff here</div>
Plugin API
SimpleStyle does one thing out of the box well, and that's providing an intuitive way for you to write your CSS-in-JS in ways that are very similar to popular CSS Preprocessors like LESS, SASS, Stylus, among others. If you need to provide additional functionality that's not offered in the core library, simplestyle-js
provides easy ways to tie into lifecycle hooks in the style rendering process if you need to stub out additional behavior. This allows you to create and chain an infinite number of plugins, based on your needs.
In order to use a plugin, you need to register each plugin you'd like to use before you issue any calls to createStyles
. Plugins will be executed in the order in which they were registered. The methods available for you to register plugins are as follows:
registerPreHook(preHookFnc)
preHookFnc
is a function that accepts one parameter of an object whose keys are the generated classnames that will be outputted, and the values are the CSS properties that will be transformed and written to a sheet.- A valid
preHookFnc
is expected to return thetoRender
object it was provided, after you've done any manipulations. This allows you to do additional transforms on the rules before they're flushed to a CSS string and then written to the DOM.
registerPostHook(postHookFnc)
postHookFnc
is a function that accepts one parameter, which is the string contents of the sheet that should eventually be written to the DOM. This function should return a string, after you've done any desired transformations to the sheetContents.
What this library isn't
This library isn't trying to make grandiose assumption about how your styles should be rendered. Its goal is to simply provide a typed way of easily creating reusable styles close to your JavaScript / TypeScript components. Eventually a plugin system will be introduced so that you can stub out additional behaviors you might desire, but in the meantime, it is a zero-dependency way of creating CSS in JS and assumes that you're wise enough to know whether you've made a styling mistake (wrong property, wrong unit, invalid rule format, etc)