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. 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
  2. React: CSS in JS - Global Namespace - Dependencies -

    Dead Code Elimination - Minification - Sharing Constants - Non-deterministic Resolution - Isolation
  3. 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
  4. 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);
  5. 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} /> ); }
  6. Problems - Pseudo classes/elements - Media queries - Style fallbacks

    - Animations - !important - Separation of concerns - Debugging - Performance?
  7. 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
  8. 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>; } }
  9. const styles = { button: "_0" }; class Button extends

    Component { render() { return <button className={styles.button}>Click me!</button>; } } Component
  10. React CSS - "Pop" classes on and off - Keep

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

    { return { 'default': {button: {color: 'red'}} } } render() { return <button is="button">Click me!</button>; } }
  12. 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>; } }
  13. Activating classes classes() { // This is activated by default

    'default': { … }, // this.props.disabled === true 'disabled': { … }, // this.props.foo === 'bar' 'foo-bar': { … } }
  14. Radium Radium is a set of tools to manage inline

    styles on React elements. It gives you powerful styling capabilities without CSS. FormidableLabs/radium
  15. 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
  16. import Radium from 'radium'; @Radium class Button extends Component {

    render() { return <button style={styles.button}>Click me!</button>; } } Component
  17. 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.
  18. Animations const pulseKeyframes = Radium.keyframes({ '0%': {width: '10%'}, '50%': {width:

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

    fontFamily: 'Helvetica Neue, Helvetica, Arial, sans-serif' }, 'h1, h2, h3': { fontWeight: 'bold' } }} /> Style Component
  20. 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>
  21. 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
  22. React import React from 'react'; import styles from './button.css'; const

    Button = React.createClass({ render() { return <button className={styles.common}>Click me!</button>; } });
  23. CSS Loader module.exports = { module: { loaders: [ {

    test: /\.css$/, loader: "style-loader!css-loader" }, ] } };
  24. BEM .button { color: red; } .button--disabled { opacity: 0.5;

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

    opacity: 0.5; } <button class="button--disabled">Click me!</button>
  26. React import React from 'react'; import styles from './button.css'; const

    Button = React.createClass({ render() { return <button className={styles.disabled}>Click me!</button>; } });
  27. Dependencies .common { color: red; } .disabled { composes: common;

    composes: small from './typography.css'; opacity: 0.5; }
  28. 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
  29. 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>; } };
  30. Example [ ] + [ ] = [ 1 ]

    + [ 2 ] = 3 [ 1 ] + [ a ] = NaN
  31. 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> );
  32. 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
  33. 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
  34. FAQ

  35. $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
  36. 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
  37. Once you’re in, you’re in. - Copy and paste -

    No migration tools (write one!)
  38. 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
  39. 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
  40. 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
  41. - use the right tool, no matter if it breaks

    the rules - inline styles vs local scope - appearance vs state - have fun :) Recap