百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>CSS教程> CSS Modules 详解
分享文章到:

CSS Modules 详解

发布时间:09/01 来源:未知 浏览: 关键词:

层叠样式表

我们知道,css的全名叫做层叠样式表,这个“层叠”到底是啥意思呢?

有一种说明是,假如你先写了一条样式规则(选手1):


.title {
 color: silver;
}

然后又在后边写了一条相似的(选手2):


.title {
 color: gold;
}

由于名字雷同,选手2就会和选手1打起来(让你丫假冒我!)。结果是选手2得胜,class名为title的元素,终究的color值为gold。

css里就像这样,随时大概一言不和就发生战争,结果输掉的一方就会被胜利的一方所覆盖。“层叠”一词可以说形象地描写了这个历程。

那么,为什么会有这样的层叠(zhàn zhēng )呢?

css的作用域问题

在javascript里,可以做到这样的搭配:


var title = "silver";

(function(){
 var title = "gold";
 console.log(title); // gold
}());

console.log(title); // silver

利用javascript的函数作用域,两位一样名为title的选手可以友好相处。

但回到css里的样式规则,状况就完全不是这么回事了。

css不是程序说话,但假如说要给它加一个作用域的概念的话,那就是:只要全局作用域。

不管分拆为多少个css文件,不管用怎样的方式引入,所有的样式规则都位于统一作用域,只要选中符近似,就有发生覆盖的大概。

减少彼此影响的战略

为减少彼此影响,幸免预感之外的样式覆盖,我们不断以来想过许多方法。

比方你接手一一般人留下来的旧项目,接下来要新增一个标题元素的时候,你会成心识地不去使用.title这样含糊的class名,由于它太容易重名了。终究,你用的名称大概是:


.module-sp-title {
 color: deepskyblue;
}

即便你决议要用.title这个名字,你也会加上包括选中符作为限制:


.module-1 .title { 
 font-size: 18px;
}
/* ... */
.module-2 .title {
 font-size: 14px;
}

其中.module-1和.module-2的名字应当是独一的,这样的代码在组件化(模块化)的开发风格里很常见。

此外,一些有名的css理论,如SMACSS,会倡议你为所有规划样式使用l-或layout-的前缀,以示区分。

相似的做法还有许多,但归结起来,都是在尝试供给一种合理的命名约定。而合理的命名约定,确实是组织css代码的有效战略。

此刻,我们有了新的可用战略,CSS Modules就是其中之一。

技术流的模块化

CSS Modules是一种技术流的组织css代码的战略,它将为css供给默许的部分作用域。

CSS Modules是怎样做到的呢?来看一个CSS Modules的简便例子吧。

有这样的一个html元素:


<h2 id="example_title" class="title">a title for CSS Modules</h2>

依照一般css的写法,我们可以这样为它增加样式:


.title {
 background-color: snow;
}

此刻我们改用CSS Modules。第一,css保持不变。然后,修改html的写法。不再这样直接写html,而是改为在javascript文件里动态增加,这样做(css文件名为main.css):


var styles = require("./main.css");

var el = document.getElementById("example_title");
el.outerHTML = '<h2 class="' + styles.title + '">a title for CSS Modules</h2>';

咦,require了一个css文件?对的,所以要用到webpack。编译后,html和css会变成这样:

看到这样不太美妙的class名你大约就清楚了,CSS Modules没法改动css全局作用域的天性,它是依托动态生成class名这一手段,来实现部分作用域的。明显,这样的class名就可以是独一的,不管本来的css代码写得有多随意,都可以这样转换得到不冲突的css代码。

模拟的部分作用域也没有关系,它是可靠的。

这个CSS Modules的例子说完了,但你必然跟我最初看到的时候一样有许多问题。

CSS Modules的利用细节

怎样启用CSS Modules

“webpack编译css我也用过,如何我用的时候不长这样?”

一样来说,require一个css文件的写法是:


require("./main.css");

但在前面的例子中,用了var styles = require("./main.css");的写法。这就仿佛是在说,我要这个css文件里的样式是部分的,然后我按照需要自行取用。

在项目里利用CSS Modules有许多办法,当前比力常用的是使用webpack的css-loader。在webpack配置文件里写css-loader?modules就可以开启CSS Modules,例如前面的例子所用的:


module: {
 loaders: [{
  test: /\.css$/,
  loader: 'style!css?modules'
 }]
}

才发明不断用着的css-loader本来有这功效?其实,CSS Modules确实是一个后来才并入css-loader的新功效。

自定义生成的class名

名字都这样了,还如何调试?”

为css-loader增添localIdentName参数,是可以指定生成的名字。localIdentName的默许值是[hash:base64],一样开发环境倡议用相似这样的配置:


{
 test: /\.css$/,
 loader: 'style!css?modules&localIdentName=[name]__[local]___[hash:base64:5]'
}

一样利用到前面的例子里,这时候就会变成这样的结果:

这样是不是要成心义多了?

假如是线上环境,可以思考用更短的名字进一步减小css文件大小。

CSS Modules下的html

(看了前面例子里的el.outerHTML = ...后)

“什么,outerHTML?class名还要拼接?你家html才这么写呢!”

很遗憾,CSS Modules官方的例子,也是这个意思:要使用CSS Modules,必需想方法把变量风格的class名注入到html中。也就是说,html模板系统是必需的,也正是如此,比拟一般css的状况,CSS Modules的html写起来要更为费力。

假如你搜一下CSS Modules的demo,可以发明大部分都是基于React的。明显,虚拟DOM风格的React,搭配CSS Modules会很容易(ES6):


import styles from './ScopedSelectors.css';

import React, { Component } from 'react';

export default class ScopedSelectors extends Component {

 render() {
 return (
  <p className={ styles.root }>
  <p className={ styles.text }>Scoped Selectors</p>
  </p>
 );
 }

};

假如不使用React,还是那句话,只要有方法把变量风格的class名注入到html中,就可以用CSS Modules。原始的字符串拼接的写法明显很糟糕,但我们可以借助各种模板引擎和编译工具做一些改善。下面请看一个用Jade的参照 示例。

想象一下你有一个用一般css的页面,但你想在一小块区域使用CSS Modules。这一块区域在一个容器元素里:


<p id="module_sp_container"></p>

后用jade来写html(关联的css文件为module_sp.css):


- styles = require("./module_sp.css");
h2(class=styles.title) a title for CSS Modules

接下来,依然是在javascript里增加这段jade生成的html:


var el = document.getElementById("module_sp_container");
var template = require("./main.jade");
el.innerHTML = template();

最后,记得在css-loader启用CSS Modules的同时,增添jade-loader:


{
 test: /\.jade$/,
 loader: 'jade'
}

编译运转,就可以得到想要的结果。除Jade之外,还有些其他CSS Modules的html利用方案,引荐参照 github上的这篇issue。

当前CSS Modules还在开展中,并且也在思考改善CSS Modules下的html写作体验。CSS Modules团队成员有提到一个叫CSS Modules Injector的将来计划项目,目的是让开发者不消javascript也可以使用CSS Modules(这就很接近原生html + css的组合了)。

CSS Modules下的样式复用

“样式都是独一的了,如何复用?”

我们已经说了挺多一般css单个全局作用域的害处。但对应的,这也有一个很大的好处,就是便于实现样式的复用。css理论OOCSS也是在追求这一点。

CSS Modules供给一个composes办法用于样式复用。例如,你有一个btn.css里有一条:


.btn{
 display: inline-block;
}

然后,你在另一个CSS Module的module_sp.css里可以这样引入它:


.btn-sp{
 composes: btn from "./btn.css";
 font-size: 16px;
}

那么,这个p.btn-sp的DOM元素将会是:

可以看到,composes的用途比力相似sass的@extend,但不一样于@extend的是,composes并不增添css里的选中符总量,而是采纳组合多个class名的情势。在这个例子里,本来仅有1个class的p.btn-sp,变成了2个class。

因此,CSS Modules倡议只使用1个class就定义好对应元素所需的全部样式。它们会再由CSS Modules转换为恰当的class组合。

CSS Modules团队成员认为composes是CSS Modules里最强大的功效:

For me, the most powerful idea in CSS Modules is composition, where you can deconstruct your visual inventory into atomic classes, and assemble them at a module level, without duplicating markup or hindering performance.

更具体的composes的用途及其懂得,引荐阅读CSS Modules: Welcome to the Future。

其他大概有用的补充

和已有的一般css共存

许多项目会引入Bootstrap、Materialize等框架,它们是一般的、全局的css。此外,你也大概本人会写一些一般css。怎样共存呢?CSS Modules团队成员对此提到过:

a CSS Module should only import information relative to it

意思是,倡议把CSS Modules看做一种新的css,和本来的一般css区分开来。比方,composes的时候,不要从那些一般的css里去取。

在css-loader里通过指定test、include、exclude来区分它们。保持CSS Modules的纯洁,只要想要利用CSS Modules的css文件,才启用CSS Modules。

只转换class和id

经过我本人的测试,CSS Modules只转换class和id,此外的标签选中符、伪类等都不会被转换。

倡议只使用class。

一个CSS Module的输出

简便用console.log()就可以查看CSS Module的输出:


var styles = require("./main.css");
console.log("styles = ", styles);

结果相似这样:


{
 "btn-sp": "_2SCQ7Kuv31NIIiVU-Q2ubA _2r6eZFEKnJgc7GLy11yRmV",
 title: "_1m-KkPQynpIso3ofWhMVuK"
}

这可以帮忙懂得CSS Modules是怎样工作的。

预编译器

sass等预编译器也可以用CSS Modules,对应的loader大概是这样:


{
 test: /\.scss$/,
 loader: 'style!css?modules!resolve-url!sass?sourceMap'
}

留意不要由于是sass就习惯性地用嵌套写法,CSS Modules并不适合使用包括选中符。

倡议的命名方式

CSS Modules会把.title转换为styles.title,由于后者是用在javascript中,因此驼峰命名会更适合。

假如像我此前那样写.btn-sp,需要留意在javascript中写为styles["btn-sp"]。

此外,你还可认为css-loader增添camelCase参数来实现主动转换:


{
 test: /\.css$/,
 loader: 'style!css?modules&camelCase',
}

这样即使你写.btn-sp,你也可以直接在javascript里用styles.btnSp。

结语

不管是不断以来我们认真遵照的命名约定,还是这个新的CSS Modules,目的都是一样的:可保护的css代码。我觉得就CSS Modules根本还是在写css这一点来说,它还是很友好的。

虽然本文为了严谨,结果写了相当长的篇幅,但但愿你读过之后,还能觉得CSS Modules是简便易懂的。由于这样,我就达成我的目的:扣题,了。

引荐教程:《PHP》


以上就是CSS Modules 详解的具体内容,更多请关注百分百源码网其它相关文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有153人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板