On Github Huxpro / css-sucks-2015
export default () => ( <Huxpro zh='黄玄' en='Hux'> <Wepiao> Frontend Infrastructure Team @2015 </Wepiao> <Taobao> Alibaba Trip Mobile Team @2014 </Taobao> </Huxpro> )
HTML is born for document in 1993
层叠样式表
### <em class="b" id="g">Priority</em> & *Inheritance*
h3 { color: white; font-size: 1.3em; } em { color: #ffef99; font-style: italic; } .b { color: blue; } #g { color: gold; }
we are good at cascading!
thinking globally makes sense
Bootstrap and Foundation
(Nicole Sullivan 2008)
Separate structure and skin Reuse visual feature as skins (mixable) Structural semantics are provided by structural classes Reference classes instead of HTML tags. (flexible HTML)
Separate container and content Rarely use location-dependent styles Classes over tags, avoid the descendent selector An object should look the same no matter where you put it.
The Media Object Saves Hundreds Of Lines Of Code →
(Nicole Sullivan 2010)
<div class="media"> <a href="#" class="img"> <img src="myAvatar.jpg" alt="huxpro" /> </a> <div class="bd"> <a href="#">@huxpro</a> <span class="detail">14 miniutes ago</span> </div> </div>
Fighting with number of words...
What is meant by an “object” in OOCSS? →
A common case you may be familier with
<div class="mod"> <div class="inner"> <div class="hd">Block Head</div> <div class="bd">Block Body</div> <div class="ft">Block Foot</div> </div> </div>
"Each CSS class is not necessarily an object in its own right, but can be a property of a wrapper class."
Reusable, Portable, Not Easy...
"CSS Zen Garden proved that we can alter a design into a myriad of permutations simply by changing the CSS. However, we’ve rarely seen the flip side of this — the side that is more likely to occur in a project: the HTML changes. We modify the HTML and then have to go back and revise any CSS that goes with it."
(Jonathan Snook 2012)
Sharing similar idea with OOCSS Well, It is really a long style guide
You can't imagine how early they first appeared!
(Since Sep 2013)
Everyone should hear about
Yes, one of the most famousPostCSS Plugins!
Well, OfficiallyPostCSS is Not a Post-processor
It is time admit my mistakes. “Postprocessor” term was bad. PostCSS team stoped to use it.
— PostCSS (@PostCSS) July 28, 2015
But PostCSS plugins can do ALL those cool shit...
In my view, the Babel and Webpack for CSS we will keep mentioning it...
After 22 years evolution...
单页面应用
组件样式内聚
2014.11 problems with CSS for building larger applications - NationJS @vjeux →
be future-proofing
provides encapsulation for the JavaScript, CSS, and templating in a Web Component.
Houdini: Maybe The Most Exciting Development In CSS You’ve Never Heard Of →
Well...future is still future.
when we talk about "today", what we actually mean is community...
.TheStory__ofNamingConvention--whateverYouChoose.is-kindsOfLooong{}
(2012)
First appeared in 2009 by YandexThe history of BEM methodology (from 2005) →
Parts of BEM webapp frameworkBEM official site → The original naming convention part is not clear enough →
Honed by @Nicolas as naming pattern2012.03 About HTML semantics and front-end architecture → 2012.04 A New Front-End Methodology: BEM → 2013.01 MindBEMding – getting your head round BEM syntax →
.block__element--modifier
.block{} .block__element{} .block--modifier{} .block__element--modifier{}
check getBEM.com to get started
Let's draw a BEMed Button!drawing button is the "hello world" of a styling tool
.slds-button{} /*block*/ .slds-button--inverse{} /*inverse modifier*/ .slds-button__icon{} /*icon element in block*/ .slds-button__icon--left{} /*icon element in the left*/ .slds-button__icon--right{} /*icon element in the right*/
<button class="slds-button">normal</button> <button class="slds-button slds-button--inverse">inverse</button> <button class="slds-button">button with a right icon <svg class="slds-button__icon slds-button__icon--right"></svg> </button>
Uuuugly? This is a real-world example Button - "Salesforce design system" → Building an Enterprice CSS Framework →
BEM provide "scope"2012.02 Scope CSS classes with prefixes (from chained classes) → 2013.05 ‘Scope’ in CSS (from Nesting to BEM) →
BEM stop specificity wars2013.05 ‘Scope’ in CSS (nesting unnecessarily increase specificity) → 2015.09 Building an Enterprice CSS Framework → (the most frustrating part of CSS is — the C. Cascading)
/* Bad */ .block .element{} /* nesting */ .element.modifier{} /* chained */ /* Good */ .block__element{} .element--modifier{}Why not use element type selectors with child or sibling combinators (like ul > li + li) to avoid inheritance issues?
Get loose coupled CSS from HTML! Remember OOCSS? →
.block{ .element{ &.modifier{ color: red; } } .modifier{ color: blue; } } // Generates .block .element.modifier{ color: red; } .block .modifier{ color: blue; } // hmm...what's the color when you use .modifier?
Sass 3.3 supports BEM officially! - Sass Blog
[2014.03] "With the rise in popularity of BEM, OOCSS, and SMACSS, people became more and more interested in adding suffixes to classes.".block{ &__element{ &--modifier{ color: red; } } &--modifier{ color: blue; } } // Generates .block__element--modifier{ color: red; } .block--modifier{ color: blue; }
I want to highlight this person:
About HTML semantics and front-end architecture →
[Youtube] Adaptation and Components → In this video, he introduce us...
(2014)
One of BEM variant, thinking in componentsSUIT CSS naming conventions → PascalCase, camelCase, Utilities and StateOfComponent
CSS preprocessor (based on PostCSS) Leverage Future CSS and Modern toolchain: autoprefixer/import/custom-properties/calc/custom-media Encapsulation testing based on postcss-bem-linter
The Plain Way (metaCSS):
<div class="fwb tar bd1"></div> <div class="m-5 mt-10"></div>
Yahoo! Atomizer:
<div> <div class="Bgc(#0280ae.5) H(90px) IbBox W(50%) foo_W(100%)"></div> <div class="Bgc(#0280ae) H(90px) IbBox W(50%) foo_W(100%)"></div> </div>
God...
(Thierry 2013)
Classes related to presentation instead of content WAT!? It's non-semantics and a anti-pattern → "Reinventing Inline CSS!" Well, I hold similar POV (1)(2) in the most beginning
Better inline styling with classes Lower specificity of classes Pseudo-classes or pseudo-elements support Portable, reusable (like OOCSS) Better caching and compression!
Borrows many of pros from inline styles Stop specificity wars Pure Presentational classes lead to=> Few content-derived class or context-based selector => Work around the global namespace and scope issues.
Classes is static analysable Dead code elimination possible Classnames uglification/minification possible Perfect compile-target (react-native-web/styleSheet API)
I should recall 'Atomic CSS is wrong' → separate the whole concept into two parts makes things clearThe End Result vs "Authoring Time"
WAT?
Story back to crazy facebook
2014.11 React: CSS in JS @vjeux →This talk is INSANE and you had better go through it yourself
This idea just erupted!
2015.07 [Youtube][ReactEurope] Michael Chan -Inline Styles: themes, media queries, contexts, & when it's best to use CSS →The BEST talk I watched about inline styles
2015.04 SEEK UI Engineering - Block, Element, Modifying Your JavaScript Components →
Remember "SEEK UI Engineering", you will know...
Bunch of CSS in JS Libs for React...
Quick Look
Problem solved!
2014.11 React: CSS in JS @vjeux →And supporters hold that React Native use it
and learn javascript listen some negative voice...
Overengineered, Unstable... Learning Curve & Migration Costs
It's great. But maybe you like
to write css in .css file
Post by "SEEK UI Engineering"!
Let's draw some buttons!
/* components/submit-button.css */ .Button { /* all styles for Normal */ } .Button--disabled { /* overrides for Disabled */ } .Button--error { /* overrides for Error */ } .Button--in-progress { /* overrides for In Progress */
Before CSS Modules
/* components/submit-button.css */ .normal { /* all styles for Normal */ } .disabled { /* all styles for Disabled */ } .error { /* all styles for Error */ } .inProgress { /* all styles for In Progress */
With CSS Modules
Time for JavaScript
/* components/submit-button.js */ import styles from './submit-button.css'; buttonElem.outerHTML = ` <button class=${styles.normal}>Submit</button> `
↓ time for magic
<button class="components_submit_button__normal__abc5436"> Processing... </button>
BLOOOOOOOM! Did you see the classnames? It's HASHED!
shared styles between all the states
/* BEM Style */ innerHTML = `<button class="Button Button--in-progress">` /* CSS Modules */ innerHTML = `<button class="${styles.inProgress}">`
each class should contain all the styles
.common { /* all the common styles you want */ } .inProgress { composes: common; /* similar to Sass @extend */ /* anything that only applies to In Progress */ }
CSS Modules changes which classes are exported to JavaScript.
Under the hood
.common { /* font-sizes, padding, border-radius */ } .normal { composes: common; /* blue color, light blue background */ } .error { composes: common; /* red color, light red background */ }
.components_submit_button__common__abc5436 { /* font-sizes, padding, border-radius */ } .components_submit_button__normal__def6547 { /* blue color, light blue background */ } .components_submit_button__error__1638bcd { /* red color, light red background */ }
In your JS code, import styles from "./submit-button.css" returns:
styles: { common: "components_submit_button__common__abc5436", normal: "components_submit_button__common__abc5436 components_submit_button__normal__def6547", error: "components_submit_button__common__abc5436 components_submit_button__error__1638bcd" }
that's how we get multiple class rendered into the DOM.
@import or require dependencies
/* colors.css */ .primary { color: #720; } .secondary { color: #777; } /* other helper classes... */
/* submit-button.css */ .common { /* font-sizes, padding, border-radius */ } .normal { composes: common; composes: primary from "../shared/colors.css"; }
Influencer: Smarter CSS(SCSS) builds with Webpack
@mixin also has a replacement
.element { composes: large from "./typography.css"; composes: dark-text from "./colors.css"; composes: padding-all-medium from "./layout.css"; composes: subtle-shadow from "./effect.css"; }
/* this short hand: */ .element { composes: padding-large margin-small from "./layout.css"; } /* is equivalent to: */ .element { composes: padding-large from "./layout.css"; composes: margin-small from "./layout.css"; }
wanna listen some low-level stories?
Local Scope changed everything new feature landed in webpack css-loader
require('./MyComponent.css'); // becomes... import styles from './MyComponent.css';
:local(.header) { ... } :local(.footer) { ... } // becomes... /* Globally unique classes */ ._1rJwx92-gmbvaLiDdzgXiJ { ... } ._ah6Hch-gjsAdSE53CxzaEs { ... }
NO MORE NAMING COLLISIONS!
Classname Mapping
// Styles object: { 'header': '_1rJwx92-gmbvaLiDdzgXiJ', 'footer': '_ah6Hch-gjsAdSE53CxzaEs' }
import styles from './MyComponent.css'; export default () => ( <div> <div className={styles.header}>...</div> <div className={styles.footer}>...</div> </div> );
and only global class need :global()
[Youtube] 2015.10 CSSconf EU 2015 | Glen Maddern: Interoperable CSS → github repos →
hmm...seems perfect...
there is still something trouble...
You can never override classes from another file Import className from fileName #40 → Damn easy to override a class in old css by using selectors (.scope .be-overrode{}) With CSS Modules, a css file can never know the actual classname another css file
This is a half way between CSS and CSS-in-JS Every style need to be set in .JS file, and some stuff can be only done in JS, Which means all your CSS is highly coupled with your JS There is still a expensive migration costs for old projects. There is still a learning curve especially for HTML/CSS-only Engineers
Future of CSS? Or a present compromise.Until ICSS is officially inclued into CSS spec
It just force you thinking everthing in JavaScript and Components
"Anyway, this all is the cost of the encapsulation. Which is harder, but absolutely better." - #40
But, what if there are HTML/CSS Engineers in the team? It's very common. for example your designer can do CSS?
I searched Linkedin
PSD-to-HTML + SCSS + RWD + Gitpretty nice!
Im confusing! where does this naming come from?
What the hell is this translating...
There are possibilities in PostCSS community I believed
CSS Next Use tomorrow's CSS syntax, today.one of the 'Future CSS' postCSS plugins
PostCSS Auto Reset one of the 'End of Global CSS' postCSS plugins
Scoped CSS in Vue-loader one of the BEST idea I have seen to solve the global cssclever attribute selector
At your own risk to use in production...
You ask me
it’s not like one approach is de facto better than the other as this would depend on which factors are to be taken into consideration. @Thierry
Small and full-stack team CSS Modules/Inline CSS/Atomic CSS...Go pick your favourite one! They are all extremely engineering way, but solve problem perfectly Everyone in your team had better to know modern JavaScript (and webpack) well
Big and tranditional team Pick a Naming Convention (BEM/SUIT/ECSS etc) or make your own. Especially there is HTML/CSS engineers in your team, let them do what they do best
Hey Im working on websites, not apps Just keep your old way if it is satisfied! Those stuff may well are over-engineered to your product!
A pragmatic naming proposal used in my team
for component-based multi-entries SPA
In multi-entries SPA
// Component/index.scss .ComponentName { &__decendentName { &--modifierName {} } .isStateOfComponent {} }
// Component/index.js require('./index.scss');
CSS is always bundled with components(from loading, mount to unmount)
2015.05 Smarter CSS(SCSS) builds with Webpack → 2015.04 Block, Element, Modifying Your JavaScript Components →
// Pages/PageA.scss #PageA { .pagelet-name { .pagelet-descendent-name {} } .ComponentName{ /* override */ } }
// Pages/index.js require('./PageA.scss');
It's technology-agnostic One css framework can be played with whatever technology stacksYou can combined Scss, PostCSS and whatever you want
Solving problems, and easy Makes reading and teamwork much easierGet all benefit from BEM, SUITCSS and others
Leverage the power of cascading properly Scoping components but allow reasonable overridingIt's pragmatic, flexible and hitting the sweet spot
Hey, don't be shy.