Skip to content

Instantly share code, notes, and snippets.

@fabiomcosta
Last active June 12, 2018 21:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fabiomcosta/875add280c38c4b25ee648b5a6043729 to your computer and use it in GitHub Desktop.
Save fabiomcosta/875add280c38c4b25ee648b5a6043729 to your computer and use it in GitHub Desktop.
# Mixed css-in-js solution
Current css-in-js solutions generaly have 2 different approaches to inserting styles on the page:
1. `style` DOM nodes that have their text `innerHTML` changed
2. static style extration, where a CSS file is created from the inlined JS
`1` is good because it allows applications to support dynamic styles that have their value changed overtime, but they
require a runtime that adds some overhead to the APP and will require the browser to parse the JS code that contains the CSS rules and then the inject CSS.
`2` is good because it allows developers to ship CSS directly to the browser, without the runtime cost.
No solution I found would mix both these approaches in a way that:
* static styles are extracted to external stylesheets (1)
* dynamic styles are injected on the page via `style` DOM nodes (2)
## Proposed Solution
The solution to this problem would be a `babel-transform`, similar to existing ones like https://github.com/martinandert/babel-plugin-css-in-js .
The difference would be that it would only move the "static" styles to the external stylesheet file.
## Questions
### How to differentiate what is static from what is dynamic?
To create static stylesheet files, we need to generate the style values at build time from other literal values like
pure strings and numbers, so that's how we can differentiate what approach to take.
// Example using `cxs` as the runtime css-in-js library and `classnames` as class concatenation utility.
//
// BEFORE babel transform
//
// './mixed.js'
import cxs from 'cxs';
class App extends React.Component {
render() {
const className = cxs({
':hover': { color: 'black' },
'@media screen and (min-width: 40em)': { fontSize: '48px' },
padding: '5px',
margin: this.props.addMargin ? '5x' : '0px',
border: `1px solid ${uxcore.palette('primary')}`
});
render <div className={ className } />;
}
}
//
// AFTER babel-transform
//
// './mixed.[hash].css' is created
.static-mixed-app-[hash] { // [hash] is a placeholder for am auto generated hash that we'll think about how to create.
padding: 5px;
}
.static-mixed-app-[hash]:hover {
color: 'black';
}
@media screen and (min-width: 40em) {
.static-mixed-app-[hash] {
font-size: 48px;
}
}
// './mixed.js'
import './mixed.[hash].css';
import cx from 'classnames';
import cxs from 'cxs';
class App extends React.Component {
render() {
const className = cx('static-mixed-app-[hash]', cxs({
border: `1px solid ${uxcore.palette('primary')}`,
margin: this.props.addMargin ? '5x' : '0px'
}));
render <div className={ className } />;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment