当前位置:威尼斯 > Web前端 > 禁止转载,这里的翻译都是根据我自己的理解进

禁止转载,这里的翻译都是根据我自己的理解进

文章作者:Web前端 上传时间:2019-11-08

不要再在 JavaScript 中写 CSS 了

2017/06/28 · CSS · CSS, Javascript

本文由 伯乐在线 - 古鲁伊 翻译。未经许可,禁止转载!
英文出处:Gajus Kuizinas。欢迎加入翻译组。

本文作者是 react-css-modules 和 babel-plugin-react-css-modules 的作者。并不是对 CSS in JavaScript: The future of component-based styling,或是使用样式组件的反对,而是一种补充,web 开发者要了解自己的需求,明白自己使用 styled-components 的真正原因。

前言

这是Glen Maddern发布于2015年8月19日的一篇文章,主要是之前翻译的文章《理解CSS模块方法》里提到这篇文章,现在算是顺藤摸瓜跟进来看看。

这里的翻译都是根据我自己的理解进行的,所以不是一句一句的来的,有哪些不对的也在所难免,水平有限,希望大家指出。

不要再在 JavaScript 中用 CSS了

正文

如果想在最近CSS开发思想上找到一个转变点,最好去找Christopher Chedeau 2014年11月在NationJS上发表的“css in js”演讲。这是一个分界线,各种不同的思想,就像高速粒子似的在自己的方向上快速发展。例如:在React及一些依赖React的项目中写样式, React Style,jsxstyle威尼斯,和Radium是其中三个,最新的,最巧妙的,和最可行的方法。如果发明是在一种探索的情况下相邻的可能(adjacent possible),那么christopher是创造了很多接近相邻(adjacent)可能性。

威尼斯 1

这些问题,以不同的形式存在于大的CSS代码库中。christopher指出,这些问题都可能通过在js中写代码来解决。但这种解决方案引入了其自身的复杂性和特性。只要看一下,在之前提到的项目中(React Style,jsxstyle和Radium),处理在:hover状态下range的方法。这个问题,在浏览器端css中已经早被解决了。

CSS Modules team找到问题的关键--保持和CSS一致,使用styles-in-js的方式编写。虽然我们还是坚持看好使用了CSS的形式,但还有要感谢对我们提供很多建议的朋友。

我们一直在绞尽脑汁地思考CSS,怎样去编写更好。

9 个谎言

CSS 不应随意放置。许多项目选择将样式写在 JavaScript 中的理由不对。本文列出了常见的误解,以及解决问题的现存 CSS 方案。

本文的任何言论都没有对某个项目或人进行人身攻击的意思。styled-components 是 React 的目前趋势,所以我将 styled-components 定义为“JavaScript 中的 CSS”。

styled-components 的发起人(Max Stoiber、Glen Maddern 以及所有的贡献者)都很聪明、想法独特,出发点也是好的。

为了完全透明,我还要指出我是 react-css-modules 和 babel-plugin-react-css-modules 的作者。

威尼斯 2

小红帽

第1步:默认局部作用域

在css模块中,每一个文件都是独立编译的,因此你可以使用一些CSS短命名-不用担心命名冲突。下面看一下,提交按钮的4种状态的例

威尼斯 3

CSS 和 JavaScript 历史

层叠样式表(CSS)是为描述标记语言文档的展现样式而出现的。JavaScript 是为了组合图片、插件等组件而创造的一种“胶水语言”。随着发展,JavaScript 拓展、转变,有了新的应用场景。

Ajax 的出现(2005)是一个重要的里程碑。这时 Prototype、jQuery、MooTools 等库已经吸引了大量的拥护者,共同解决后台跨浏览器数据获取问题。这又引发了新的问题:如何管理数据?

到了 2010 年,Backbone.js 出现,成为了应用状态管理的行业标准。不久后,Knockout 和 Angular 双向绑定的特点吸引了所有人。之后,React 和 Flux 出现,开启了单页应用(SPA)的新纪元,组件构造应用。

常规的CSS书写方法

用Suit或BEM命名、一些CSS样式、一段html。代码如下:

css代码段:

/* 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 */

html代码段:

<button class="Button Button--in-progress">Processing...</button>

上面代码运行不错,我们有4种状态的类名,BEM命名,避免了使用嵌套选择器。使用大写字母开头的单词Button作为选择器,避免与之前或引用样式的类名冲突。并且我们使用--modifier语法来消除基础样式。

到现在为止,这都是一段不错的可维护的代码。但也引入了严格的命名规范。但这也是能用标准CSS,做到的最好的方式了。

那么 CSS 呢?

借用 styled-components 文档中的话:

纯 CSS 的问题在于它产生的那个时代,网站由文档组成。1993 年,网站产生,主要用于交换科学文献,CSS 是设计文献样式的解决方案。但是如今我们构建的是丰富的、面向用户的交互应用,而 CSS 并不是为此而生的。

我不这么认为 。

CSS 已经发展到可以满足现代 UI 的需求了。过去十年中出现的新特性数不胜数(pseudo-classes、pseudo-elements、CSS variables、media queries、keyframes、combinators、columns、flex、grid、computed values 等等)。

从 UI 的角度看,“组件”是文档中一个独立的片段(<button /> 就是个组件)。CSS 被设计用来样式化文档,包括所有组件。问题在哪?

俗话说:“工欲善其事必先利其器”。

CSS模块书写方法

使用CSS模块,你不用担心使用一些短命名了。可以像下面这样。

/* 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 */

看,你不用在任何地方再去加长长的前缀。为什么可以这样做,我们可以像其它语言一样,不用在本地变量前加长长的前缀,只要把CSS对应的文件名改成submit-botton.css

这可以让在JS中使用requireimport加载的CSS模块文件,可以被编译出来。

/* components/submit-button.js */

import styles from './submit-button.css';

buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

真正在页面使用的样式名,是动态生成的唯一标识。CSS模块把文件编译成ICSS格式的文件,这种格式文件可以方便CSS和JS进行通信。当你运行程序,会得到类似下面的代码

<button class="components_submit_button__normal__abc5436"> Processing...</button>

得到类似结果,说明运行成功~

Styled-components

styled-components 可以用标记模板字面量在 JavaScript 中写 CSS。这样就省去了组件和样式间的匹配 ——组件由细粒度的样式结构组成,比如:

import React from 'react'; import styled from 'styled-components'; // Create a <Title> react component that renders an <h1> which is // centered, palevioletred and sized at 1.5em const Title = styled.h1` font-size: 1.5em; text-align: center; color: palevioletred; `; // Create a <Wrapper> react component that renders a <section> with // some padding and a papayawhip background const Wrapper = styled.section` padding: 4em; background: papayawhip; `; // Use them like any other React component – except they're styled! <Wrapper> <Title>Hello World, this is my first styled component!</Title> </Wrapper>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from 'react';
import styled from 'styled-components';
// Create a <Title> react component that renders an <h1> which is
// centered, palevioletred and sized at 1.5em
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;
// Create a <Wrapper> react component that renders a <section> with
// some padding and a papayawhip background
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;
// Use them like any other React component – except they're styled!
<Wrapper>
  <Title>Hello World, this is my first styled component!</Title>
</Wrapper>

结果:

威尼斯 4

Live demo

styled-components 目前是 React 的 趋势 。

我们要理清一件事情:styled-components 只是 CSS 层面的高度抽象。它只是解析定义在 JavaScript 中的 CSS,然后生成对应 CSS 的 JSX 元素。

我不喜欢这个趋势,因为存在很多误解。

我在 IRC、Reddit 和 Discord 上调查了大家使用 styled-components 的原因,整理了一份选择使用 styled-components 常见原因的列表 。我称之为 myths。

Myth #1:避免全局命名空间和样式冲突

我把这条算作 myth 是因为它听起来就像之前这些问题没有得到解决一样。CSS Modules、Shadow DOM 还有很多命名协议(比如 BEM)已经早就在社区中解决了这个问题。

styled-components(就像 CSS modules)只是替人完成了命名的任务。人总会犯错,计算机犯错少点而已。

但就本身而言,这并不是使用 styled-components 的好理由。

Myth 2:styled-components 可以简明代码

通常伴随着如下的例子:

<TicketName></TicketName> <div className={styles.ticketName}></div>

1
2
<TicketName></TicketName>
<div className={styles.ticketName}></div>

首先——关系不大。差异基本可以忽略。

其次,说的也不对。字符数量取决于样式命名。

<TinyBitLongerStyleName></TinyBitLongerStyleName> <div className={styles.longerStyleName}></div>

1
2
<TinyBitLongerStyleName></TinyBitLongerStyleName>
<div className={styles.longerStyleName}></div>

这同样适用于本文之后的构造样式(Myth 5:给组件设置条件样式更简单)。styled-components 只是在多数基本组件的情况下稍胜一筹。

Myth 3:styled-components 使人更关注语义化

前提就不对。样式和语义化代表着不同的问题,需要不用的应对方案。引用 Adam Morse(mrmrs)的话:

内容语义化和视觉样式 没有半点关系。当我用乐高建造东西时,我从来不会想“这是引擎的一部分”,我想着“这是个 1×4 的蓝色乐高,我用来随便做什么都行”。不论水下潜水基地还是飞机——我清晰地知道怎么用这个乐高块。

(强烈建议读一读 Adam 关于 可拓展 CSS 的文章)

我们还可以举个例子看看两者是否相关。

示例:

<PersonList> <PersonListItem> <PersonFirstName>Foo</PersonFirstName> <PersonLastName>Bar</PersonLastName> </PersonListItem> </PersonList>

1
2
3
4
5
6
<PersonList>
  <PersonListItem>
    <PersonFirstName>Foo</PersonFirstName>
    <PersonLastName>Bar</PersonLastName>
  </PersonListItem>
</PersonList>

语义化是要使用正确的标签构造标记。你能知道这些组件会渲染成什么 HTML 标签吗?不,你不知道。

和下面这段代码比较下:

<ol> <li> <span className={styles.firstName}>Foo</span> <span className={styles.lastName}>Bar</span> </li> </ol>

1
2
3
4
5
6
<ol>
  <li>
    <span className={styles.firstName}>Foo</span>
    <span className={styles.lastName}>Bar</span>
  </li>
</ol>

Myth 4:拓展样式更容易

v1 版本可以用 styled(StyledComponent) 拓展样式;v2 引进了 extend 方法来拓展已存在的样式,比如:

const Button = styled.button` padding: 10px; `; const TomatoButton = Button.extend` color: #f00; `;

1
2
3
4
5
6
const Button = styled.button`
  padding: 10px;
`;
const TomatoButton = Button.extend`
  color: #f00;
`;

这挺好。但是你可以在 CSS 中完成(或者使用 CSS 模块组合 或 SASS 继承混合 @extend)。

button { padding: 10px; } button.tomato-button { color: #f00; }

1
2
3
4
5
6
button {
  padding: 10px;
}
button.tomato-button {
  color: #f00;
}

难道不比 JavaScript 简单?

Myth 5:给组件设置条件样式更简单

这点是说你可以根据组件属性给组件设置样式,比如:

<Button primary /> <Button secondary /> <Button primary active={true} />

1
2
3
<Button primary />
<Button secondary />
<Button primary active={true} />

这在 React 中很有用。毕竟组件行为就是由属性控制的。给属性值直接绑定样式有意义吗?可能吧。但是来看看组件的实现代码:

styled.Button` background: ${props => props.primary ? '#f00' : props.secondary ? '#0f0' : '#00f'}; color: ${props => props.primary ? '#fff' : props.secondary ? '#fff' : '#000'}; opacity: ${props => props.active ? 1 : 0}; `;

1
2
3
4
5
styled.Button`
  background: ${props => props.primary ? '#f00' : props.secondary ? '#0f0' : '#00f'};
  color: ${props => props.primary ? '#fff' : props.secondary ? '#fff' : '#000'};
  opacity: ${props => props.active ? 1 : 0};
`;

利用 JavaScript 按条件创造样式表是挺强大的,但是这也意味着样式难以理解,对比以下 CSS:

button { background: #00f; opacity: 0; color: #000; } button.primary, button.seconary { color: #fff; } button.primary { background: #f00; } button.secondary { background: #0f0; } button.active { opacity: 1; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
button {
  background: #00f;
  opacity: 0;
  color: #000;
}
button.primary,
button.seconary {
  color: #fff;
}
button.primary {
  background: #f00;
}
button.secondary {
  background: #0f0;
}
button.active {
  opacity: 1;
}

这样 CSS 更简短(229 VS 222 字符),(个人认为)也更容易理解。此外,还可以用预处理器使 CSS 分组、更短:

button { background: #00f; opacity: 0; color: #000; &.primary, &.seconary { color: #fff; } &.primary { background: #f00; } &.secondary { background: #0f0; } &.active { opacity: 1; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
button {
  background: #00f;
  opacity: 0;
  color: #000;
  
  &.primary,
  &.seconary {
    color: #fff;
  }
  &.primary {
    background: #f00;
  }
  &.secondary {
    background: #0f0;
  }
  &.active {
    opacity: 1;
  }
}

Myth 6:有利于代码组织

有些人告诉我他们喜欢 styled-components,因为它可以让样式和 JavaScript 在一个文件中。

我理解同一组件有许多文件很烦,但是把样式和标记塞进一个文件的方法很糟糕。这样不仅版本控制难以回溯,而且所有组件都需要滚动很长一段距离,而不是简单地点下按钮。

如果一定要把 CSS 和 JavaScript 放在一个文件中, 可以考虑使用 css-literal-loader。它可以在 build 时用 extract-text-webpack-plugin 提取 CSS,用标准 loader 配置处理 CSS。

Myth 7:DX 很方便,这工具太棒了!

很明显你没用过 styled-components

  • 一旦样式写错了,整个 app 会崩溃,并输出长长的调用栈错误(v2 更奇葩)。相比之下,CSS “style error” 只是元素渲染地不对而已。
  • 元素没有 className,所以调试时不得不去对比 React 元素树和 DevTools DOM 树(v2 可以用 babel-plugin-styled-components 定位)。
  • 没有语法检查(有一款 样式检查插件 正在开发中)。
  • 不合法的样式会被忽略(比如:clear: both; float left; color: #f00; 不会报 error 或 warning,只能祈祷调试好运了,即使看了 styled-components 源码,还是花了我 15 分钟查看调用栈。最后我在聊天中把代码粘出来寻求帮助,才有人提醒是少了:。你注意到了吗?)
  • 支持语法高亮、代码补全以及其它 IDE 细节的 IDE并不多。如果你在金融或政府机构工作,很可能无法使用 Atom IDE。

Myth 8:性能更好,bundle 更小

  • 事实是,styled-components 无法提取静态 CSS 文件(比如使用 )。这意味着浏览器无法开始解释样式直到 styled-components 解析、加载到 DOM上。
  • 缺少文件分离意味着无法分开缓存 CSS 和 JavaScript。
  • 所有样式化的组件都会额外包装一层 HoC。这是不必要的性能损耗。因为类似的结构缺陷,我终止了  
  • 因为 HOC,如果在服务端渲染,会导致标记文档大很多。
  • 有 keyframes, 我也不需要用动态样式值做动画。

Myth 9:它可以开发响应式组件

这说的是依据环境给组件设置样式的能力,比如父容器偏移量、子元素数量等。

首先,styled-components 和响应式没什么关系。这已经超出了这个主题的范围。这种情况最好直接设置组件的 style,以避免额外的成本。

但是,元素查询是个有趣的问题,也逐渐成为 CSS 中的一个高热话题,主要是 EQCSS 等类似项目。元素查询和 @media queries 在语法上很相似,只是元素查询操作具体某些元素。

<a href="; {selector} and {condition} [ and {condition} ]* { {css} }

1
<a href="http://www.jobbole.com/members/feiguohai46">@element</a> {selector} and {condition} [ and {condition} ]* { {css} }

{selector} 是 CSS 选择器对应着一或多个元素。例如:#id 或 .class

{condition} 由尺寸和值组成。

{css} 可以包含:任何合法的 CSS 规则。(例如:#id div { color: red }

元素查询可以用 min-widthmax-widthmin-heightmax-heightmin-charactersmax-charactersmin-childrenmax-childrenmin-linesmax-linesmin-scroll-xmax-scoll-x 等 (详见 )条件给元素设置样式。

总有一天类似 EQCSS 的内容也会出现在 CSS 标准中的(希望如此)。

命名约定

还是拿按钮的例子来说

/* 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 */

所有类名都是独立的,不是一个是基类名,其它的用来修改。在CSS模块中,所有类必须包括所有的属性和样式。这让你在JS中使用类名时有很大的不同。

/* 不要像这样 */

`class=${[styles.normal, styles['in-progress']].join(" ")}`

/* 不同之处是使用单独的类名 */

`class=${styles['in-progress']}`

/* 最好使用驼峰式 */

`class=${styles.inProgress}`

当然,如果你是按照代码量来收钱的,你可以按照你的方式继续。

等下!

大部分内容都长期有效,无论是社区、React 变更或 styled-components 本身。但意义何在?CSS 已被广泛支持,有大量的社区,也确实行之有效。

本文的目的并不是阻止读者在 JavaScript 中使用“CSS”或是 styled-componentsstyled-components 一个很棒的使用场景是:更好的跨平台支持性。不要因为错误的理由使用它。

一个React例子

这里不是关于React特有的CSS模块。但React提供了,在使用CSS模块时,特别优秀的体验。下面做一个复杂点的例子。

/* components/submit-button.jsx */

import { Component } from 'react';

import styles from './submit-button.css';

export default class SubmitButton extends Component {

render() {

let className, text = "Submit"

if (this.props.store.submissionInProgress) {

className = styles.inProgress text = "Processing..."

} else if (this.props.store.errorOccurred) {

className = styles.error

} else if (!this.props.form.valid) {

className = styles.disabled

} else {

className = styles.normal

}

return <button className={className}>{text}</button>

}

}

你可以使用你的样式,不用再担心全局冲突,让你可以专注于组件开发,而不是在写样式上。一旦离开之前的频繁在CSS,js之间切换方式,你就再也不想回去了。

但这只是开始,当你考虑样式合并时,CSS模块又没法使用了。

那么我们应该用什么呢?

使用 Shadow DOM v1 还为时尚早(51% 支持率)。CSS 应遵循命名协议(建议 BEM),如果担心类名冲突(或懒得用 BEM),可以用 CSS modules。如果你在开发 React web,考虑用 babel-plugin-react-css-modules。如果在开发 React Native,styled-components 更好。

感谢 Max Stoiber。

打赏支持我翻译更多好文章,谢谢!

打赏译者

第2步 一切皆为组件

前面提到CSS模块需要每种状态都包含所有所需的样式。

这里假设你需要多个状态,我们对比一下CSS模块和BEM命名。

/* BEM Style */

innerHTML = `<button class="Button Button--in-progress">`

/* CSS Modules */

innerHTML = `<button class="${styles.inProgress}">`

等一下,如何在所有状态共享样式呢?答案是CSS模块的最有力工具-组件

.common { /* all the common styles you want */ }

.normal { composes: common; /* anything that only applies to Normal */ }

.disabled { composes: common; /* anything that only applies to Disabled */ }

.error { composes: common; /* anything that only applies to Error */ }

.inProgress { composes: common; /* anything that only applies to In Progress */ }

关键词composes指出.normal包含.common中的样式,就像sass里的@extend关键词一样。sass是通过重写css选择器来实现的。css模块则是通过改变js中使用的类名来实现。

打赏支持我翻译更多好文章,谢谢!

任选一种支付方式

威尼斯 5 威尼斯 6

2 赞 4 收藏 评论

SASS:

使用前面的BEM例子,使用一些SASS的@extend

.Button--common { /* font-sizes, padding, border-radius */ }

.Button--normal { @extends .Button--common; /* blue color, light blue background */}

.Button--error { @extends .Button--common; /* red color, light red background */}

这将编译为

.Button--common, .Button--normal, .Button--error { /* font-sizes, padding, border-radius */ }

.Button--normal { /* blue color, light blue background */ }

.Button--error { /* red color, light red background */ }

你只需要在你的标签上引用一个类名,可以得到通用的和独有的样式。功能很强大,但你必须知道,这也存在着特殊情况和陷阱。Hugo Giraudel 汇总了一些问题,想了解更多,请点击《为什么你应该避免使用SASS的@extend》

关于作者:古鲁伊

威尼斯 7

立志做一名有格调的程序媛 个人主页 · 我的文章 · 34

威尼斯 8

使用CSS模块

composes关键词和@extend使用方法类似,但工作方式是不同的。看个例子

.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 */ }

在js代码中,import styles from "./submit-button.css"将得到

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"
}

还是使用styles.normalstryles.error,在DOM中将被渲染为多个类名

<button class="components_submit_button__common__abc5436 components_submit_button__normal__def6547"> Submit</button>

这就是composes的功能,你可以合并多个样式,但不用去修改你的JS代码,也不会重写你的CSS选择器。

第3步.文件间共享代码

使用SASS或LESS工作,通过@import来引用同一个工作空间的文件。你可以声明变量,函数,并在其它文件中使用。很不错的方法,但在各个不同的项目中,变量命名有可能冲突。那么你就得重构你的代码,编写如variables.scsssettings.scss,你也不清楚哪些组件依赖于哪些个变量了。你的settings文件会变得很大。

也有更好的解决方案(《使用Webpack构建更小巧的CSS》),但由于SASS的全局属性,还是有很大的限制。

CSS模块一次只运行一个单独的文件,因此不会污染全局作用域。js代码用使用importrequire来引用依赖,CSS模块使用compose从另一个文件引用样式。

/* 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"; }

使用组件,我们可以像引用本地类名一样,引用colors.css文件的类。而且,组件变化的类名在输出时会被改变,但CSS文件本身并不变化,composes块也会在生成浏览器端CSS之前被去除。

/* colors.css */
.shared_colors__primary__fca929 { color: #720; }
.shared_colors__secondary__acf292 { color: #777; }

/* submit-button.css */
.components_submit_button__common__abc5436 { /* font-sizes, padding, border-radius */ }
.components_submit_button__normal__def6547 {}

 

<button class="shared_colors__primary__fca929 components_submit_button__common__abc5436 components_submit_button__normal__def6547"> Submit </button>

 

实际上,在浏览器端,normal没有自身的样式。这是好事情,你可以添加新的语义化的对象,但不用去添加CSS样式。我们还可以做得更多一点,

在全站开发中增加类名和视觉的一致性,在浏览器端减少样式代码的大小。

旁注:可以使用csso检测并移除空类。

第4步:单一职责模块

组件的强大之处在于描述一个元素是什么,而不修饰它的样式。它以一种不同的方式来映射页面实体(元素)和样式实体(样式规则)。

看一个旧的CSS例子

.some_element { font-size: 1.5rem; color: rgba(0,0,0,0); padding: 0.5rem; box-shadow: 0 0 4px -2px; }

一个元素,一些样式,很简单。尽管这样,还是存在一些问题:color,font-size,box-shadow,padding,这些都在这里指定了,但无法在其它地方使用。

我们用SASS重构一下。

$large-font-size: 1.5rem;
$dark-text: rgba(0,0,0,0);
$padding-normal: 0.5rem;
@mixin subtle-shadow { box-shadow: 0 0 4px -2px; }
.some_element {
@include subtle-shadow;
font-size: $large-font-size;
color: $dark-text;
padding: $padding-normal;
}

比旧的CSS样式有很大的改进,我们只是定义了很少的一部分。事实上像$large-font-size是排版,$padding-normal是布局,这些都仅仅用名字表达含义,不会在任何地方运行。如果要声明一个box-shadow变量,但它并不能表达自身含义,这时就必须使用@mixin@extend了。

使用CSS模块

通过使用组件,我们可以在组件中,注释写明哪些可以重复使用的类名。

.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";
}

使你在网站开发上,每一种视觉对应一个类名。用上面的方式,来开发你的网站,变为一种可能。

.article {
composes: flex vertical centered from "./layout.css";
}
.masthead {
composes: serif bold 48pt centered from "./typography.css";
composes: paragraph-margin-below from "./layout.css";
}
.body {
composes: max720 paragraph-margin-below from "layout.css";
composes: sans light paragraph-line-height from "./typography.css";
}

这是一种我有兴趣进一步探索的技术。在我看来,它结合了像Tachyons的原子CSS技术,像Semantic UI样式类名的可读性,单一职责等优势。

但CSS模块的故事才刚刚开始,希望你能去在现在或将来使用它,并传播它。

上手

通过使用CSS模块,希望能帮助你和你的团队,即可以交流当前的CSS知识和产品,又可以更舒服,更高效地完成工作。我们已经尽可能保持语法的简单,并写了一些例子,当你可以使用这些例子里的代码时,你就可以使用它进行工作了。这里有一些关于Webpack,JSPM和Browseriry项目的DEMO,希望对你有所帮助。我们一直看有哪些新的环境可以运行CSS模块:正在适配服务器端NODEJS和Rails。

为了使事情更简单,这里做了一个Plunkr,可以直接动手,不用安装。开始吧

 威尼斯 9

如果你准备使用了,可以看一看CSS模块源码,如果有什么问题,可以在issue里进行讨论。CSS模块组,规模小,无法涵盖所有的应用场景。

期待你们的讨论。

祝:写样式开心。

原文:CSS Modules

原文链接:

本文由威尼斯发布于Web前端,转载请注明出处:禁止转载,这里的翻译都是根据我自己的理解进

关键词: