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

Oleg Slobodskoi, Chatgrape, Berlin — Javascript Style Sheets

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
Tweet

More Decks by React Amsterdam

Other Decks in Technology

Transcript

  1. 1
    JavaScript Style
    JavaScript Style
    Sheets
    Sheets
    by Oleg Slobodskoi
    jss
    React Amsterdam 2016

    View Slide

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

    View Slide

  3. 3
    React and CSS
    React and CSS
    React is about
    React is about components
    components.
    .
    CSS is for
    CSS is for documents.
    documents.

    View Slide

  4. 4
    First JSS release
    First JSS release

    View Slide

  5. 5

    View Slide

  6. 6
    Inline styles
    Inline styles
    const style = {color: red}


    HTML
    React
    const element = document.createElement('div')
    element.style.color = 'red'
    DOM

    View Slide

  7. 7
    Global Namespace
    Global Namespace
    Selectors are the evil.
    Try to write an application inside of
    one function.

    View Slide

  8. 8
    Implicit
    Implicit
    Dependencies
    Dependencies
    My Button
    /* buttons.css */
    .default-button {
    cursor: pointer;
    }
    /* my-component.css */
    .my-button {
    color: red;
    }

    View Slide

  9. 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"}})};

    View Slide

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

    View Slide

  11. 11
    Sharing Constants
    Sharing Constants
    Data driven styling
    Shared Breakpoints
    Javascript Layouts

    View Slide

  12. 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;
    }





    My Button

    View Slide

  13. 13
    Isolation
    Isolation
    No access to external components.
    Very high specificity.

    View Slide

  14. 14
    Complex Selectors
    Complex Selectors
    .article #comments ul > li > a.button

    View Slide

  15. 15
    Redundancy
    Redundancy
    Smaller payload.

    View Slide

  16. 16
    Can we do even
    Can we do even
    better?
    better?
    YES.
    YES.

    View Slide

  17. 17
    Other alternatives?
    Other alternatives?

    View Slide

  18. 18
    And more ...
    And more ...

    View Slide

  19. 19
    And more ...
    And more ...
    Text
    https://github.com/MicheleBertoli/css-in-js

    View Slide

  20. 20
    3 Categories
    3 Categories
    1. Pure Inline
    2. Mixed Mode
    3. Pure Style Sheets

    View Slide

  21. 21
    Pure
    Pure Inline
    Inline
    Already built in React
    No support for @media, @keyframes etc.
    Performance Downsides

    View Slide

  22. 22
    Mixed Mode
    Mixed Mode
    Radium is using:
    React Events for Pseudo Selectors.
    Style Sheets for @media and co.
    Inline for everything else.

    View Slide

  23. 23
    Pure
    Pure Style Sheets
    Style Sheets
    Aphrodite
    JSS

    View Slide

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

    View Slide

  25. 25
    How does it work.
    How does it work.
    Virtual
    CSS Tree
    Process Render
    Run plugins
    on every
    VRule
    Output <br/>with CSS.<br/>Abstraction for<br/>CSS Rules<br/>Manipulation<br/>

    View Slide

  26. 26
    React-JSS
    React-JSS
    Lazy compilation
    Ref counting

    View Slide

  27. 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 {props.text}
    }
    No magic in code.

    View Slide

  28. 28

    View Slide

  29. 29
    Boring CSS output.
    Boring CSS output.

    View Slide

  30. 30
    Problems it solves.
    Problems it solves.
    1. All issues solved by Inline Styles.
    2. Issues introduced by Inline Styles.
    3. More CSS Issues.

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  36. 36
    Fallbacks
    Fallbacks
    export default {
    container: {
    display: ['box', 'flexbox','flex']
    }
    }
    .jss-0-1 {
    display: box;
    display: flexbox;
    display: flex;
    }
    JSS CSS
    Not possible Inline.

    View Slide

  37. 37
    Rules Caching
    Rules Caching
    Not possible Inline.
    CSS Rules are created just once.

    View Slide

  38. 38
    Rules Sharing
    Rules Sharing
    Not possible Inline.
    One rule applies to all list items

    View Slide

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

    View Slide

  40. 40
    Smaller Payload
    Smaller Payload
    Up to 50% smaller payload
    when rendered at runtime.

    View Slide

  41. 41
    Tools Agnostic
    Tools Agnostic
    Library agnostic.
    Infrastructure agnostic.

    View Slide

  42. 42
    Extensible
    Extensible
    Small Core
    Plugins API.

    View Slide

  43. 43
    Vendor Prefixer
    Vendor Prefixer
    Plugin
    export default {
    container: {
    display: 'flex'
    }
    }
    .jss-0-1 {
    display: -webkit-flex;
    }
    JSS CSS

    View Slide

  44. 44
    Inheritance
    Inheritance
    Styles inherit from parent.
    Still no TRUE Isolation.

    View Slide

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

    View Slide

  46. 46
    Unsolved Problems
    Unsolved Problems
    :(
    :(

    View Slide

  47. 47
    Overengineered
    Overengineered
    Solution
    Solution
    If you feel it - don't use it.

    View Slide

  48. 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
    }
    }
    }

    View Slide

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

    View Slide

  50. 50
    No standard DSL
    No standard DSL
    Styles reuse only together with the lib.

    View Slide

  51. 51
    Missing dev tools
    Missing dev tools
    There is no autocomplete tools like
    Emmet or IntelliSense.
    There is no CSS specific highlighting.
    No linters.

    View Slide

  52. 52
    Blocks initial
    Blocks initial
    rendering.
    rendering.
    Use it where it doesn't matter.
    Use server-side rendering.
    Use a hybrid approach.

    View Slide

  53. 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!

    View Slide

  54. 54
    Thank You
    Thank You
    #reactamsterdam
    @oleg008
    https://github.com/jsstyles/jss

    View Slide