Fixing CSS

Aleksey Kulikov

  • I'm from Russia, Perm
  • I live in Ljubljana since Jan 2015
  • I like travel and hiking
  • I have a wife and son
  • I write web applications since 2009.
  • I contributed to many open source projects like rails and component
  • I bootstrapped Gingko App, than sold my part and relocated to Ljubljana
  • I was first employee of butterfly.ai (now we are 19 people team around the world and keep growing)

Technical skills survey

  • Who knows how to build websites?
  • Who is comfortable writing css + html + js?
  • Who has a project with more than 1000 lines of CSS?
  • Who is familiar with css preprocessors, like postcss or saas?
  • Who knows ES6 and babel?
  • Who heard about CSS-in-JS libraries?

Plan

  1. Problems with CSS
  2. How to write modern CSS without JS
  3. Existing CSS-in-JS solutions
  4. Ideal approach to define styles in web

Part 1.

The problem

Documents vs Web Apps

  • CSS was designed for web documents:
    • separate HTML + CSS and JS files
    • stateless communication by URL
  • Now we create web applications using components
    • rich, interactive UX
    • complex client-side logic and routing

Different separation of concerns

Scale

  • one developer & one page - css is perfect

  • many developers & 100s of components - css sucks

Why CSS does not scale for web apps?

Everything is global

  • global variables are bad
  • hard to reuse external libraries
    • new external library -> bunch of global variables
    • for example bootstrap.css -> 600 globals
  • no isolation, easy to rewrite rule

Unspecified dependencies

  • not clear how different parts of application are connected
  • hard to refactor and delete legacy code

Part 2.

CSS still works

With good naming convention CSS works pretty well

On a medium "scale"

  • 6 developers team
  • 9270 lines of CSS and 0 !important

  • 0 issues with CSS during 1.5 year

1. BEM naming convention

2. CSS Preprocessor: PostCSS + CSSNext

  • Future CSS syntax like variables & nesting
  • Autoprefixer
  • Performant and extensible

3. Flexbox

4. normalize.css

  • solid foundation for all components
  • no need for frameworks
  • css is really expressive language

5. No DRY

6. Stylelint

* but:

  • no connection with JS code
  • hard to start and requires review for new developers
  • a lot of repetition when refer on classes
  • hard to setup rules validation on existing code base
  • easy to break

*

Part 3.

CSS-in-JS

Beginning of CSS-in-JS

Christopher "vjeux" Chedeau
https://speakerdeck.com/vjeux/react-css-in-js

Facebook level of Scale

Problem with inline styles

  • it's only subset of CSS
    • no @media queries
    • no pseudo-selectors, like :hover or :visited
    • no css tools, like autoperfixer
    • no custom fonts

Experimentation begins

  • inline styles that work
  • easy to add to existing project, because every rule marked as !important
  • problems: client-side processing, 20kb size, odd syntax for native css features
  • works similar to <style scoped> or vue.js
  • full CSS support
  • minimal and performant
  • problems: jsx (react) only, no nesting and custom CSS syntax
  • use ES6 template literal to define styles
  • components instead of classes and tags
  • dynamic properties
  • problems: react only, slow (at least v1), not necessary abstraction on html tags
  • atomic css
  • critical rendering path optimization
  • high-performance
  • problems: low-level, object syntax for css declarations

Different approaches and no silver bullet

Part 4.

Ideal approach

A bit of theory

  • CSS rule: selector + declaration(s)
  • Declaration: key + value

key+value is fine

  • no one says we need better background property
  • concept of declarations is simple and robust
  • many css guides focus mostly on it, leaving selector part up to developers

Selectors == Cascade

Cascade is broken

  • Who can explain how cascade works?
  • CSS selectors may be a good idea to traverse DOM (jquery), but not for styling.
  • > (parent selector), may be the only one adequate selector, which brings the glory of old days CSS to modern web apps.

<link rel=”stylesheet” href=”file.css” >

== Sheet

  • it loads text file with rules (it's hard to use this concept in components world)
  • it blocks render
  • for apps with client-side routing, this is not an option

How ideal styles library should look like?

  • supports all CSS features and keeps flexibility and power of the language
  • has 0 size and minimal initialisation overhead
  • injects only actually used styles
  • eliminates concept of selector
  • scales in teams with different experience (not css gurus)
  • connects with JS world (similar to jsx)

That's it!

but... one more thing

injected - to introduce something new that is necessary or helpful to a situation or process

Usage

Install the package:

 

npm install injected-css

 

Add "injected-css/babel" to plugins section

in your babel config:

 

                                     {
                                         "plugins": [
                                             "injected-css/babel"
                                         ]
                                     }

Main features

matches "ideal" points

  • Write real CSS (copy-paste from stack-overflow)
  • Use powerful tools of JS world
    • ES modules to manage dependencies between styles and JS components
    • Eslint to ensure, it's hard to write bad CSS
    • Variables and functions
    • Webpack 2, Hot Module Replacement, code splitting, and server side render
  • Overhead is minimal - 300 byte runtime (think about inject function as styles version of require)

Demo

Path to v1.0

  • implement eslint plugin
  • server side rendering
  • support BEM's __
  • feedback from community
  • experiments: atomic classes and development hints

 

 

https://github.com/alekseykulikov/injected-css/issues/1

Recap

  • Embrace the change

  • Experiments are still in progress, we're not figure out yet

  • Participate and share

  • Star and watch injected-css

Thank you!

Fixing CSS

By Aleksey Kulikov

Fixing CSS

Slovenia CSS User Group

  • 2,036