仅供参考
前言
完成《CSS核心技术与实战》这本书,已有一个多月了,而这篇文章原本是打算写在那本书里面的,但本章讲解的内容,毕竟属于CSS未来的范畴,而这一切都还不能够确定下来,所以这一章没有写进去,但不管怎么说,多少了解一下还是有好处的,里面部分功能,有些浏览器已经实现了。
如果你对CSS预处理器感兴趣,那么本篇文章也许很适合你。
初学CSS预处理器,其实我是不太明白为什么需要用这种东西的,后来想明白一件事,一切都是为了可维护性。比如下面这幅图
距离左边有一点点间距,而其他元素设置的间距往往也是一样的,但如果不使用预处理器,或许我们会这样写
.box{
padding:12px;
}
.footer{
padding:12px;
}
....{
padding:12px;
}
但这种问题是,如果需要更改所有间距,你不得不诶个去替换,这样带来了很多不必要的工作量,如果使用预处理器就好办了,因为预处理器是允许你使用变量的,你可以像编程语言那样,定义一个全局变量,在需要的地方,引用这个全局变量,更改的时候,只需要修改一处就好了,假设代码如下:
var pad = 12px;
.box{
padding:pad;
}
.footer{
padding:pad;
}
也就是说预处理器很大一部分就是为了解决可维护性,本章讲解的是后处理器。
那么后处理器和预处理器有什么区别
你可以这样理解,后处理器就好比动态语言,而预处理器就好比静态语言。预处理器就是事先将结果编译出来,而后处理器则不同,值是在运行时才决定的。
CSS的未来
在未来的CSS中将会支持更多的属性以及函数,其中不乏有变量,嵌套,值计算等,这一章我们将会讲解它们。
注意:因为本节内容大部分需要CSS未来版本才支持,所以你的浏览器可能不一定有效果,不过有一个插件(cssnext)可以解决这个问题,关于这个插件的使用请到本节的最后一节中查看。
CSS变量
1. 变量的基本使用
在这些新增的功能中最喜欢的非CSS变量莫属,CSS变量名通过自定义属性来设置(要实现全局变量,需要在html
或body
也可以在:root
伪类中声明),并且自定义属性必须以--
开头,使用 var()
来访问。如下:
:root{
--colorRed:red;
--size:16px;
--h:35px;
--l-h:35px;
}
a{
display:block;
height:var(--h);
line-height:var(--l-h);
color:var(--colorRed);
font-size:var(--size);
outline:1px solid #666;
}
效果如图13.11
图13.11 变量
以上我们通过:root
在全局中定义了几个变量,然后在a元素中通过var
函数来使用这些变量。
需要注意的是这些变量对大小写是敏感的,如:--color
和--Color
是两个不同的变量。
另外这些变量也是可以继承的,如下这段:
:root{
--color-red:red;
}
.box{
color:var(--color-red);
}
<div class="box">
<p>CSS变量</p>
</div>
效果如图13.12
图13.12 继承
这些变量也具有层叠性,如下这段代码:
:root{
--head-color:red;
}
.box{
--head-color:blue;
}
.box p{
color:var(--head-color);
}
如上这段,我们在全局声明了一个--head-color
在.box
中又声明了一次,那么它最终会使用的是它父元素中定义的--head-color
,就近原则,效果如图13.13
图13.13 变量也具有层叠性
不过还得注意一下就是这些变量不支持!important
,也就是说设置了和没设置是一样的,根本没用,如下:
:root{
--head-color:red !important;
}
.box{
color:var(--head-color);
}
.box{
color:blue;
}
<div class="box">CSS变量</div>
效果如图13.14
图13.14 变量不支持!important
看到了吧,虽然我们给--head-color
设置了!important
但还是被层叠了,如果是正常情况应该会像下面这段代码一样:
.box{
color:red !important;
}
.box{
color:blue;
}
效果如图13.15
图13.15 如果可以的话应该是这个样子
这个var
函数还支持一个很强大的功能,允许你传递一个默认的参数,当变量不存在的时候就会使用默认值,如下:
:root{
/*--head-color:red;*/
}
.box{
color:var(--head-color,orange);
}
以上我们在var
中使用了一个默认的值,当--head-color
不存在就会使用orange
,效果如图13.16
图13.16 使用默认值
2.CSS变量的意义
如果你使用过一些编程语言,你不会忘记变量是多么的重要,如在Javascript
中,我们经常会写这样一段代码:
var oBox = document.getElementById('box');
oBox.style.width = '100px';
oBox.style.height = '100px';
oBox.style.backgroundColor = 'red';
在这段代码中我们通过oBox
变量来引用.box
元素,在下次的使用中就不需要重新去获取这个元素了,这样给我们带来了很大的便利。在CSS中变量也同样重要,不然你让Less
、Sass
等预处理情何以堪,正是因为它们支持在CSS中像编程语言一样编程,所以在之前的很长一段时间里它们是那样的让人着迷。在CSS中合理的使用变量,可以减轻不少的工作,以及可维护性。比如一个网站的主调色,它们基本都是固定的,那么我们完全可以使用变量来储存它们,另外一点就是当网站改版时,如果网站主调色改变时我们只需要改变相应的变量即可,这或许就是变量的最大好处吧。从另一个角度来讲使用变量的另一个好处就是,具有一致性,比如页面中所有元素的字体大小都是引用的同一个变量,那么当我们改变这个变量时,其他元素的字体大小都会相应的改变,我们来看一下,下面这段代码:
:root{
--main-size:12px;
}
.box{
font-size:var(--main-size);
}
.box2{
font-size:var(--main-size);
}
.box3{
font-size:var(--main-size);
}
@media screen and (min-width:600px){
:root{
--main-size:16px;
}
}
以上当屏幕宽度大于600px
时,这三个元素都会相应的改变字体大小,使用这个可以和rem
媲美。也许你还想给其中一个元素单独指定一个比--main-size
大一点的字体,那我们可以结合使用calc
函数,如下:
:root{
--main-size:12px;
}
.box{
font-size:var(--main-size);
}
.box2{
font-size:calc(var(--main-size) + 2px);
}
.box3{
font-size:var(--main-size);
}
效果如图13.17
图13.17 单独设置某个样式
calc
允许你使用计算功能,不过需要注意的是中间需要一个空格。
虽然以上只是几个很简单的例子,但这些也足以说明CSS变量是多么的重要,在以后的CSS写作中不要忘了使用它。
应用规则集(@apply)
我想你如果体验过组件化,那么你对@apply
肯定会爱不释手,简单来说@apply
可以实现更小的组合。如下:
:root{
--overflow-ellipsis:{
overflow:hidden;
text-overflow: ellipsis;
white-space: nowrap;
};
}
.title{
width:200px;
@apply --overflow-ellipsis;
}
在以上我们定义了一个用来实现当元素溢出时隐藏文字的代码段--overflow-ellipsis
,当我们需要时只需要通过@apply
来引用即可,真的是很实用的一个功能,不由想起来了Javascript中的函数。
如果某段代码是重复的,你不妨试试@apply
。
未来的媒体查询
1.自定义媒体查询
使用自定义的媒体查询使之更加语义化,使用如下:
@custom-media --big-viewport (max-width:1100px);
@media (--big-viewport) {
body{
background-color:red;
}
}
通过@custom-media
来设置一个媒体规则。感觉没什么用?好吧,来看下一个功能。
2.限制媒体查询范围
以前如果我们想实现一个限制媒体查询的范围也许是这样的:
@media (min-width: 320px) and (max-width: 640px) {
body{
background-color:red;
}
}
以上我们限制屏幕的宽在320到640之间时让页面背景变成红色,但现在我们可以这样:
@media (width >= 320px) and (width <= 640px) {
body{
background-color:red;
}
}
是不是更加一目了然了,当然它还可以结合@custom-media
来使用,如下:
@custom-media --noly-mobile (width >= 320px) and (width <= 640px);
@media (--noly-mobile) {
body{
background-color:red;
}
}
自定义选择器
想过自己来定义选择器吗,接下来我们就来实现一个,如下:
@custom-selector :--title h2,h3;
.main :--title{
font-size:18px;
font-weight:normal;
}
自定义选择器通过@custom-selector
来定义,后面跟随一个:--
接着是自定义选择器的名称,后面是你需要定义的选择器,多个用逗号隔开,如果你不理解的话,可以看下面这段代码,以上和下面这段代码效果是一样的。
.main h2,
.main h3{
font-size:18px;
font-weight:normal;
}
要说,上面这两段代码的区别,可能就是自定义选择器更加灵活以及方便吧。
选择器嵌套
选择器嵌套是我非常喜欢的一个功能,话说当初我使用预处理器就是因为它有这个功能,小二来一段不加盐的代码:
div {
& h2 {
font-size:16px;
&.title{
color:red;
}
& span{
color:pink;
}
}
}
它的效果和下面这段代码一样:
div h2 {
font-size: 16px
}
div h2.title {
color: red
}
div h2 span {
color: pink
}
有没有一种再也不想用预处理器的冲动,另外对于媒体查询我们不需要用&
来引用,直接在大括号中使用即可,如下:
div {
@media (max-width:1100px) {
background-color:red;
}
}
效果和下面这段代码一样:
@media (max-width:1100px) {
div {
background-color: red
}
}
它还支持比较复杂的嵌套(规则嵌套),如下这段:
a{
@nest p &{
color:red;
}
}
规则嵌套需要使用关键字@nest
,效果和下面这段一样:
p a{
color: red
}
颜色函数
颜色函数通过color
使用,如下:
body{
background-color:color(pink a(30%));
}
这段代码的意思是说给body添加了一个背景为pink
的颜色并且透明度为30%,和下面这段代码一样:
body{
background-color:rgba(255, 192, 203, 0.3);
}
当然你也可以使用其它的颜色表示法,如:
body{
background-color:color(#666 a(30%));
}
这个还是比较方便的。
更多这方面的功能可以到https://drafts.csswg.org/css-color/#modifying-colors中查看。
初始值
我们知道一个div
默认是块元素,那么如果你不想它默认变成块元素可以通过initial
将它设置成初始值。如下:
div {
display: initial;
}
<div>我才是真正的DIV,T_T</div>
<div>我才是真正的DIV,T_T</div>
效果如图13.18所示
图13.18 初始值
这里它之所以在一排了,是因为display
的初始值就是inline
,而为什么不将div
的display
设置成initial
它默认是block
是因为浏览器给div
设置了默认样式,也就是说initial
可以去掉浏览器默认样式。
如果你想去掉一个元素中的所有浏览器默认样式,可以这样:
div{
all:initial;
}
但不是特别建议你这样,最好还是根据需求来。
cssnext插件使用
cssnext插件允许你在CSS中写未来版本的CSS,它会将这些代码转换成浏览器兼容的代码,不过要使用cssnext我们还得下载一个postcss,那么postcss是什么呢?官方是这样说的:
使用JavaScript来转换CSS的工具
这里并不想详细的讲解postcss是什么,更多关于postcss的说明可以到http://postcss.org/官网查看,接下来我们来安装一下postcss
- 安装postcss-cli
npm install postcss-cli -g
- 下载完以后,我们接着下载
cssnext
如下:
npm install postcss postcss-cssnext -g
为了方便我们这里使用的是命令行工具,如果想在命令行工具中使用postcss
需要下载postcss-cli
,这里我们是通过npm
来下载的,npm
是一个包管理工具,这里不做讲解,如果你不知道npm
是什么,我想,你应该是前端新人,建议如果遇到不懂的通过搜索引擎来搜索。npm
官网https://www.npmjs.com/
这些都成功安装完以后我们就可以开始使用它了,如下:
postcss styles.css -u postcss-cssnext -d dist
效果如图13.19所示
图13.19 输入这段代码
以上这段代码的意思是用postcss-cssnext
这个插件将styles.css
里面的代码转换成兼容的代码,-d
表示要输出到哪个目录,-w
可以用来监听文件的变化,当文件变化时会自动输出文件,如下:
postcss styles.css -u postcss-cssnext -w -d dist
更多方法可以访问https://github.com/postcss/postcss-cli
具体效果如下:
源代码:
:root{
--main-color:red;
}
div{
display:flex;
}
span{
color:var(--main-color);
}
转换后的代码:
div{
display:-webkit-box;
display:-ms-flexbox;
display:flex;
}
span{
color:red;
}
完。