서문
CSS 전처리기에 관심이 있다면 이 기사가 적합할 수 있습니다.
처음 CSS 전처리기를 배웠을 때 왜 이런 것을 사용해야 하는지 잘 이해하지 못했습니다. 그런데 모든 것이 유지 관리를 위한 것이라는 사실을 깨달았습니다. 예를 들어 아래 그림
은 왼쪽에서 약간의 간격이 있고 다른 요소에서 설정한 간격도 같은 경우가 많은데 전처리기를 사용하지 않으면 , 아마도 우리는 이렇게 될 것입니다.
CSS
.box{ padding:12px; } .footer{ padding:12px; } ....{ padding:12px; }
그러나 이것의 문제는 필요한 경우 간격을 모두 바꾸려면 불필요한 작업이 많이 필요합니다. 전처리기를 사용하면 프로그래밍 언어처럼 전역 변수를 정의할 수 있으므로 더 쉬울 것입니다. 필요할 때 사용하세요. 변경할 때 한 곳만 수정하면 됩니다.
CSS
var pad = 12px; .box{ padding:pad; } .footer{ padding:pad; }
즉, 전처리기의 큰 부분은 유지보수성을 해결하는 것입니다.
이렇게 이해하시면 됩니다. 후처리기는 동적 언어와 같고, 전처리기는 정적 언어와 같습니다. 전처리기는 결과를 미리 컴파일하지만 후처리기는 다릅니다. 값은 런타임에 결정됩니다.
미래에 CSS는 변수, 중첩, 값 계산 등을 포함한 더 많은 속성과 기능을 지원할 예정입니다. 이에 대해 이 장에서 설명하겠습니다.
참고: 이 섹션의 콘텐츠 대부분은 CSS의 향후 버전을 지원해야 하기 때문에 브라우저에 반드시 효과가 있는 것은 아닙니다. 그러나 이 문제를 해결할 수 있는 플러그인(cssnext)이 있습니다. 이 플러그인 사용에 대한 자세한 내용은 이 섹션의 마지막 섹션을 확인하세요.
이러한 새로운 기능 중에서 제가 가장 좋아하는 것은 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
는 서로 다른 두 변수입니다.
또한 이러한 변수는 아래와 같이 상속될 수도 있습니다.
CSS
:root{ --color-red:red; } .box{ color:var(--color-red); }
효과는 그림 13.12와 같습니다
CSS 변수
그림 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
을 지원하지 않는다는 점에 유의해야 합니다. 즉, 설정 여부는 동일하며 다음과 같이 전혀 쓸모가 없습니다.
CSS
:root{ --head-color:red !important; } .box{ color:var(--head-color); } .box{ color:blue; }
효과는 그림과 같습니다. 13.14
CSS 변수
그림 13.14 변수는 !important를 지원하지 않습니다
보시다시피 --head-color
를 !important
로 설정했지만 , 여전히 계단식으로 연결되어 있으면 다음 코드와 같아야 합니다.
CSS
.box{ color:red !important; } .box{ color:blue; }
효과는 그림 13.15에 나와 있습니다
그림 13.15 가능한 경우 다음과 같아야 합니다.
이 var
함수도 매우 강력한 기능을 지원하므로 기본값을 전달할 수 있습니다. 변수가 존재하지 않을 경우 다음과 같이 기본값이 사용됩니다.
CSS
:root{ /*--head-color:red;*/ } .box{ color:var(--head-color,orange); }
以上我们在var
中使用了一个默认的值,当--head-color
不存在就会使用orange
,效果如图13.16
图13.16 使用默认值
如果你使用过一些编程语言,你不会忘记变量是多么的重要,如在Javascript
中,我们经常会写这样一段代码:
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中合理的使用变量,可以减轻不少的工作,以及可维护性。比如一个网站的主调色,它们基本都是固定的,那么我们完全可以使用变量来储存它们,另外一点就是当网站改版时,如果网站主调色改变时我们只需要改变相应的变量即可,这或许就是变量的最大好处吧。从另一个角度来讲使用变量的另一个好处就是,具有一致性,比如页面中所有元素的字体大小都是引用的同一个变量,那么当我们改变这个变量时,其他元素的字体大小都会相应的改变,我们来看一下,下面这段代码:
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
函数,如下:
CSS
: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
可以实现更小的组合。如下:
CSS
:root{ --overflow-ellipsis:{ overflow:hidden; text-overflow: ellipsis; white-space: nowrap; }; } .title{ width:200px; @apply --overflow-ellipsis; }
在以上我们定义了一个用来实现当元素溢出时隐藏文字的代码段--overflow-ellipsis
,当我们需要时只需要通过@apply
来引用即可,真的是很实用的一个功能,不由想起来了Javascript中的函数。
如果某段代码是重复的,你不妨试试@apply
。
使用自定义的媒体查询使之更加语义化,使用如下:
CSS
@custom-media --big-viewport (max-width:1100px); @media (--big-viewport) { body{ background-color:red; } }
通过@custom-media
来设置一个媒体规则。感觉没什么用?好吧,来看下一个功能。
以前如果我们想实现一个限制媒体查询的范围也许是这样的:
CSS
@media (min-width: 320px) and (max-width: 640px) { body{ background-color:red; } }
以上我们限制屏幕的宽在320到640之间时让页面背景变成红色,但现在我们可以这样:
CSS
@media (width >= 320px) and (width <= 640px) { body{ background-color:red; } }
是不是更加一目了然了,当然它还可以结合@custom-media
来使用,如下:
CSS
@custom-media --noly-mobile (width >= 320px) and (width <= 640px); @media (--noly-mobile) { body{ background-color:red; } }
想过自己来定义选择器吗,接下来我们就来实现一个,如下:
CSS
@custom-selector :--title h2,h3; .main :--title{ font-size:18px; font-weight:normal; }
自定义选择器通过@custom-selector
来定义,后面跟随一个:--
接着是自定义选择器的名称,后面是你需要定义的选择器,多个用逗号隔开,如果你不理解的话,可以看下面这段代码,以上和下面这段代码效果是一样的。
CSS
.main h2, .main h3{ font-size:18px; font-weight:normal; }
要说,上面这两段代码的区别,可能就是自定义选择器更加灵活以及方便吧。
选择器嵌套是我非常喜欢的一个功能,话说当初我使用预处理器就是因为它有这个功能,小二来一段不加盐的代码
CSS
p { & h2 { font-size:16px; &.title{ color:red; } & span{ color:pink; } } }
它的效果和下面这段代码一样:
CSS
p h2 { font-size: 16px } p h2.title { color: red } p h2 span { color: pink }
有没有一种再也不想用预处理器的冲动,另外对于媒体查询我们不需要用&
来引用,直接在大括号中使用即可,如下:
CSS
p { @media (max-width:1100px) { background-color:red; } }
效果和下面这段代码一样:
CSS
@media (max-width:1100px) { p { background-color: red } }
它还支持比较复杂的嵌套(规则嵌套),如下这段:
CSS
a{ @nest p &{ color:red; } }
规则嵌套需要使用关键字@nest
,效果和下面这段一样:
CSS
p a{ color: red }
color
使用,如下:CSS
body{ background-color:color(pink a(30%)); }
这段代码的意思是说给body添加了一个背景为pink
的颜色并且透明度为30%,和下面这段代码一样:
CSS
body{ background-color:rgba(255, 192, 203, 0.3); }
当然你也可以使用其它的颜色表示法,如:
CSS
body{ background-color:color(#666 a(30%)); }
这个还是比较方便的。
更多这方面的功能可以到https://drafts.csswg.org/css-color/#modifying-colors中查看。
我们知道一个p
默认是块元素,那么如果你不想它默认变成块元素可以通过initial
将它设置成初始值。如下:
CSS
p { display: initial; }
我才是真正的DIV,T_T
我才是真正的DIV,T_T
效果如图13.18所示
图13.18 初始值
这里它之所以在一排了,是因为display
的初始值就是inline
,而为什么不将p
的display
设置成initial
它默认是block
是因为浏览器给p
设置了默认样式,也就是说initial
可以去掉浏览器默认样式。
如果你想去掉一个元素中的所有浏览器默认样式,可以这样:
CSS
p{ all:initial; }
但不是特别建议你这样,最好还是根据需求来。
cssnext插件允许你在CSS中写未来版本的CSS,它会将这些代码转换成浏览器兼容的代码,不过要使用cssnext我们还得下载一个postcss,那么postcss是什么呢?官方是这样说的:
使用JavaScript来转换CSS的工具
这里并不想详细的讲解postcss是什么,更多关于postcss的说明可以到http://postcss.org/官网查看,接下来我们来安装一下postcss
安装postcss-cli
npm install postcss-cli -g
2.
npm install postcss postcss-cssnext -g
下载完以后,我们接着下载cssnext
如下:
为了方便我们这里使用的是命令行工具,如果想在命令行工具中使用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
具体效果如下:
源代码:
CSS
:root{ --main-color:red; } p{ display:flex; } span{ color:var(--main-color); }
转换后的代码:
CSS
p{ display:-webkit-box; display:-ms-flexbox; display:flex; } span{ color:red; }