Who?

Senior FED

Back to the past (1991)

1995

2002

2005

2011

2010

2014

2008

2015

2010

2014

2002

1991

1995

2005

2008

2011

2013

2015

<Template/>

JS Logic

CSS/SCSS

Component

CSS/SCSS

2013

2017

Component

CSS/SCSS

CSS-in-JS

CSS/SCSS

Just why???

Yippee!

CSS in JS

The Good

The Bad

& The Ugly

The Fear

...of CSS

CSS is awesome

BUT

Chris

Chris

Chris


/* style.css */

.chris {
  color:'blue';
}

/* style.css */

.chris {
 color:'gold';
}

/* style.css */

.chris {
 color:'green';
}

<div class="my-awesome-container">
    <button class="chris">
        Chris!
    </button>
</div>

Chris!

😰

!important

Scaling

Global namespace

Implicit dependencies

Code Maintenance (DEAD code)

Scaling

Minification

Sharing constants

Non deterministic order of source

<h2 class="42">
    I'm happy!
</h2>

You are. But I'm not 🤦‍♀️

The (not) old style

OOCSS & SMACSS

BEM

CSS processors

NOT pure CSS

HARD to migrate

NAMING !

STILL NOT scalable

(that HUGE CSS file!)

Real-time CSS modifiers ?

var()

😍

😱

JavaScript

😰 Performance 

😰 Complexity 

CSS has fundamental flaws at scale that can be solved by writing styles in JS .

@VJEUX — NOVEMBER 2014

SS-in-JS

<Component/>

JS

CSS

React Inline Style

import React from "react";
import { Image } from "cloudinary-react";
import { cloudName } from "../settings";

const avatarStyle = {
  display: "flex",
  position: "relative",
  alignItems: "center",
  width: "150px",
  height: "150px"
};

const Avatar = props => {
  return (
    <div style={avatarStyle}>
      <Image
        cloudName={cloudName}
        publicId={props.publicId}
        alt={props.title}
        width={150}
        height={150}
        crop="thumb"
        radius="max"
        opacity={50}
      />
    </div>
  );
};

export default Avatar;

React INLINE Style

//...
/* style of container */
const avatarStyle = {
  /*...*/
};

/* style of avatar initials */
const titleStyle = {
  position: "absolute",
  display: "flex",
  fontSize: "40px",
  width: "inherit",
  alignItems: "center",
  justifyContent: "center"
};

const Avatar = props => {
  return (
    <div style={avatarStyle}>
      <Image
        cloudName={cloudName}
        publicId={props.publicId}
        alt={props.title}
        width={150}
        height={150}
        crop="thumb"
        radius="max"
        opacity={50}
      />
      <div style={titleStyle}>
        {props.title[0].toUpperCase()}
      </div>
    </div>
  );
};
//...

Animations

Scalability

Media queries

🙄

Readability

How about

INLINE but NOT INLINE?

Ideal concepts

Scoped CSS per component

Extendable CSS in global scope

Full CSS support

SSR (Static CSS extraction)

The EXTEND

Debuggable

Syntax highlighting

Free of dead CSS code

Themes

40+

libraries

2015

<Component/>

JS

CSS

.css

import "./button.css";

//will become

import styles from "./button.css";
/* button.css */

:local(.button) {
/* by default */
/*...*/
}

//is the same as
.button { /*...*/ }

<Component/>

JS

CSS

Scoped

Composition

Share-able

Full CSS support

Pre-processor support

Dynamic modifiers

Reusable CSS

/*Item.module.css*/
.itemCard {
  width: 220px;
  padding: 5px;
  box-shadow: 0 1px 2px rgba(0,0,0,.2);
  border: 1px solid lightgray;
}

.itemCard:hover {
  background-color: #d3d3d363;
  cursor: pointer;
}

.itemTitle {
  color: rebeccapurple;
  margin: 0;
  padding: 0.8rem 0;
  border-top: 1px solid lightgray;
}
/*Item.js*/
import React from "react";
import { Image } from "cloudinary-react";
import { cloudName } from "../../settings";
import styles from "./Item.module.css";

const Item = props => {
  return (
    <div className={styles.itemCard}>
      <Image
        cloudName={cloudName}
        publicId={props.id}
        width="200"
        crop="scale"
      />
      <h3 className={styles.itemTitle}>
        {props.title}
      </h3>
    </div>
  );
};

export default Item;
npm install node-sass --save
/*Item.module.scss*/
.itemCard {
  width: 220px;
  padding: 5px;
  box-shadow: 0 1px 2px rgba(0,0,0,.2);
  border: 1px solid lightgray;

  &:hover {
    background-color: #d3d3d363;
    cursor: pointer;
  }
}

.itemTitle {
  color: rebeccapurple;
  margin: 0;
  padding: 0.8rem 0;
  border-top: 1px solid lightgray;
}
/* Item.js */
import React from "react";
import { Image } from "cloudinary-react";
import { cloudName } from "../../settings";
import styles from "./Item.module.scss";

const Item = props => {
  return (
    <div 
        className={props.isGrid 
            ? styles.itemCard 
            : styles.itemRow}>
      <Image
        cloudName={cloudName}
        publicId={props.id}
        width={props.isGrid ? "200" : ""}
        height={props.isGrid ? "" : "60"}
        crop="scale"
      />
      <h3 className={styles.itemTitle}>
        {props.title}
      </h3>
    </div>
  );
};

export default Item;
/* Item.module.scss */
.item{
  border: 1px solid lightgray;
  padding: 5px;

  &:hover {
    background-color: #d3d3d363;
    cursor: pointer;
  }
}

.itemCard {
  composes: item;
  width: 220px;
  box-shadow: 0 1px 2px rgba(0,0,0,.2);
}

.itemRow {
  composes: item;
  min-height: 60px;
  display: flex;

  .itemTitle {
    border:none;
    font-size: 18px;
    margin-left: 10px;
    line-height: 2;
  }
}








/* .css */
.container {...}

/* will be mapped to */

<div 
    class="elements__Container-l1fwko0zmfBG">
    ...
</div>

Random class generator

BUT

CSS in JS

not really

It's still

NOT Full extendable CSS in global scope

NO EASY way for theming

NAMING (not name collisions)

THE CSS-in-JS

The challenge

<Item/>

List-view

Grid-view

/* Item.css */
.item{
  border: 1px solid lightgray;
  padding: 5px;

  &:hover {
    /* Hover styles */
  }
}

.itemCard {
  composes: item;
  margin-right:10px;
  margin-bottom: 10px;
  width: 220px;
  box-shadow: 0 1px 2px rgba(0,0,0,.2);
}

.itemRow {
  composes: item;
  min-height: 60px;
  display: flex;

  .itemTitle {
    border:none;
    font-size: 18px;
    margin-left: 10px;
    line-height: 2;
  }
}
/* Item.js */
import styled, {css} from "styled-components";

const rowStyle = css`
    /* styles for row view */
`;

const cardStyle = css`
    /* styles for card view */
`;

const ItemContainer = styled.div`
    /* default styles*/
    
    ${props => props.isGrid 
             ? rowStyle : cardStyle}
`;

const Item = props => {
  return (
    <ItemContainer isGrid={props.isGrid}>
      <Image
        /*...*/
      />
      <ItemTitle>{props.title}</ItemTitle>
    </ItemContainer>
  );
};
/* Item.js */
import styled, {css} from "styled-components";

const rowStyle = css`
    /* styles for row view */
`;

const cardStyle = css`
    /* styles for card view */
`;

const ItemContainer = styled.div`
    /* default styles*/
    
    ${props => props.isGrid 
            ? rowStyle : cardStyle}
`;

const Item = props => {
  return (
    <ItemContainer isGrid={props.isGrid}>
      <Image
        /*...*/
      />
      <ItemTitle>{props.title}</ItemTitle>
    </ItemContainer>
  );
};
/* Item.js */
import styled from "@emotion/styled";

const ItemContainer = styled.div(
  `
  /* default styles */
`,
  props =>
    props.isGrid
      ? {
          /* card styles */
        }
      : {
          /* row styles */
        }
);

const Item = props => {
  return (
    <ItemContainer isGrid={props.isGrid}>
      <Image
        /*...*/
      />
      <ItemTitle>{props.title}</ItemTitle>
    </ItemContainer>
  );
};

The GOOD

Easy to theme

NO Dead code

Extendable

Super scoped

/* Item.js */
import styled from "styled-components";

const Item = props => {
  return (
    <ItemContainer isGrid={props.isGrid}>
      <Image
        /*...*/
      />
      <ItemTitle>{props.title}</ItemTitle>
    </ItemContainer>
  );
};

const ExtendedItem = styled(Item)`
    /* extended styled*/
`

Themes

NO more CSS file!

It's awesome!

Or is it really ? 😏

The NOT so good (and ugly)

Fragmentation

Stylex coming soon... (better & faster)

Box

/* Box.js */

import React from "react";
import styled from "@emotion/styled";

const StyledBox = styled.div(props => ({
  width: `${props.size}px`,
  height: `${props.size}px`,
  background: "grey",
  marginLeft: "auto",
  marginRight: "auto",
  marginTop: "10px"
}));

const Box = props => <StyledBox {...props} />;

export default Box;

Input size of box

Interactive Comp

😱

JS

CSS

Parse CSS

Inject to Stylesheet

stylesheet.insertRule

Browser

HTML Paint

load

 😮 Accessibility?

NO Cache

download

How about

Scaling & Sharing ?

Scaling & Sharing ?

CSS

JS

CSS

Dev

Des

Des

Scaling & Sharing ?

CoolJS

CSS

🤯

How about

Re-render problem?

Re-render problem

/*index.js*/

import { ThemeProvider } from "emotion-theming";

function App() {
  const [theme, changeTheme] = useState({
    color: "rebeccapurple"
  });

  return (
    <StyledApp>
      <h1>The Pokemons</h1>
      <select
        defaultValue={theme.color}
        onChange={e => changeTheme({ 
            color: e.target.value
          })}
      >
        <option value="orange">Orange</option>
        <option value="lime">Lime</option>
        <option value="pink">Pink</option>
        <option value="yellow">Yellow</option>
        <option value="rebeccapurple">Purple</option>
      </select>
      <ThemeProvider theme={theme}>
        <StyledLayout />
      </ThemeProvider>
    </StyledApp>
  );
}
/*Item.js*/
const ItemTitle = styled.h3`
  color: ${props => props.theme.color};
  //...
`;

How about

Security?

Security?

CSS-in-JS means

It's still CSS! (not JS)

Learning CSS is still required! 😆

Should we use CSS-in-JS?

Yes, but with caution

So

Easy to theme

NO Dead code

Nested class

Scoped

Extra re-render

Styles on run time

Security

Portability

One standard?

Context switch

Messy code

CSS-in-JS

The Good

The Bad

The Ugly

Themeable

One standard

Portable

No scope

Non deterministic

Bundle size

Dead code (somewhere)

Naming

Private to JS code

Re-usable?

Load once

No re-render

CSS-in-CSS

The Good

The Bad

The Ugly

React Native

"Use the right tool for the right job"

And naming is not a good enough reason...

CSS-in-JS

CSS

When?

React Native App

CSS modules

CSS consistency between projects

Same technology (React) for all projects

Simple and isolated component

Full control over component styling

Theme is critical (IE included)

Support dynamic styling via props

Complex and large apps

Medium size apps / third-party libs

Security is a concern

IE 11 is not a concern

Basic scope

NO dynamic styling via props

CSS/SCSS (global)

Styled component (component)

My choice

BEM (naming)

Resources

Thank you

CSS in JS - the good, the bad and the ugly

By Maya Shavin

CSS in JS - the good, the bad and the ugly

The rise of modern JS frameworks brought in more efficient concept of Front End programming. These inspired new approaches, such as CSS Module and CSS-in-JS, more scoped in working with CSS. It’s always a debate which is the best practice among these approaches. Some claimed CSS-in-JS eliminates developer’s most fear when dealing with CSS (the CSS file) with more dynamic approach. Some disagreed. If you are keen to know about CSS-in-JS and what should be considered when it comes to work with CSS, this talk is for you.

  • 772
Loading comments...

More from Maya Shavin