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 full-size 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 full-size 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 full-size slide

  4. 4
    First JSS release
    First JSS release

    View full-size slide

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


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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. 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 full-size slide

  9. 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 full-size slide

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

    View full-size slide

  11. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  14. 15
    Redundancy
    Redundancy
    Smaller payload.

    View full-size slide

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

    View full-size slide

  16. 17
    Other alternatives?
    Other alternatives?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  22. 23
    Pure
    Pure Style Sheets
    Style Sheets
    Aphrodite
    JSS

    View full-size slide

  23. 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 full-size slide

  24. 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 full-size slide

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

    View full-size slide

  26. 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 full-size slide

  27. 29
    Boring CSS output.
    Boring CSS output.

    View full-size slide

  28. 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 full-size slide

  29. 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 full-size slide

  30. 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 full-size slide

  31. 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 full-size slide

  32. 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 full-size slide

  33. 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 full-size slide

  34. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  37. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  40. 42
    Extensible
    Extensible
    Small Core
    Plugins API.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  43. 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 full-size slide

  44. 46
    Unsolved Problems
    Unsolved Problems
    :(
    :(

    View full-size slide

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

    View full-size slide

  46. 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 full-size slide

  47. 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 full-size slide

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

    View full-size slide

  49. 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 full-size slide

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

    View full-size slide

  51. 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 full-size slide

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

    View full-size slide