UVP*
and the future of
CSSinJS
* Unique Value Proposition
by Oleg Slobodskoi @oleg008
The world’s first
Project Messenger.
I maintain a
CSSinJS lib
CSSinJS is an
approach to describeCSS in JavaScript
CSSinJS
!==
Inline Styles
- Scoping
- Isolation
- Modules
- Code reuse
- Specificity
- Non-deterministic Resolution
- Dead code elimination
2014
Do we really need CSSinJS for this?
Can get there
with PostCSS?
So why CSSinJS?
JavaScript,
Motherfucker,
Do You Speak It!
2014
Since then I got a ridiculous amount of feedback …
… did a lot of experiments …
… learned from many other CSSinJS implementations …
… and from using in production.
Lost my hair!!!
My Top 9
Examples!
import {lighten} from 'polished'
const styles = {
button: {
background: lighten(0.2, '#CCCD64')
}
}
polished
import {zoomIn} from 'cssinjs-animations'
const styles = {
'@keyframes zoomIn': zoomIn,
box: {
position: 'absolute',
width: 50,
height: 50,
background: 'blue',
animation: {
name: 'zoomIn',
duration: '1s'
}
}
}
cssinjs-animations
import rtl 'rtl-css-js'
const styles = rtl({paddingLeft: 10})
rtl-css-js
const styles = {paddingRight: 10}
The contract
between packages
For JavaScript
1. Public API documentation
2. Tests
3. Linters
4. Typings
5. Runtime Errors
What about CSS?
NPM Registry
~ 550k Packages
Still wanna use BEM?
PBEM?
Package Block Element Modifier
How do you ensure?
- Source Order
- Cascading
- Global Styles
CSS Properties and Values should be part of the
contract
Many Runtimes
Is it a
CSSinJS war?
Is it
CSSinJS fatigue?
No, it is
absolutely
normal
The same is with DOM
libs
Room for
improvements
DX gets better
Performance
gets better
Best ideas win
<View style={{
marginTop: 5,
borderWidth: 1,
borderRadius: 5,
borderStyle: this.state.showBorder ? 'dotted' : null,
padding: 5
}}>
<Text style={{fontSize: 11}}>
Dotted border style
</Text>
</View>
const styles = csjs`
.panel {
border: 1px solid black;
background-color: ${green};
}
.title {
padding: 4px;
font-size: 15px;
}
`
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: ${({theme}) => theme.palette.headline};
`
import {ThemeProvider} from 'theming'
const theme = {
main: 'green'
}
const App = () => (
<ThemeProvider theme={theme}>
<SomeComponent />
</ThemeProvider>
)
Universal Theming
So what did
JSS learn?
box-shadow: 10px 10px 5px 5px black;
boxShadow: {
x: 10,
y: 10,
blur: 5,
spread: 5,
color: 'black'
}
Expanded syntax
Function values
button: {
fontSize: 12,
color: ({focused}) => focused ? 'black' : 'gray'
}
Template Strings
{
button: `
border-radius: 3px;
background-color: green;
color: red;
margin: 20px 40px;
padding: 10px;
`
}
import styled from 'styled-jss'
const Button = styled('button')({
fontSize: 12,
color: 'gray'
})
// Composition.
const PrimaryButton = styled(Button)({
color: 'blue'
})
<PrimaryButton>Click me!<PrimaryButton>
Styled Primitives
Theming
const styles = (theme) => ({
button: {
background: theme.colorPrimary
},
label: {
fontWeight: 'bold'
}
})
const StyledButton = injectSheet(styles)(Button)
Theming
Definition of "Theme",
anyone?
Look and Feel
CSS Variables
:root {
--main-bg-color: brown;
}
.one {
color: white;
background: var(--main-bg-color);
}
CSS Variables
cascade and inherit
:root {
--main-bg-color: brown;
}
.one {
color: white;
background: var(--main-bg-color);
}
global
When a contract between packages is vanilla CSS
Rebranding
Much easier with JavaScript
React Native
const styles = StyleSheet.create({
red: {
color: 'red'
},
boldblue: {
color: 'blue',
fontWeight: 'bold'
}
})
class SomeComponent extends Component {
render() {
return (
<View>
<Text style={styles.red}>red text</Text>
<Text style={styles.boldblue}>bold blue text</Text>
</View>
);
}
}
Subset of CSS
No shorthand notations
No media queries
No pseudo selectors
Typed CSS
Autocomplete
Linting
Contracts
We need
Universal Flow and Typescript
typings
Shorthand support
const styles = {
border: '1px solid red'
}
Expanded format
const styles = {
border: {
width: 1,
style: 'solid',
color: 'red'
}
}
Colocation
Styles and Markup
in one file
Write small components!
A complex component
is a composition
of simple components
State Driven Styles
User input
Mouse position
Viewport size
JavaScript Controlled Animations
Don't use Inline Styles!
High Performance
Function Values
JavaScipt Animations
at 60FPS
Faster than
React Inline Styles
2 Problems with
React Inline Styles
1. Reconciliation
in tree structure
2. Slow interface
<div
style={{
color: 'red',
fontSize: 12
}}
>
</div>
CSSOM
to the rescue
Same
CSSStyleDeclaration
Interface
CSSRulesList
is flat
const style = document.createElement(‘style’)
style.sheet.insertRule(‘.my-button {color: red}’, 0)
style.sheet.cssRules[0].style.color = ‘green’
Better Interface
const styles = {
button: {
color: (props) => props.isFocused ? 'red' : 'green'
}
}
Applies Changes Only
class MyComponent extends Component {
shouldComponentUpdate() {
return false
}
}
1
ISTF
Talk to me
Why CSSinJS
By Oleg Isonen
Why CSSinJS
- 4,264