css in react

Post on 16-Apr-2017

1.059 Views

Category:

Engineering

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

CSSIN

React

Joe Sei�     @joesei�

THE BADTHE GOODAND THE UGLY

Familiarity - (CSS Level 1 released 19 years ago)Optimized Browser parsing and layoutJavaScript DOM APIInheritance structure - JSON likeMedia Queries - size and feature detectionPseudo Selectors - browser statesBasic math via calc()

CSS3 (THE GOOD)

Flat - nested rules not supportedNeeds vendor pre�xesNo variables, no functionsSome dynamic updates still require JavaScript

CSS3 (THE BAD)

Global namespace pollutionImportance, speci�city wars, & eventually !importantNondeterministic, depends on source orderEncapsulation - sharing code across components is scaryChanges & dead code elimination are manualMissing rules and syntax errors at runtime

CSS3 (THE UGLY)

(like �ux for CSS)Object-Oriented CSS (OOCSS)Scalable and Modular Architecture for CSS (SMACSS)Block, Element, Modi�er (BEM)ATOMIC CSSSUIT CSS

METHODOLOGIES

(like babel for CSS)SASSLESSStylusPostCSSAutopre�xer / cssnext

PRE/POST PROCESSORS

a like buttonEXAMPLE:

HTML<button class="btn btn‐primary">   Like <span class="badge">9</span> </button> 

OR

JSX & REACTconst LikeButton = ({ likes }) => {   return (     <button className="btn btn‐primary">       Like <span className="badge">{likes}</span>     </button>   ) } 

DOM API

1. const LikeButton = ({ likes }) => { 2. return ( 3. <button className="btn btn-primary"> 4. Like <span className="badge">{likes}</span> 5. </button> 6. ) 7. } 8.

AND

CSS3.btn { 

  display: inline‐block; 

  border: 0; 

  padding: 6px 12px; 

.btn.btn‐primary { 

  color: #fff; 

  background‐color: #f74A27; 

.btn.btn‐primary:hover { 

  background‐color: #ff7857; 

.btn.btn‐primary > .badge { 

  color: #f74A27; 

  background‐color: #fff; 

.btn > .badge { 

  display: inline‐block; 

  border‐radius: 10px; 

  padding: 3px 6px; 

  

SASS.btn { 

  display: inline‐block; 

  border: 0; 

  padding: 6px 12px; 

  &.btn‐primary { 

    color: $text‐color; 

    background‐color: $button‐color; 

    &:hover { 

      background‐color: $button‐color‐hover; 

    } 

    .badge { 

      color: $button‐color; 

      background‐color: $text‐color; 

    } 

  } 

   

  .badge { 

    display: inline‐block; 

    border‐radius: 10px; 

    padding: 3px 6px; 

  } 

RESULTLike  9

NOW LET'S TRY THE SAMEWITH INLINE STYLES

in React

JSONconst styles = { 

  'btn': { 

    'display': 'inline‐block', 

    'border': '0', 

    'padding': '6px 12px' 

  }, 

  'btn_primary': { 

    'color': '#fff', 

    'backgroundColor': '#f74A27' 

  }, 

  'btn_primary_hover': { 

    'backgroundColor': '#ff7857' 

  }, 

  'btn_primary__badge': { 

    'color': '#f74A27', 

    'backgroundColor': '#fff' 

  } 

  'btn__badge': { 

    'display': 'inline‐block', 

    'borderRadius': '10px', 

    'padding': '3px 6px' 

  } 

REACTimport React, { Component } from 'react' 

import { styles } from './styles' 

export const LikeButton = ({ likes }) => { 

  return ( 

    <button style={{ 

      ...styles.btn, 

      ...styles.btn_primary 

      }}> 

      Like 

      <span 

        style={{ 

        ...styles.btn__badge, 

        ...styles.btn_primary__badge 

        }}> 

        {likes} 

      </span> 

    </button> 

  ) 

  

CSS IN JAVASCRIPT

1. const styles = { 2. 'btn': { 3. 'display': 'inline-block', 4. 'border': '0', 5. 'padding': '6px 12px' 6. }, 7. 8. 'btn_primary': { 9. 'color': '#fff', 10. 'backgroundColor': '#f74A27' 11. }, 12. 'btn_primary_hover': { 13. 'backgroundColor': '#ff7857' 14. },

14. },

IN YOUR COMPONENT

1. import React, { Component } from 'react' 2. 3. import { styles } from './styles' 4. 5. export const LikeButton = ({ likes }) => { 6. return ( 7. <button style={{ 8. ...styles.btn, 9. ...styles.btn_primary 10. }}> 11. Like 12. <span 13. style={{ 14. ...styles.btn__badge,

14. ...styles.btn__badge,

RESULT WITH JSONLike  9

No pseudo selectors :hover :before etc.No media queries @media viewport etc.No rule nestingNo auto pre�xingNo CSS extractionFOUC

ISSUES WITH USING THE PLAIN

JSON object

Radiumreact-css-modulesstyled-componentsaphrodite, jss, cxs, csjs, glamor, so many more

FRAMEWORKS FOR

CSS in JS

RADIUMexport const styles = { 

  btn: { 

    display: 'inline‐block', 

    border: '0', 

    padding: '6px 12px', 

    btn_primary: { 

      color: '#fff', 

      backgroundColor: '#f74A27', 

      ':hover': { 

        backgroundColor: '#ff7857' 

      }, 

      badge: { 

        color: '#f74A27', 

        backgroundColor: '#fff' 

      } 

    } 

    badge: { 

      display: 'inline‐block', 

      borderRadius: '10px', 

      padding: '3px 6px' 

    } 

  } 

REACTimport React, { Component } from 'react' 

import Radium from 'radium' 

import { styles } from './styles' 

@Radium 

class LikeButton extends Component { 

  render () { 

    const { likes } = this.props 

    return ( 

      <button style={[ 

        styles.btn, 

        styles.btn.btn_primary 

      ]}> 

        Like <span style={[ 

          styles.btn.badge, 

          styles.btn.btn_primary.badge 

        ]}>{likes}</span> 

      </button> 

    ) 

  } 

export default LikeButton 

  

RADIUM STYLE SYNTAX

1. export const styles = { 2. btn: { 3. display: 'inline-block', 4. border: '0', 5. padding: '6px 12px', 6. 7. btn_primary: { 8. color: '#fff', 9. backgroundColor: '#f74A27', 10. 11. ':hover': { 12. backgroundColor: '#ff7857' 13. }, 14.

14.

RADIUM REACT SYNTAX

1. import React, { Component } from 'react' 2. import Radium from 'radium' 3. import { styles } from './styles' 4. 5. @Radium 6. class LikeButton extends Component { 7. render () { 8. const { likes } = this.props 9. return ( 10. <button style={[ 11. styles.btn, 12. styles.btn.btn_primary 13. ]}> 14. Like <span style={[

14. Like <span style={[

Wraps your function or component with @decoratorsCreates a class to manage state for :hover :active :focusRadium.getState(this.state, 'btnPrimary', ':hover')

Style similar child elements with .map()matchMedia for media queries - IE poly�ll, server-side?Styles are inline, extract into CSS for production?

RADIUM NOTES

No globals (with caveats)Built in dead code elimination, only used componentsPresentation logic is in your view, �nd and editState, constantsComposition, loops, computationDistribute via import and exportDynamic styling, app & DOM state e.g. data attributesSome :pseudo selectors re-implemented in JavaScriptFor example :last-child becomes i === arr.length - 1

INLINE STYLES (THE GOOD)

No ::after ::before ::selection

Media queries have to use window.matchMedia()

Autopre�xing display: -webkit-flex; display: flex;

Animations via @keyframes re-implemented in JSHighest priority before !important No Speci�city CascadingPerformanceDebugging in devtools is a painDuplicate markup for similar elements

INLINE STYLES (THE BAD)

CSS MODULES

Based on Interoperable CSS - loadable, linkable CSSWorks with SASS, PostCSS etc.Broken CSS = compile errorUsing an unde�ned CSS Module = no warning

REACT-CSS-MODULES

SASS@import "variables.scss"; 

.btn { 

  display: inline‐block; 

  border: 0; 

  padding: 6px 12px; 

  &.btn‐primary { 

    color: $text‐color; 

    background‐color: $button‐color; 

    &:hover { 

      background‐color: $button‐color‐hover; 

    } 

    .badge { 

      color: $button‐color; 

      background‐color: $text‐color; 

    } 

  } 

  .badge { 

    display: inline‐block; 

    border‐radius: 10px; 

    padding: 3px 6px; 

  } 

REACTimport React, { Component } from 'react' 

import CSSModules from 'react‐css‐modules' 

import styles from '../styles/likebutton.scss' 

@CSSModules(styles, {allowMultiple: true}) 

class LikeButton extends Component { 

  render () { 

    const { likes } = this.props 

    return ( 

      <button styleName="btn btn‐primary"> 

        Like <span styleName="badge">{likes}</span> 

      </button> 

    ) 

  } 

export default LikeButton 

  

REACT-CSS-MODULES SYNTAX

1. import React, { Component } from 'react' 2. import CSSModules from 'react-css-modules' 3. import styles from '../styles/likebutton.scss' 4. 5. @CSSModules(styles, {allowMultiple: true}) 6. class LikeButton extends Component { 7. render () { 8. const { likes } = this.props 9. return ( 10. <button styleName="btn btn-primary"> 11. Like <span styleName="badge">{likes}</span> 12. </button> 13. ) 14. }

14. }

styles object or this.props.styles[yourClasslassName]Con�gure your component classnames via localIdentName

Webpack CSS loader [path]___[name]__[local]___[hash:base64:5]

Generated classname styles-___likebutton__btn-primary___HYx7V

No overruling, intentionally nor unintentionallyComposition composes: parentClass same as @extend in SassOthers from ICSS :global :export :import

Use extract text plugin in production

REACT-CSS-MODULES NOTES

STYLED COMPONENTS

STYLEDimport styled from 'styled‐components' 

const StyledLikeButton = styled.button` 

  display: inline‐block; 

  border: 0; 

  padding: 6px 12px, 

  &.btn‐primary { 

    color: #fff; 

    background‐color: #f74A27; 

    &:hover { 

      background‐color: #ff7857; 

    } 

    .badge { 

      color: #f74A27; 

      background‐color: ${THEME.bgColor}; 

    } 

  } 

  .badge { 

    display: inline‐block; 

    border‐radius: 10px; 

    padding: 3px 6px; 

  } 

export default StyledLikeButton 

REACTimport React, { Component } from 'react' 

import StyledLikeButton from './StyledLikeButton' 

class LikeButton extends Component { 

  render () { 

    const { likes } = this.props 

    return ( 

      <StyledLikeButton className="btn‐primary"> 

        Like <span className="badge">{likes}</span> 

      </StyledLikeButton> 

    ) 

  } 

export default LikeButton 

  

STYLED COMPONENTS SYNTAX

1. import styled from 'styled-components' 2. 3. const StyledLikeButton = styled.button` 4. display: inline-block; 5. border: 0; 6. padding: 6px 12px, 7. &.btn-primary { 8. color: #fff; 9. background-color: #f74A27; 10. &:hover { 11. background-color: #ff7857; 12. } 13. .badge { 14. color: #f74A27;

14. color: #f74A27;

STYLED COMPONENTS USAGE

1. import React, { Component } from 'react' 2. import StyledLikeButton from './StyledLikeButton' 3. 4. class LikeButton extends Component { 5. 6. render () { 7. const { likes } = this.props 8. return ( 9. <StyledLikeButton className="btn-primary"> 10. Like <span className="badge">{likes}</span> 11. </StyledLikeButton> 12. ) 13. } 14.

14.

Autopre�xing included for freeWrite plain CSS, no weird poly�lls neededGenerated classnames are namespaced btn-primary gjkSC

Injects style tags into the document headSupports server-side rendering, but not extract text pluginkeyframes helper keeps your rules local to your componentTheming is built in

STYLED COMPONENTS NOTES

Web Components and Shadow DOMcssnextCSS4¿¡ !?

WHAT'S NEXT

View examples on Github

THANK YOU!

top related