css-项目中的解决方案
css是页面的样式控制,但我们在使用中,常常会出现自己写的css样式给覆盖了,这是因为css的样式优先级是根据css的权重来的
权重排行:!important(最高级) > 行内样式(1000) > id(100) > class(10) > element(1)
计算规则:除!important 外,权重是父级到子级的权重相加,最大权重的css样式就覆盖较小权重的css样式
举例:
<style>
#box p{color: red};
.box1 .a.b.c.j p{color: green}
</style>
<body>
<div class="box1">
<div id="box" class="a b c j">
<p>hello world</p>
</div>
</div>
</body>
分析:
- #box p,权重是100 + 1 = 101
- .box1 .a.b.c.j p 权重是 10 + 10 + 1 = 21, 注意,a,b,c,j只能算给一个10,不能进行相加
- 所以hello world 是红色
所以主要权重足够高,你的样式就有可能给覆盖。
为了解决这个问题,一般有下面三种方法处理
- bem:BEM命名方式
- css in js
- css-module
第一种方法:BEM命名方式:B:block(块), E:element(元素),M:modifier(修饰符)
- 中划线 :仅作为连字符使用,表示某个块或者某个子元素的多单词之间的连接记号。
__ 双下划线:双下划线用来连接块和块的子元素
_ 单下划线:单下划线用来描述一个块或者块的子元素的一种状态
<ul class="xxx">
<li class="xxx__item">第一项
<div class="xxx__product-name">我是名称</div>
<span class="xxx__jin-wan-da-lao-hu">看类名</span>
<a href="#" class="xxx__link">我是link</a>
<li>
<li class="xxx__item xxx__item_current">第二项 且 当前选择项
<div class="xxx__product-name">我是名称</div>
<a href="#" class="xxx__item-link">我是link</a>
<li>
<li class="xxx__item xxx__item_hightlight">第三项 且 特殊高亮
<div class="xxx__product-name">我是名称</div>
<a href="#" class="xxx__item-link">我是link</a>
<li>
</ul>
分析:
- xxx代表中一个组件的名称(代表着块)
- xxx__item:双下划线代表着链接块和块的子元素
- xxx__item_current: 单下划线代表着状态 ,这是当前被选中的状态
- xxx__jin-wan-da-lao-hu: 中划线用来连接名称
这样命名的方式,可以很大程度避免class名重复,但是不能完全避免
第二种方法:css in js: 把css的样式作为js的一部分,在通过,行内样式赋值
第三种方法:css-module, 这个是用webpack进行打包时候,对样式进行处理,用hash保证class是唯一的
编译之前的代码
import React from 'react';
import style from './App.css';
export default () => {
return (
<h1 className={style.title}>
Hello World
</h1>
);
};
.title {
color: red;
}
编译之后的代码
<html><head><title>CSS Modules Demo</title>
<style type="text/css">.hUJNtAvq9Izkpp34Oy95D{color:red}.title{color:green}</style></head>
<body>
<script type="text/javascript" src="bundle.js"></script>
<div><h1 data-reactroot="" class="hUJNtAvq9Izkpp34Oy95D">Hello World</h1></div>
</body>
</html>
分析: hUJNtAvq9Izkpp34Oy95D是hash生成的唯一的值,这样可以保证唯一性
webpack配置
var webpack = require('webpack');
module.exports = {
entry: __dirname + '/index.js',
output: {
publicPath: '/',
filename: './bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'stage-0', 'react']
}
},
{
test: /\.css$/,
loader: "style-loader!css-loader?modules"
},
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false }
})
]
};
分析: 重要的代码是"style-loader!css-loader?modules",开启了模块化