Inline Styles

Inline Styles

Talking about inline styles is always hard and there are still a lot of unanswered questions, like: 'are you kidding me?'.
I'll try to give you the key to enter the magical world of #CSSinJS (or to stay away from it forever).

414db81dca21f468b4d7acd88172370c?s=128

Michele Bertoli

October 30, 2015
Tweet

Transcript

  1. Inline Styles @MicheleBertoli

  2. Front End Developer at YPlan Member of WEBdeBS Follow me

    @MicheleBertoli Michele Bertoli
  3. 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
  4. Survey JSX from 2.71 to 4.36 (+61%) Inline Styles from

    2.55 to 3.08 (+21%)
  5. Mindset - Give it five minutes - Unlearn everything -

    Components
  6. History

  7. React: CSS in JS Christopher Chedeau, Nov 2014

  8. React: CSS in JS - Global Namespace - Dependencies -

    Dead Code Elimination - Minification - Sharing Constants - Non-deterministic Resolution - Isolation
  9. Inline Styles are the Future Colin Megill, Mar 2015

  10. 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
  11. The End of Global CSS Mark Dalgleish, May 2015

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

    - Local scope
  13. JavaScript Style Sheets (JSSS) Netscape Communications Corporation, Aug 1996

  14. JavaScript Style Sheets (JSSS) h1 { font-size: 20pt; } document.tags.H1.fontSize

    = "20pt"; with (tags.H3) { color = "green"; }
  15. Inline Styles

  16. 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(<div style={divStyle}>Hello World!</div>, mountNode);
  17. Can your Style Sheets do this? :)

  18. Recompute handleChange(e) { this.setState({number: e.target.value}); } render() { const styles

    = {fontSize: this.state.number}; return ( <input type="number" style={styles} value={this.state.number} onChange={this.handleChange} /> ); }
  19. Problems - Pseudo classes/elements - Media queries - Style fallbacks

    - Animations - !important - Separation of concerns - Debugging - Performance?
  20. None
  21. Inline Styles #forreal - Uniqlo (US - mobile)

  22. CSS in JS

  23. None
  24. 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
  25. import StyleSheet from 'react-inline'; const styles = StyleSheet.create({ button: {color:

    'red', ':hover': {color: 'green'} } }); class Button extends Component { render() { return <button className={styles.button}>Click me!</button>; } }
  26. $ react-inline-extract --vendor-prefixes --compress-class-names --minify --bundle ../public/bundle.css --babelize ./src ./tmp

    CLI
  27. const styles = { button: "_0" }; class Button extends

    Component { render() { return <button className={styles.button}>Click me!</button>; } } Component
  28. ._0{color:red}._0:hover{color:green} CSS

  29. Autoprefixer included Pseudo classes Media queries Styles as object literals

    Extract CSS files x x x x x
  30. ReactCSS Bringing Classes to Inline Styles. casesandberg/reactcss

  31. React CSS - "Pop" classes on and off - Keep

    styles in one place - Simple to attach to elements
  32. import {Component} from 'reactcss'; class Button extends Component { classes()

    { return { 'default': {button: {color: 'red'}} } } render() { return <button is="button">Click me!</button>; } }
  33. <Button /> <button style="color:red;">Click me!</button> Default

  34. import {Component} from 'reactcss'; class Button extends Component { classes()

    { return { 'default': {button: {color: 'red'}}, 'disabled': {button: {opacity: 0.5}} } } render() { return <button is="button">Click me!</button>; } }
  35. <Button disabled /> <button style="color:red;opacity:0.5;">Click me!</button> Disabled

  36. Activating classes classes() { // This is activated by default

    'default': { … }, // this.props.disabled === true 'disabled': { … }, // this.props.foo === 'bar' 'foo-bar': { … } }
  37. Autoprefixer included Pseudo classes Media queries Styles as object literals

    Extract CSS files x x
  38. None
  39. Radium Radium is a set of tools to manage inline

    styles on React elements. It gives you powerful styling capabilities without CSS. FormidableLabs/radium
  40. 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
  41. const styles = { button: { color: 'red', ':hover': {

    color: 'green' } } }; Styles
  42. import Radium from 'radium'; @Radium class Button extends Component {

    render() { return <button style={styles.button}>Click me!</button>; } } Component
  43. <button style="color: red;">Click me!</button> <button style="color: green;">Click me!</button> Output

  44. 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.
  45. Animations const pulseKeyframes = Radium.keyframes({ '0%': {width: '10%'}, '50%': {width:

    '50%'}, '100%': {width: '10%'}, }); const styles = { animation: `${pulseKeyframes} 3s ease 0s infinite`, };
  46. import {Style} from 'radium'; <Style rules={{ body: { margin: 0,

    fontFamily: 'Helvetica Neue, Helvetica, Arial, sans-serif' }, 'h1, h2, h3': { fontWeight: 'bold' } }} /> Style Component
  47. Flash of Incorrectly Styled Content (FISC) { color: 'red', '@media

    (max-width: 500px)': { color: 'green' } } <button style="color:red;@media (max-width: 500px):[object Object];">Click me!</button>
  48. Autoprefixer included Pseudo classes Media queries Styles as object literals

    Extract CSS files x x x x
  49. None
  50. 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
  51. CSS .common { color: red; }

  52. React import React from 'react'; import styles from './button.css'; const

    Button = React.createClass({ render() { return <button className={styles.common}>Click me!</button>; } });
  53. Output <button class="JoFm3I_KMlvnoKpksAd60">Click me!</button>;

  54. CSS Loader module.exports = { module: { loaders: [ {

    test: /\.css$/, loader: "style-loader!css-loader" }, ] } };
  55. Parameters - modules - sourceMap - minimize - localIdentName (e.g.

    [name]---[local]---[hash:base64:5])
  56. BEM .button { color: red; } .button--disabled { opacity: 0.5;

    } <button class="button button--disabled">Click me!</button>
  57. SASS .button { color: red; } .button--disabled { @extends .button;

    opacity: 0.5; } <button class="button--disabled">Click me!</button>
  58. Composition .common { color: red; } .disabled { composes: common;

    opacity: 0.5; }
  59. React import React from 'react'; import styles from './button.css'; const

    Button = React.createClass({ render() { return <button className={styles.disabled}>Click me!</button>; } });
  60. Output <button class="button---disabled---3FMzF button---common---JoFm3" >Click me!</button>;

  61. Dependencies .common { color: red; } .disabled { composes: common;

    composes: small from './typography.css'; opacity: 0.5; }
  62. Output <button class="button---disabled---3FMzF button---common---JoFm3 typography---small---2Tu_R">Click me!</button>;

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

  64. 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
  65. React CSS Modules React CSS Modules implement automatic mapping of

    CSS modules. gajus/react-css-modules
  66. import CSSModules from 'react-css-modules'; import styles from './button.css'; @CSSModules(styles) class

    Button extends Component { render() { return <button styleName="common">Click me!</button>; } };
  67. Autoprefixer included Pseudo classes Media queries Styles as object literals

    Extract CSS files x x x
  68. Application State

  69. Example [ ] + [ ] = [ 1 ]

    + [ 2 ] = 3 [ 1 ] + [ a ] = NaN
  70. const {v1, v2} = this.state; const sum = parseInt(v1) +

    parseInt(v2); const styles = isNaN(sum) ? {color: 'red'} : null; return ( <div> <input className="v1" onChange={e => this.handleChange('v1', e)} /> <input className="v2" onChange={e => this.handleChange('v2', e)} /> <span className="r" style={styles}>{sum}</span> </div> );
  71. const sum = TestUtils.renderIntoDocument(<Sum />); 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
  72. const sum = TestUtils.renderIntoDocument(<Sum />); 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
  73. FAQ

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

  75. $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
  76. None
  77. 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
  78. #2 What if I want to change library or framework

    after 14 months?
  79. Once you’re in, you’re in. - Copy and paste -

    No migration tools (write one!)
  80. #3 My button has to look different according to his

    parent, how can I do it?
  81. .button { color: red; } .sidebar .button { font-weight: bold;

    } CSS
  82. const button = { color: red }; class Button extends

    Component { render() { const style = Object.assign({}, button, this.props.style); return <button style={style}>Click me!</button>; } } Inline Styles #1
  83. class Sidebar extends Component { render() { return <Button style={{font-weight:

    'bold'}} />; } } Inline Styles #1
  84. 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 <button style={style}>Click me!</button>; } } Inline Styles #2
  85. class Sidebar extends Component { render() { return <Button type="sidebar"

    />; } } Inline Styles #2
  86. .common { color: red; } .sidebar { composes: common; font-weight:

    bold; } CSS Modules
  87. import styles from './button.css'; class Button extends Component { render()

    { const type = this.props.type || 'common'; return <button className={styles[type]}>Click me!</button>; } } CSS Modules
  88. class Sidebar extends Component { render() { return <Button type="sidebar"

    />; } } CSS Modules
  89. The end

  90. - use the right tool, no matter if it breaks

    the rules - inline styles vs local scope - appearance vs state - have fun :) Recap
  91. Any questions?