Share
Embed
Oleg Slobodskoi, Chatgrape, Berlin — Javascript Style Sheets
Oleg Slobodskoi, Chatgrape, Berlin — Javascript Style Sheets
About the good parts of writing styles in javascript using JSS. Comparison to other existing CSS solutions and points about negative aspects got so far.
React Amsterdam
April 21, 2016
Transcript
54 slides
-
1 JavaScript Style JavaScript Style Sheets Sheets by Oleg Slobodskoi
jss React Amsterdam 2016 -
2 Plan Plan 1. React and CSS. 2. What are
inline styles. 3. Problems solved by inline styles. 4. Interesting CSS in JS libs. 5. What is JSS. 6. Problems solved by JSS. 7. Unsolved problems. -
3 React and CSS React and CSS React is about
React is about components components. . CSS is for CSS is for documents. documents. -
6 Inline styles Inline styles const style = {color: red}
<div style={style}></div> <div style="color: red"></div> HTML React const element = document.createElement('div') element.style.color = 'red' DOM -
7 Global Namespace Global Namespace Selectors are the evil. Try
to write an application inside of one function. -
8 Implicit Implicit Dependencies Dependencies <button class="default-button my-button">My Button</button> /*
buttons.css */ .default-button { cursor: pointer; } /* my-component.css */ .my-button { color: red; } -
9 Dead code Dead code A task for a compiler.
function module() { var styles = { button: { color: 'green' }, myButton: { color: 'red' } } // Renders a button. button({style: styles.myButton}) } function module(){button({style:{color:"red"}})}; -
10 Minification Minification function test(a) { var obj = {a:
a, b: 2}; return obj.a + obj.b; } window.a = test(1) window.a=3; No selectors to minify. JavaScript compressor for the rest. -
12 Non-deterministic Non-deterministic Resolution Resolution CSS Specificity Concept. /* my-button-1.css
*/ .my-button.my-blue-button { color: blue; } /* my-button-2.css */ button.my-button { color: red; } <head> <link href="my-button-1.css" rel="stylesheet" /> <link href="my-button-2.css" rel="stylesheet" /> </head> <body> <button class="my-button">My Button</button> </body> -
16 Can we do even Can we do even better?
better? YES. YES. -
20 3 Categories 3 Categories 1. Pure Inline 2. Mixed
Mode 3. Pure Style Sheets -
21 Pure Pure Inline Inline Already built in React No
support for @media, @keyframes etc. Performance Downsides -
22 Mixed Mode Mixed Mode Radium is using: React Events
for Pseudo Selectors. Style Sheets for @media and co. Inline for everything else. -
24 What is JSS. What is JSS. Good parts of
CSS only. Designed with components in mind. Declarative JavaScript. JavaScript to CSS compiler. Easy to reason about. -
25 How does it work. How does it work. Virtual
CSS Tree Process Render Run plugins on every VRule Output <style> with CSS. Abstraction for CSS Rules Manipulation -
27 Example with React Example with React import React from
'react' import {useSheet} from 'react-jss' @useSheet({ button: { color: 'green' } }) export default function Button(props) { const {classes} = props.sheet return <button className={classes.button}>{props.text}</button> } No magic in code. -
30 Problems it solves. Problems it solves. 1. All issues
solved by Inline Styles. 2. Issues introduced by Inline Styles. 3. More CSS Issues. -
31 Plan Plan 1. Media Queries 2. Keyframes Animation 3.
Font Face 4. Pseudo Selectors 5. Fallbacks 6. Rules Caching 7. Rules Sharing 8. Extensible Architecture 9. Tools Agnostic 10. Vendor Prefixer 11. Inheritance DSL Library -
32 Media Queries Media Queries export default { '@media (min-width:
1024px)': { button: { minWidth: 200 } } } const breakpoint = 1024 export default { [`@media (min-width: ${breakpoint}px)`]: { button: { minWidth: 200 } } } @media (min-width: 1024px) { .button-jss-0 { min-width: 200px; } } JSS in ES5 JSS in ES6 CSS Not possible Inline. -
33 Keyframes Animation Keyframes Animation export default { '@keyframes my-animation':
{ from: {opacity: 0}, to: {opacity: 1} } } const identifier = random() export default { [`@keyframes ${identifier}`]: { from: {opacity: 0}, to {opacity: 1} } } @keyframes my-animation { from { opacity: 0; } to { opacity: 1; } } JSS in ES5 JSS in ES6 CSS Not possible Inline. -
34 Font Face Font Face export default { '@font-face': {
fontFamily: 'MyWebFont', src: [ 'url(webfont.eot)', 'url(webfont.eot?#iefix) format(embedded-opentype)', 'url(webfont.woff2) format(woff2)' ] } } @font-face { font-family: 'MyWebFont'; src: url('webfont.eot'); src: url('webfont.eot?#iefix') format('embedded-opentype'), url('webfont.woff2') format('woff2'); } JSS CSS Not possible Inline. -
35 Pseudo Selectors Pseudo Selectors export default { button: {
color: 'green' '&:hover': { color: 'red' }, '&:active': { color: blue }, '&:before': { content: '"icon"' }, '& span': { verticalAlign: 'middle' } } } .jss-0-1 { color: green; } .jss-0-1:hover { color: red; } .jss-0-1:active { color: blue; } .jss-0-1:before { content: "icon"; } .jss-0-1 span { vertical-align: middle; } JSS CSS Not possible Inline. Inspired by Sass. -
36 Fallbacks Fallbacks export default { container: { display: ['box',
'flexbox','flex'] } } .jss-0-1 { display: box; display: flexbox; display: flex; } JSS CSS Not possible Inline. -
37 Rules Caching Rules Caching Not possible Inline. CSS Rules
are created just once. -
38 Rules Sharing Rules Sharing Not possible Inline. One rule
applies to all list items -
39 Class Names are fast. Class Names are fast. 1.
Find modified props. 2. Find props to unset. 3. Ensure valid property name, value, default unit. 4. Apply each property to an element -
40 Smaller Payload Smaller Payload Up to 50% smaller payload
when rendered at runtime. -
43 Vendor Prefixer Vendor Prefixer Plugin export default { container:
{ display: 'flex' } } .jss-0-1 { display: -webkit-flex; } JSS CSS -
45 JSS-ISOLATE JSS-ISOLATE Created a JSS plugin. and SOLVED INHERITANCE
PROBLEM Maxim Koretskiy “ This plugin protects styles from inheritance. It automatically creates a reset rule and applies it to every user's rule. -
48 Wrong Language? Wrong Language? import color from 'color' import
fonts from 'theme/fonts' import mixins from 'jss-mixins' import {gainsboroLight, grapeTypo, grey, blue, white} from 'theme/colors' const grapeTypoSemi = color(grapeTypo).alpha(0.5).rgbaString() export default { datalist: { background: white, border: `1px solid ${gainsboroLight}`, boxShadow: `0px 3px 4px 0 ${grapeTypoSemi}`, overflow: 'auto' }, item: { extend: [fonts.normal, mixins.ellipsis], padding: `5px 7px`, color: grey, cursor: `pointer` }, `@media (min-width: 1024px)`: { item: { color: blue } } } -
49 Let's experiment! Let's experiment! export default css` datalist {
background: ${white}; border: 1px solid ${gainsboroLight}; box-shadow: 0px 3px 4px 0 ${grapeTypoSemi}; overflow: auto } item { extend: ${[fonts.normal, mixins.ellipsis]}; padding: 5px 7px; color: ${grey}; cursor: ${pointer}; } @media (min-width: 1024px) { item { color: ${blue} } } ` Tagged template literals -
50 No standard DSL No standard DSL Styles reuse only
together with the lib. -
51 Missing dev tools Missing dev tools There is no
autocomplete tools like Emmet or IntelliSense. There is no CSS specific highlighting. No linters. -
52 Blocks initial Blocks initial rendering. rendering. Use it where
it doesn't matter. Use server-side rendering. Use a hybrid approach. -
53 Takeaways Takeaways CSS in JS is not only for
big projects, it's for any maintainable project. Use Inline Styles for: 1. State styles. For e.g. when a "width" of a component depends on its state. 2. Animations. Don't be religious. Keep an open mind. Use tools that solve your problems!