Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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).

Michele Bertoli

October 30, 2015
Tweet

More Decks by Michele Bertoli

Other Decks in Programming

Transcript

  1. Inline Styles
    @MicheleBertoli

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

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

    View full-size slide

  5. Mindset
    - Give it five minutes
    - Unlearn everything
    - Components

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. Inline Styles
    are the Future
    Colin Megill, Mar 2015

    View full-size slide

  9. 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

    View full-size slide

  10. The End of
    Global CSS
    Mark Dalgleish, May 2015

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  14. Inline Styles

    View full-size slide

  15. 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);

    View full-size slide

  16. Can your Style Sheets do this? :)

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  19. Inline Styles #forreal
    - Uniqlo (US - mobile)

    View full-size slide

  20. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  26. ReactCSS Bringing Classes to Inline
    Styles.
    casesandberg/reactcss

    View full-size slide

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

    View full-size slide

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

    View full-size slide


  29. Click me!
    Default

    View full-size slide

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

    View full-size slide


  31. Click me!
    Disabled

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  35. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  38. Click me!
    Click me!
    Output

    View full-size slide

  39. 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.

    View full-size slide

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

    View full-size slide

  41. import {Style} from 'radium';
    body: {<br/>margin: 0,<br/>fontFamily: 'Helvetica Neue, Helvetica, Arial, sans-serif'<br/>},<br/>'h1, h2, h3': {<br/>fontWeight: 'bold'<br/>}<br/>}} /><br/>Style Component<br/>

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  44. 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

    View full-size slide

  45. CSS
    .common {
    color: red;
    }

    View full-size slide

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

    View full-size slide

  47. Output
    Click me!;

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  54. Output
    >Click me!;

    View full-size slide

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

    View full-size slide

  56. Output
    Click me!;

    View full-size slide

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

    View full-size slide

  58. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  62. Application State

    View full-size slide

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

    View full-size slide

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

    onChange={e => this.handleChange('v1', e)} />
    onChange={e => this.handleChange('v2', e)} />
    {sum}

    );

    View full-size slide

  65. 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

    View full-size slide

  66. 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

    View full-size slide

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

    View full-size slide

  68. $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

    View full-size slide

  69. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  76. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  82. Any questions?

    View full-size slide