Slide 1

Slide 1 text

Inline Styles @MicheleBertoli

Slide 2

Slide 2 text

Front End Developer at YPlan Member of WEBdeBS Follow me @MicheleBertoli Michele Bertoli

Slide 3

Slide 3 text

Badmouthing CSS has the unfortunate side effect of driving entire communities away from React. Part of me wonders if this is on purpose. - Mark Dalgleish

Slide 4

Slide 4 text

Survey JSX from 2.71 to 4.36 (+61%) Inline Styles from 2.55 to 3.08 (+21%)

Slide 5

Slide 5 text

Mindset - Give it five minutes - Unlearn everything - Components

Slide 6

Slide 6 text

History

Slide 7

Slide 7 text

React: CSS in JS Christopher Chedeau, Nov 2014

Slide 8

Slide 8 text

React: CSS in JS - Global Namespace - Dependencies - Dead Code Elimination - Minification - Sharing Constants - Non-deterministic Resolution - Isolation

Slide 9

Slide 9 text

Inline Styles are the Future Colin Megill, Mar 2015

Slide 10

Slide 10 text

Inline Styles are the Future - Modularization - Computation & State - Explicit Modifiers - Support for pseudo elements and browser states - Support for media queries - Progressive Enhancement - Dead code elimination & Minification - Large teams / maintainability

Slide 11

Slide 11 text

The End of Global CSS Mark Dalgleish, May 2015

Slide 12

Slide 12 text

The End of Global CSS - import styles from './MyComponent.css'; - Local scope

Slide 13

Slide 13 text

JavaScript Style Sheets (JSSS) Netscape Communications Corporation, Aug 1996

Slide 14

Slide 14 text

JavaScript Style Sheets (JSSS) h1 { font-size: 20pt; } document.tags.H1.fontSize = "20pt"; with (tags.H3) { color = "green"; }

Slide 15

Slide 15 text

Inline Styles

Slide 16

Slide 16 text

React const divStyle = { color: 'white', backgroundImage: 'url(' + imgUrl + ')', WebkitTransition: 'all', // note the capital 'W' here msTransition: 'all' // 'ms' is the only lowercase vendor prefix }; React.render(
Hello World!
, mountNode);

Slide 17

Slide 17 text

Can your Style Sheets do this? :)

Slide 18

Slide 18 text

Recompute handleChange(e) { this.setState({number: e.target.value}); } render() { const styles = {fontSize: this.state.number}; return ( ); }

Slide 19

Slide 19 text

Problems - Pseudo classes/elements - Media queries - Style fallbacks - Animations - !important - Separation of concerns - Debugging - Performance?

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

Inline Styles #forreal - Uniqlo (US - mobile)

Slide 22

Slide 22 text

CSS in JS

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

React Inline Transform inline styles defined in JavaScript modules into static CSS code and class names so they become available to, e.g. the `className` prop of React elements. martinandert/react-inline

Slide 25

Slide 25 text

import StyleSheet from 'react-inline'; const styles = StyleSheet.create({ button: {color: 'red', ':hover': {color: 'green'} } }); class Button extends Component { render() { return Click me!; } }

Slide 26

Slide 26 text

$ react-inline-extract --vendor-prefixes --compress-class-names --minify --bundle ../public/bundle.css --babelize ./src ./tmp CLI

Slide 27

Slide 27 text

const styles = { button: "_0" }; class Button extends Component { render() { return Click me!; } } Component

Slide 28

Slide 28 text

._0{color:red}._0:hover{color:green} CSS

Slide 29

Slide 29 text

Autoprefixer included Pseudo classes Media queries Styles as object literals Extract CSS files x x x x x

Slide 30

Slide 30 text

ReactCSS Bringing Classes to Inline Styles. casesandberg/reactcss

Slide 31

Slide 31 text

React CSS - "Pop" classes on and off - Keep styles in one place - Simple to attach to elements

Slide 32

Slide 32 text

import {Component} from 'reactcss'; class Button extends Component { classes() { return { 'default': {button: {color: 'red'}} } } render() { return Click me!; } }

Slide 33

Slide 33 text

Click me! Default

Slide 34

Slide 34 text

import {Component} from 'reactcss'; class Button extends Component { classes() { return { 'default': {button: {color: 'red'}}, 'disabled': {button: {opacity: 0.5}} } } render() { return Click me!; } }

Slide 35

Slide 35 text

Click me! Disabled

Slide 36

Slide 36 text

Activating classes classes() { // This is activated by default 'default': { … }, // this.props.disabled === true 'disabled': { … }, // this.props.foo === 'bar' 'foo-bar': { … } }

Slide 37

Slide 37 text

Autoprefixer included Pseudo classes Media queries Styles as object literals Extract CSS files x x

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Radium Radium is a set of tools to manage inline styles on React elements. It gives you powerful styling capabilities without CSS. FormidableLabs/radium

Slide 40

Slide 40 text

Features - Conceptually simple extension of normal inline styles - Browser state styles to support :hover, :focus, and :active - Media queries - Automatic vendor prefixing - Keyframes animation helper - ES6 class and createClass support

Slide 41

Slide 41 text

const styles = { button: { color: 'red', ':hover': { color: 'green' } } }; Styles

Slide 42

Slide 42 text

import Radium from 'radium'; @Radium class Button extends Component { render() { return Click me!; } } Component

Slide 43

Slide 43 text

Click me! Click me! Output

Slide 44

Slide 44 text

How does Radium work? Add handlers to props if interactive styles are specified, e.g. onMouseEnter for :hover, wrapping existing handlers if necessary. If any of the handlers are triggered, e.g. by hovering, Radium calls setState to update a Radium-specific field on the components state object.

Slide 45

Slide 45 text

Animations const pulseKeyframes = Radium.keyframes({ '0%': {width: '10%'}, '50%': {width: '50%'}, '100%': {width: '10%'}, }); const styles = { animation: `${pulseKeyframes} 3s ease 0s infinite`, };

Slide 46

Slide 46 text

import {Style} from 'radium'; Style Component

Slide 47

Slide 47 text

Flash of Incorrectly Styled Content (FISC) { color: 'red', '@media (max-width: 500px)': { color: 'green' } } Click me!

Slide 48

Slide 48 text

Autoprefixer included Pseudo classes Media queries Styles as object literals Extract CSS files x x x x

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. CSS Modules css-modules/css-modules

Slide 51

Slide 51 text

CSS .common { color: red; }

Slide 52

Slide 52 text

React import React from 'react'; import styles from './button.css'; const Button = React.createClass({ render() { return Click me!; } });

Slide 53

Slide 53 text

Output Click me!;

Slide 54

Slide 54 text

CSS Loader module.exports = { module: { loaders: [ { test: /\.css$/, loader: "style-loader!css-loader" }, ] } };

Slide 55

Slide 55 text

Parameters - modules - sourceMap - minimize - localIdentName (e.g. [name]---[local]---[hash:base64:5])

Slide 56

Slide 56 text

BEM .button { color: red; } .button--disabled { opacity: 0.5; } Click me!

Slide 57

Slide 57 text

SASS .button { color: red; } .button--disabled { @extends .button; opacity: 0.5; } Click me!

Slide 58

Slide 58 text

Composition .common { color: red; } .disabled { composes: common; opacity: 0.5; }

Slide 59

Slide 59 text

React import React from 'react'; import styles from './button.css'; const Button = React.createClass({ render() { return Click me!; } });

Slide 60

Slide 60 text

Output Click me!;

Slide 61

Slide 61 text

Dependencies .common { color: red; } .disabled { composes: common; composes: small from './typography.css'; opacity: 0.5; }

Slide 62

Slide 62 text

Output Click me!;

Slide 63

Slide 63 text

Exceptions :global switches to global scope for the current selector.

Slide 64

Slide 64 text

CSS Modules disadvantages - You have to use camelCase CSS class names - You have to use styles object whenever constructing a className - Mixing CSS Modules and global CSS classes is cumbersome - Reference to an undefined CSS Module resolves to undefined without a warning

Slide 65

Slide 65 text

React CSS Modules React CSS Modules implement automatic mapping of CSS modules. gajus/react-css-modules

Slide 66

Slide 66 text

import CSSModules from 'react-css-modules'; import styles from './button.css'; @CSSModules(styles) class Button extends Component { render() { return Click me!; } };

Slide 67

Slide 67 text

Autoprefixer included Pseudo classes Media queries Styles as object literals Extract CSS files x x x

Slide 68

Slide 68 text

Application State

Slide 69

Slide 69 text

Example [ ] + [ ] = [ 1 ] + [ 2 ] = 3 [ 1 ] + [ a ] = NaN

Slide 70

Slide 70 text

const {v1, v2} = this.state; const sum = parseInt(v1) + parseInt(v2); const styles = isNaN(sum) ? {color: 'red'} : null; return (
this.handleChange('v1', e)} /> this.handleChange('v2', e)} /> {sum}
);

Slide 71

Slide 71 text

const sum = TestUtils.renderIntoDocument(); const v1 = TestUtils.findRenderedDOMComponentWithClass(sum, 'v1'); TestUtils.Simulate.change(v1, {target: {value: 1}}); const v2 = TestUtils.findRenderedDOMComponentWithClass(sum, 'v2'); TestUtils.Simulate.change(v2, {target: {value: 2}}); const r = TestUtils.findRenderedDOMComponentWithClass(sum, 'r'); expect(r.getDOMNode().textContent).toBe('3'); Jest

Slide 72

Slide 72 text

const sum = TestUtils.renderIntoDocument(); const v1 = TestUtils.findRenderedDOMComponentWithClass(sum, 'v1'); TestUtils.Simulate.change(v1, {target: {value: 1}}); const v2 = TestUtils.findRenderedDOMComponentWithClass(sum, 'v2'); TestUtils.Simulate.change(v2, {target: {value: 'a'}}); const r = TestUtils.findRenderedDOMComponentWithClass(sum, 'r'); expect(r.getDOMNode().style.color).toBe('red'); Jest

Slide 73

Slide 73 text

FAQ

Slide 74

Slide 74 text

#1 How are designers supposed to write CSS in JavaScript?

Slide 75

Slide 75 text

$bg: (); @for $i from 0 to $n { $a: $i*360deg/$n + $ac; $au: if($rev, 360 - $a/1deg, $a/1deg); $c: hsl($au + $ac2, 100%, 50%); $bg: $bg, radial-gradient(circle at $rc*(1 + cos($a)) $rc*(1 + sin($a)), rgba($c, $of), rgba($c, 0) 1.25*$rc); } background: $bg; SASS

Slide 76

Slide 76 text

No content

Slide 77

Slide 77 text

Inline Styles for designers - Keys are the camelCased version of the style names - Values are strings - Commas instead of semicolons - Vendor prefixes (other than ms) begin with a capital letter

Slide 78

Slide 78 text

#2 What if I want to change library or framework after 14 months?

Slide 79

Slide 79 text

Once you’re in, you’re in. - Copy and paste - No migration tools (write one!)

Slide 80

Slide 80 text

#3 My button has to look different according to his parent, how can I do it?

Slide 81

Slide 81 text

.button { color: red; } .sidebar .button { font-weight: bold; } CSS

Slide 82

Slide 82 text

const button = { color: red }; class Button extends Component { render() { const style = Object.assign({}, button, this.props.style); return Click me!; } } Inline Styles #1

Slide 83

Slide 83 text

class Sidebar extends Component { render() { return ; } } Inline Styles #1

Slide 84

Slide 84 text

const styles = { button: {color: 'red'}, sidebar: {font-weight: 'bold'} }; class Button extends Component { render() { const {type} = this.props; const style = Object.assign({}, styles.button, styles[type]); return Click me!; } } Inline Styles #2

Slide 85

Slide 85 text

class Sidebar extends Component { render() { return ; } } Inline Styles #2

Slide 86

Slide 86 text

.common { color: red; } .sidebar { composes: common; font-weight: bold; } CSS Modules

Slide 87

Slide 87 text

import styles from './button.css'; class Button extends Component { render() { const type = this.props.type || 'common'; return Click me!; } } CSS Modules

Slide 88

Slide 88 text

class Sidebar extends Component { render() { return ; } } CSS Modules

Slide 89

Slide 89 text

The end

Slide 90

Slide 90 text

- use the right tool, no matter if it breaks the rules - inline styles vs local scope - appearance vs state - have fun :) Recap

Slide 91

Slide 91 text

Any questions?