高效开发之SASS篇
作为通往前端大神之路的普通的一只学鸟,最近接触了一样稍微高逼格一点的神器,特与大家分享~
他是谁?
作为前端开发人员,你肯定对css很熟悉,但是你知道css可以自定义吗?大家都知道,js中可以自定义变量,css仅仅是一个标记语言,不是编程语言,因此不可以自定义变量,也不可以引用等等。作为一名程序员,不能编程怎么能忍受,这就是sass存在的意义,工业化生产,让CSS程序范儿。
主要目的就是让你写CSS时不在重复。
SASS优点可以简单的规纳为以下几点:
- 增加了一些编程特性
- 简少CSS代码的重复性与代码的冗余
- 维护方便
- 适应性更强,可读性更强
代码从层次不清楚?css不够灵活?开发繁杂而痛苦?开发费时费力?
有了SASS,麻麻再也不用担心我敲代码了
安装
SASS是Ruby语言写的,但是两者的语法没有关系。不懂Ruby,照样使用。只是必须先安装Ruby,然后再安装SASS。
1. 安装ruby
如果你是WINDOWS 猛戳这里
下载rubyinstaller.exe 安装就可以了。
如果你是MAC
1
2
3
4
5
6
7
8
9
|
$ curl -L https://get.rvm.io | bash -s stable $ source ~/.rvm/scripts/rvm $ rvm -v
$ rvm install 2.0.0 $ gem -v |
可以看到版本号,说明安装成功!
假定你已经安装好了Ruby,接着在命令行输入下面的命令:
1
|
gem install sass |
好啦,大神必备轻松带回家。
若gem命令出行错误,猛戳这里
2. 使用
俗话说,简单的才是最好的,SASS其实就是一普通的文本文件,支持CSS的所有格式,当然后缀名不同哦,他的后缀名是.scss,意思为Sassy CSS。 下面的命令,可以在屏幕上显示.scss文件转化的css代码。(假设文件名为crtest)
1
|
sass crtest.scss |
如果要将显示结果保存成文件,后面再跟一个.css文件名。
1
|
sass crtest.scss crtest.css |
怎么样,很简单吧
SASS提供四个编译风格的选项:
1
2
3
4
|
* nested:嵌套缩进的css代码,它是默认值。 * expanded:没有缩进的、扩展的css代码。 * compact:简洁格式的css代码。 * compressed:压缩后的css代码。 |
生产环境当中,一般使用最后一个选项。
1
|
sass --style compressed test.sass test.css |
你也可以让SASS监听某个文件或目录,一旦源文件有变动,就自动生成编译后的版本。
1
2
3
4
|
// watch a file sass --watch input.scss:output.css // watch a directory sass --watch app/sass:public/stylesheets |
SASS的官方网站,提供了一个在线转换器。你可以在那里,试运行下面的各种例子。
用法
1. 变量
在SASS中使用美元符号定义一个变量,在这个例子里,一个美元自负,变量名字加上一个冒号定义一个变量。
$blue : #1875e7; div { color : $blue; }
当然,在SASS中有一些内建的功能,例如,darken,lighten来帮助你修改变量。下面例子里,我们使用lighten方法来生成段落中更亮的红色:
$red: #FF4848 $fontsize: 12px h1 color: $red p color: lighten($red, 10%)
在SASS中你还可以使用加减的方式来修改变量的值,如下:
p.addition_and_subtraction color: $red - #101 font-size: $fontsize + 10px
如果变量需要镶嵌在字符串之中,就必须需要写在#{}之中。
$side : left; .rounded { border-#{$side}-radius: 5px; }
2. 计算
SASS允许在代码中使用算式:
body { margin: (14px/2); top: 50px + 100px; right: $var * 10%; }
3. 嵌套
SASS允许选择器嵌套。比如,下面的CSS代码:
div h1 { color : red; } //可以写成: div { hi { color:red; } } //属性也可以嵌套,比如border-color属性,可以写成: p { border: { color: red; } } //注意,border后面必须加上冒号。
在嵌套的代码块内,可以使用&引用父元素。比如a:hover伪类,可以写成:
a { &:hover { color: #ffb3ff; } }
4 注释
SASS共有两种注释风格。
标准的CSS注释 / comment / ,会保留到编译后的文件。
单行注释 // comment,只保留在SASS源文件中,编译后被省略。
在/*后面加一个感叹号,表示这是"重要注释"。即使是压缩模式编译,也会保留这行注释,通常可以用于声明版权信息。
/*!
重要注释!
*/
福利来了!
CSS也可以重用了
5. 继承
当我们需要为多个元素定义相同样式的时候,我们可以考虑使用继承的做法。
SASS允许一个选择器,继承另一个选择器。比如,现有class1:
.class1 { border: 1px solid #ddd; }
class2要继承class1,就要使用@extend命令:
.class2 { @extend .class1; font-size:120%; }
6. mixin
Mixin有点像C语言的宏(macro),是可以重用的代码块。
使用@mixin命令,定义一个代码块。
@mixin left { float: left; margin-left: 10px; }
使用@include命令,调用这个mixin。
div { @include left; }
7. 颜色函数
如果你在为颜色的单调用法而烦恼,赶快mark
CSS 预处理器一般都会内置一些颜色处理函数用来对颜色值进行处理,例如加亮、变暗、颜色梯度等。
lighten(#cc3, 10%) // #d6d65c darken(#cc3, 10%) // #a3a329 grayscale(#cc3) // #808080 complement(#cc3) // #33c
8. 插入文件
@import命令,用来插入外部文件。
很多 CSS 开发者对导入的做法都不太感冒,因为它需要多次的 HTTP 请求。但是在 CSS 预处理器中的导入操作则不同,它只是在语义上包含了不同的文件,但最终结果是一个单一的 CSS 文件,如果你是通过 @ import "file.css";
导入 CSS 文件,那效果跟普通的 CSS 导入一样。注意:导入文件中定义的混入、变量等信息也将会被引入到主样式文件中,因此需要避免它们互相冲突。
@import "path/filename.scss";
如果插入的是.css文件,则等同于css的import命令。
@import "foo.css";
9. 高级用法
神奇的在这里
9.1 条件语句
@if可以用来判断: p { @if 1 + 1 == 2 { border: 1px solid; } @if 5 < 3 { border: 2px dotted; } } 配套的还有@else命令: @if lightness($color) > 30% { background-color: #000; } @else { background-color: #fff; }
9.2 循环语句
SASS支持for循环:
@for $i from 1 to 10 { .border-#{$i} { border: #{$i}px solid blue; } }
也支持while循环:
$i: 6; @while $i > 0 { .item-#{$i} { width: 2em * $i; } $i: $i - 2; }
each命令,作用与for类似:
@each $member in a, b, c, d { .#{$member} { background-image: url("/image/#{$member}.jpg"); } }
9.3 自定义函数
SASS允许用户编写自己的函数。
@function double($n) { @return $n * 2; } #sidebar { width: double(5px); }
看到这里,是不是感觉又重见天日了,大家应该了解了它的简单用法,大家如果有什么看法或见解,欢迎交流~
灵异留白事件——图片下方无故留白
本人在实践过程中偶尔遇见此等不解的状况,但往往睁一只眼闭一只眼,采取另外的方式了,而今看到原博主的一篇文章,大受启发,希望对各位博友也有所帮助~
① 基本现象
要八卦vertical-align
和line-height
之间的关系,我们不妨从一个极其简单的现象入手。假设,我们有一个<div>
标签,然后,里面有一张<img>
图片,我们的HTML代码就是这样子:
<div><img src="mm1.jpg"></div>
然后,表现就是一张图片呈现,类似下面这样:
恩,看上去很正常,一切都是理所当然。然而,如果我们给这个<div>
元素增加一个背景色,例如淡蓝色:
<div style=""><img src="mm1.jpg"></div>
则会是下面这样:
会发现图片下面有一段空白空间:
想必大家都遇到过类似问题,不知大家有没有思考过,为什么图片下面有留有一段间隙呢?
实际上,这段空白间隙就是vertical-align
和line-height
携手搞的鬼!
首先,大家一定要意识到这么一点:对于内联元素,vertical-align与line-height虽然看不见,但实际上「到处都是」!
因此,对于内联元素各种想得通或者想不通的行为表现,基本上都可以用vertical-align
和line-height
来解释,以及进行行为矫正,然而,要深入理解这些行为表现,还是需要狠花一番功夫的,因此,下面的内容,请确保你有半小时充足时间细细阅读,别的地方可是看不到的。
② 幽灵空白节点
「幽灵空白节点」这个概念我自己命名的,注意,是我个人YY出来的,是我自己便于理解某些行为特征提出的概念。规范可能有类似的概念,但名称并非这个。 W3C规范虽然有很多行为的解释和说明,但是,毕竟官方的东西,要求严谨正式,但是,也会有太干太涩的感觉。如果快速掌握和理解这些行为表现呢?就我个人而言,从两方面入手:1.情感化认知;2. 具象化思维。
例如,我称vertical-align
和line-height
为好基友(包括以前称浮动和绝对定位是兄弟),就是“情感化认知”;而这里的「幽灵空白节点」就是“具象化思维”。
那「幽灵空白节点」是个什么意思呢?
在HTML5文档声明下,块状元素内部的内联元素的行为表现,就好像块状元素内部还有一个(更有可能两个-前后)看不见摸不着没有宽度没有实体的空白节点,这个假想又似乎存在的空白节点,我称之为“幽灵空白节点”。//zxx: 自己捣腾的概念,不是权威,欢迎其他小伙伴反馈权威解释
抽象了这个概念,绝对定位与text-align
的一些行为表现,以及这里的行为表现,就好理解了。
还是上面的图片下边缘留空隙的例子,实际上,这种行为表现,就跟图片前面或者后面有一个宽度为0的空格元素表现是一致的。但是,空格是透明的,为了便于大家理解,我就直接使用很明显的匿名inline box, 也就是字符代替。如下,大家会发现,图片下面的间隙,依旧是那个间隙。
下面要解释这个间隙就好解释了。下面,我们让新增的文本inline-block化,然后弄个白色背景,显示其占据的高度。
会发现,图片下面的间隙,依旧是那个间隙。但是,我们的理解就好理解了。回答下面几个问题,我们就知道表现的原因了:
-
vertical-align
默认的对齐方式是? - 后面zxx文字的高度从何而来?
上面2个问题就很简单了:
-
vertical-align
默认值是baseline
, 也就是基线对齐。而基线是什么,基线就是字母X的下边缘(参见“字母’x’在CSS世界中的角色和故事”一文)。所以,妹子图片的下边缘就和后面zxx中的字母x
下边缘对齐(见下图)。而字符zxx
本身是有高度的,对吧,于是,图片下面就留空了。
- 而
zxx
文字的高度是由行高决定的。
因此,简单的图片下面留白行为表现,本质上,就是vertical-align
和line-height
背地里搞基造成的。
知道了问题的原因,我们就可以对症下药,准确搞定图片下面我们不希望看到的间隙。怎么搞呢?一对基友,vertical-align
和line-height
我们随便搞定一个就可以了。
比方说vertical-align
.
1. 让vertical-align失效
图片默认是inline
水平的,而vertical-align
对块状水平的元素无感。因此,我们只要让图片display
水平为block
就可以了,我们可以直接设置display
或者浮动、绝对定位等(如果布局允许)。例如:
img { display: block; }
则妹子就会变这样:
下面的空隙不见了。
2. 使用其他vertical-align值
告别baseline
, 取用其他属性值,比方说bottom
/middle
/top
都是可以的。
vertical-align:bottom vertical-align:middle vertical-align:top
3. 直接修改line-height值
下面的空隙高度,实际上是文字计算后的行高值和字母x下边缘的距离。因此,只要行高足够小,实际文字占据的高度的底部就会在x的上面,下面没有了高度区域支撑,自然,图片就会有容器底边贴合在一起了。比方说,我们设置行高5像素:
div { line-height: 5px; }
4. line-height为相对单位,font-size间接控制
如果line-height
是相对单位,例如line-height:1.6
或者line-height:160%
之类,也可以使用font-size
间接控制,比方说来个狠的,font-size
设为大鸡蛋0
, 本质上还是改变line-height
值.
div { font-size: 0; }
③ 基本现象衍生:垂直居中
由于「幽灵空白节点」的存在,因此,我们可以进一步衍生,实现其他更实用的效果,比方说任意尺寸的图片(或者内联块状化的多行文字)的垂直居中效果。就是借助本文的两位男主角,vertical-align
和line-height
。
你想啊,图片后面(前面)有个类似空格字符的节点,然后就能响应line-height
形成高度,此时,图片再来个vertical-align:middle
,当当当当,就可以和这个被行高撑高的「幽灵空白节点」(近似)垂直对齐了。
例如:
div { line-height: 240px; } img { vertical-align: middle; }
然后就会这样子:
不过上面的效果并不是完全的垂直居中,只是近似(稍微仔细看可以看出来)。为什么只是近似呢?那是因为「幽灵空白节点」高度行高撑开,其垂直中心是字符content area的中心,而对于字符x
而言,都是比绝对中心位置要下沉的(不同字体下沉幅度不一样),换句更易懂的描述就是x
的中心位置都是在字符内容区域高度中心点的下方,而这上下的偏差就是这里图片上下间距的偏差。
我特意把字符x
使用大字号演示了下:
换句更简单的话说就是:middle中线位置(字符x
的中心)并不是字符内容的绝对居中位置。两个位置的偏差就是图片近似居中的偏差。
嘛嘛,单纯的文字还是太苍白了,截个图示意下吧:
因此,要想完全垂直居中,最先想到的方法就是让后面的“幽灵字符”也是vertical-align:middle
,然而,呵呵,既然称之为“幽灵”就表示不会受非继承特性的属性影响,所以,根本没法设置vertical-align:middle
,除非你自己创建一个显示的内联元素。
我们就没有办法了吗?当然不是,“幽灵字符”可以受具有继承特性的CSS属性影响,于是,我们可以通过其他东西来做调整,让字符的中线和字符内容中心线在一起,或者说在一个位置上就可以了。有人可能要疑问了,这能行吗?啊,是可以的。
怎么搞?很简单,font-size:0
, 因此此时content area高度是0,各种乱七八糟的线都在高度为0的这条线上,绝对中心线和中线重合。自然全垂直居中:
div { line-height: 240px; font-size: 0; } img { vertical-align: middle; }
结果是:
处女座的你,是不是看过去舒服多啦!?
这种通过line-height
定高,元素vertical-align:middle
垂直居中的方法不仅适用于现代浏览器,连IE7浏览器也是支持的:
不过和其他浏览器再使用上还是有些需要注意的地方,就是,HTML不能这样:
<div><img src="mm1.jpg"></div>
而是需要在图片标签结束处留下空格后者换行:
<div><img src="mm1.jpg"><!-- 这里要折行或空格 --> </div>
④ 复杂现象
多年前曾分享过“text-align:justify下列表的两端对齐布局”的技术,其中,为了让任意个数的列表最后一行也是对齐排列,在列表最后会辅助列表等宽的空标签元素来占位,类似下面红色高亮HTML代码:
.justify-fix { display: inline-block; width: 128px; }
<div style="text-align: justify;"> <img src="img/mm1.jpg" width="128"> <img src="img/mm1.jpg" width="128"> <img src="img/mm1.jpg" width="128"> <img src="img/mm1.jpg" width="128"> <i class="justify-fix"></i> <i class="justify-fix"></i> <i class="justify-fix"></i> </div>
为了节约空间,我就使用小图示意:
同样的,在白色背景下,似乎看上去效果还不赖,但是,如果给div
容器加个背景色~~
会惊讶的发现,下面多了很大一块间隙(如下截图):
为了便于大家看其究竟,我把占位i
元素outline
高亮下,于是,效果如下:
结果会发现,上面巨大的空隙是由占位i
元素上面和下面的间隙共同组成的。
下面问题来了:上面的间隙是如何产生的?下面的间隙是如何产生的?如果去除这些间隙呢?
很多时候,复杂问题是由简单问题组合而成的,实际上,这里的间隙现象的始作俑者和上面的简单现象一样,都是vertical-align
和line-height
搞基带来的不好的影响。
按照之前问题解决方法,我们可以直接来个line-height:0
解决垂直间隙问题:
div { line-height: 0; }
结果图片和图片之间的间隙是没有了,但是,图片和最后的占位元素之间依然有个几像素的间距,,啊啊啊啊,这究竟是什么鬼?
简单现象的背后往往有大的学问,接下来是本文的高潮了,究其原因,要说到inline-block元素和基线baseline之间的一些纠缠的关系。
⑤ inline-block和baseline
CSS2的可视化格式模型文档中有一么一段话:
The baseline of an ‘inline-block’ is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its ‘overflow’ property has a computed value other than ‘visible’, in which case the baseline is the bottom margin edge.
英文看得眼睛大,于是我中文直译了下:
‘inline-block’的基线是正常流中最后一个line box的基线, 除非,这个line box里面既没有line boxes或者本身’overflow’属性的计算值而不是’visible’, 这种情况下基线是margin底边缘。
这段文档中出现了很多专有名词line box
, line boxes
等,这些是内联盒子模型中的概念,是CSS进阶必备知识。我在“浮动深入理解(一)”一文的中间穿插介绍了该模型。//zxx: 我现在后悔了,内联盒子模型当初应该直接独立成一篇文章,这样其他文章可以很干净地引用,所谓文章的模块化书写
如果大家没有足够精力去学习之,可以先看下面这张图:
由于上面的译文是直译的,理解起来还是有些拗口,我使用通俗的话描述就是:一个inline-block元素,如果里面没有inline内联元素,或者overflow不是visible,则该元素的基线就是其margin底边缘,否则,其基线就是元素里面最后一行内联元素的基线。
纳尼,还是没反应过来?
那我们看下面这个例子,应该就知道什么意思了。
两个同尺寸的inline-block
水平元素,唯一区别就是一个空的,一个里面有字符,代码如下:
.dib-baseline { display: inline-block; width: 150px; height: 150px; border: 1px solid #cad5eb; background-color: #f0f3f9; }
<span class="dib-baseline"></span> <span class="dib-baseline">x-baseline</span>
结果,科科:
x-baseline
会发现,明明尺寸、display水平都是一样的,结果呢,两个却不在一个水平线上对齐,为什么呢?哈哈,上面的规范已经说明了一切。第一个框框里面没有内联元素,因此,基线就是容器的margin下边缘,也就是下边框下面的位置;而第二个框框里面有字符,纯正的内联元素,因此,第二个框框就是这些字符的基线,也就是字母x的下边缘了。于是,我们就看到了框框1下边缘和框框2里面字符x
底边对齐的好戏。框框2有个小彩蛋,点击可以toggle其innerHTML
,会发现,如果框框2里面没文字,就和框框1举案齐眉了。
下面我们要做一件很有必要的事情,用来帮助我们理解上面复杂例子在line-height
值为0
后的表现,什么事情呢?哈,同境界模拟,我们也设置框框2的line-height
值为0
,于是,就会是下面这样的表现:
x-baseline
知道框框2为何又下沉了一点吗?
因为字符实际占据的高度是由行高决定的,当行高变成0的时候,字符占据的高度也是0
,此时,高度的起始位置就变成了字符content area的垂直中心位置,于是,文字就一半落在看看2的外面了。
由于文字字符上移了,自然基线位置(字母x
的底边缘)也往上移动了,于是,两个框框的垂直落差就更大了。
OK,明白了上面的简单例子,也就能明白上面的复杂例子。紧接着,如果我们在最后一个占位的<i>
元素后面新增同样的x-baseline
字符,则:
大家是不是就可以明白原因所在啦!
额~居然还有小伙伴皱眉头,那我再用文字解释下:
现在行高line-height
是0
, 则最后的x-baseline
的垂直中线就和上面一列的图片对齐,而基线呢,就在中线下面差不多半个x的高度地方,而这个高度落差就是最后图片和容器的间隙高度值,因为前面的<i class="justify-fix">
是个空元素,基线是自身的底部,哈哈,造业啊!
OK,一旦知道了现象的本质,我们就能轻松对症下药了!要么改造占位<i>
元素的基线、要么改造“幽灵空白节点”的基线位置、要么使用其他vertical-align
对齐方式~
首先,来个最有意思的方法,对吧,改造占位<i>
元素的基线。这个很简单,对吧,只要在空的<i>
元素里面随便放几个字符就可以了,例如,里面有个x
:
会发现,间隙没有了! 为什么呢?哈哈,因为<i>
元素的基线和“幽灵空白节点”的基线位置现在一致了,没有了错位,自然就不会有间隙啦!
改造“幽灵空白节点”的基线位置,哈哈,使用font-size
,字体足够小时,基线和中线会重合在一起,什么时候字体足够小呢,就是0
. 于是,CSS代码(line-height
如果是相对值,line-height:0
也可以省掉):
div { font-size: 0; }
使用其他vertical-align
对齐方式,就是让两端对齐的列表元素vertical-align:top/bottom/...
之类。
div { line-height: 0; } .justify-fix { display: inline-block; width: 128px; vertical-align: top; }
最后的效果是:
恩恩,各种方法都完美解决了垂直间隙的问题,来,各个大大的赞!
至此,vertical-align
和line-height
的断背基友关系算是彻底暴露了,而且,从行为表现上来看,line-height
是攻,vertical-align
是个受。而很多内联元素的行为表现,就是这对基友搞七搞八一起搞出来的。
以前,关系处于地下的时候,我们可能不会明白,为何男厕所的卷纸用得比女厕所还快;但是,现在关系暴露了,很多以前我们想不明白的事情一下子就豁然开朗了。
因此,我们要以正确地心态去看待这对好基友,毕竟,他们可以CSS届非常重要的两个主力大将。
本文牵扯的知识点甚多,建议大家如果想在重构领域有所造诣,很多基本的却很深入的东西是很有必要弄透的。篇幅有限,有不少知识点都是一笔带过的,大家若有疑问,可以自己去检索与研究,例如,vertical-align
各个值的规范解释,内联盒子模型,等等。也欢迎各种方式交流。
原文地址:http://www.zhangxinxu.com/wordpress/?p=4925
你会用::before、::after吗
目录
::before和::after伪元素的用法
一、介绍
css3为了区分伪类和伪元素,伪元素采用双冒号写法。
常见伪类——:hover,:link,:active,:target,:not(),:focus。
常见伪元素——::first-letter,::first-line,::before,::after,::selection。
::before和::after下特有的content,用于在css渲染中向元素逻辑上的头部或尾部添加内容。
这些添加不会出现在DOM中,不会改变文档内容,不可复制,仅仅是在css渲染层加入。
所以不要用:before或:after展示有实际意义的内容,尽量使用它们显示修饰性内容,例如图标。
举例:网站有些联系电话,希望在它们前加一个icon☎,就可以使用:before伪元素,如下:
<!DOCTYPE html> <meta charset="utf-8" /> <style type="text/css"> .phoneNumber::before { content:'\260E'; font-size: 15px; } </style> <p class="phoneNumber">12345645654</p>
Note:这些特殊字符的html,js和css的写法是不同的,具体可查看html特殊字符的html,js,css写法汇总。
二、content属性
::before和::after必须配合content属性来使用,content用来定义插入的内容,content必须有值,至少是空。默认情况下,伪类元素的display是默认值inline,可以通过设置display:block来改变其显示。
content可取以下值。
1、string
使用引号包一段字符串,将会向元素内容中添加字符串。如:a:after{content:""}
举例:
<!DOCTYPE html> <meta charset="utf-8" /> <style type="text/css"> p::before{ content: "《"; color: blue; } p::after{ content: "》"; color: blue; } </style> <p>平凡的世界</p>
2、attr()
通过attr()调用当前元素的属性,比如将图片alt提示文字或者链接的href地址显示出来。
<style type="text/css"> a::after{ content: "(" attr(href) ")"; } </style> <a href="http://www.cnblogs.com/starof">starof</a>
3、url()/uri()
用于引用媒体文件。
举例:“百度”前面给出一张图片,后面给出href属性。
<style> a::before{ content: url("https://www.baidu.com/img/baidu_jgylogo3.gif"); } a::after{ content:"("attr(href)")"; } a{ text-decoration: none; } </style> --------------------------- <body> <a href="http://www.baidu.com">百度</a> </body>
效果:
4、counter()
调用计数器,可以不使用列表元素实现序号功能。
配合counter-increment和counter-reset属性使用:
h2:before { counter-increment: chapter; content: "Chapter " counter(chapter) ". " }
代码:
<style> body{ counter-reset: section; } h1{ counter-reset: subsection; } h1:before{ counter-increment:section; content:counter(section) "、"; } h2:before{ counter-increment:subsection; content: counter(section) "." counter(subsection) "、"; } </style> ------------------------------------------------ <body> <h1>HTML tutorials</h1> <h2>HTML Tutorial</h2> <h2>XHTML Tutorial</h2> <h2>CSS Tutorial</h2> <h1>Scripting tutorials</h1> <h2>JavaScript</h2> <h2>VBScript</h2> <h1>XML tutorials</h1> <h2>XML</h2> <h2>XSL</h2> </body>
效果:
了解更多可参考:https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Counters
三、使用
1、清除浮动
清除浮动方法有多种,现在最常用的就是下面这种方法,仅需要以下样式即可在元素尾部自动清除浮动
.cf:before, .cf:after { content: " "; display: table; } .cf:after { clear: both; } .cf { *zoom: 1; }
2、模拟float:center的效果
float没有center这个取值,但是可以通过伪类来模拟实现。
这个效果实现很有意思,左右通过::before float各自留出一半图片的位置,再把图片绝对定位上去。
核心css如下:
#page-wrap { width: 60%; margin: 40px auto; position: relative; } #logo { position: absolute; top: 0; left: 50%; margin-left: -125px; } #l, #r { width: 49%; } #l { float: left; } #r { float: right; } #l:before, #r:before { content: ""; width: 125px; height: 250px; } #l:before { float: right; } #r:before { float: left; }
完整代码如下:
出自:https://css-tricks.com/float-center/
3、做出各种图形效果
举例:一个六角星
#star-six的div是一个正三角行,#star-six::after是一个倒三角形,通过绝对定位,调整其位置即可实现六角星的效果。
点我查看更多。
4、不使用图片创建小图标
举例:比如一个电话
很巧妙的应用一个div左border加圆角当机身,::before和::after配合圆角当听筒。
<style type="text/css"> #phone{width:50px;height:50px;border-left:6px solid #EEB422;border-radius:20%;transform:rotate(-30deg);-webkit-transform:rotate(-30deg);margin:20px;margin-right:0px;position:relative;display: inline-block;top: -5px;} #phone:before{width:15px;height:15px;background:#EEB422;border-radius: 20%;content: "";position: absolute;left:-2px;top: 1px;} #phone:after{width:15px;height:15px;background:#EEB422;border-radius: 20%;content: "";position: absolute;left:-3px;top: 34px;} </style> <div id="wraper"> <div id="phone"></div> </div>
更多图标:
<!doctype html> <html> <head> <title>伪类标签使用</title> </head> <style type="text/css"> #wraper{padding:10px;width:380px;height:380px;border:3px solid #ccc;margin:auto;} #power{width: 30px;height: 30px;margin:20px;border: 6px solid #EEB422;border-radius: 50%;position: relative;display: inline-block;} #power:before{width:7px;height:22px;background:#EEB422;position: absolute;left:8px;top:-13px;content: "";border: 3px solid #fff;} #play{width: 30px;height: 30px;margin:20px;border: 6px solid #EEB422;border-radius: 50%;position:relative;display: inline-block;background: #EEB422;} #play:before{border:11px solid transparent;border-left:17px solid #fff;content: "";position: absolute;left:9px;top: 3px;} #pause{width: 30px;height: 30px;margin:20px;border: 6px solid #EEB422;border-radius: 50%;position:relative;display: inline-block;background: #EEB422;} #pause:before{height:20px;width:5px;border:0px solid transparent;border-left:8px solid #fff;border-right:8px solid #fff;content: "";position: absolute;left:4px;top: 5px;} #stop{width: 30px;height: 30px;margin:20px;border: 6px solid #EEB422;border-radius: 50%;position:relative;display: inline-block;background: #EEB422;} #stop:before{height:17px;width:17px;background:#fff;content: "";position: absolute;left:6px;top: 6px;} #comment{width: 50px;height: 25px;margin:20px;border: 6px solid #EEB422;border-radius: 20%;position:relative;display: inline-block;background: #EEB422;} #comment:before{border:10px solid transparent;border-top:10px solid #EEB422;content: "";position: absolute;left:28px;top: 28px;} #comment:after{content: "....";position: absolute;color: #fff;font-size: 26px;top: -10px;left: 2px;} #like{width: 50px;height: 30px;margin:20px;border-radius: 55%;transform:rotate(55deg);-webkit-transform:rotate(55deg);position:relative;display: inline-block;background: #EEB422;} #like:before{width:50px;height:30px;border-radius: 55%;transform:rotate(-110deg);-webkit-transform:rotate(-110deg);background:#EEB422;content: "";position: absolute;left:8px;top: -12px;} #search{width: 20px;height: 20px;border:4px solid #EEB422;border-radius:50%;margin:20px;position:relative;display: inline-block;top: -5px;left: -5px;} #search:before{width:20px;height:5px;background:#EEB422;transform:rotate(45deg);-webkit-transform:rotate(45deg);content: "";position: absolute;left:15px;top: 22px;} #home{width: 30px;height: 30px;background:#EEB422;margin:20px;position:relative;display: inline-block;top: 5px;} #home:before{width:6px;height:12px;background:#fff;content: "";position: absolute;left:12px;top: 20px;} #home:after{border:25px solid transparent;border-bottom:20px solid #EEB422;content: "";position: absolute;top: -38px;left:-10px;} #photo{width:40px;height:30px;background:#EEB422;margin:20px;position:relative;display: inline-block;top: 5px;} #photo:before{width:13px;height:13px;border:4px solid #fff;border-radius:50%;background:#EEB422;content: "";position: absolute;left:10px;top: 5px;} #photo:after{width:15px;height:10px;background:#EEB422;content: "";position: absolute;top: -7px;left:13px;} #photo{width:40px;height:30px;background:#EEB422;margin:20px;position:relative;display: inline-block;top: 5px;} #email{width:50px;height:35px;background:#EEB422;margin:20px;position:relative;display: inline-block;top: 5px;} #email:before{border:25px solid transparent;border-top:20px solid #fff;content: "";position: absolute;left:0px;top: 2px;} #email:after{border:25px solid transparent;border-top:20px solid #EEB422;content: "";position: absolute;top:0px;} #file{width:30px;height:45px;border:4px solid #EEB422;margin:20px;position:relative;display: inline-block;top: 5px;} #file:before{border:10px solid #fff;border-right:10px solid #EEB422;border-bottom:10px solid #EEB422;content: "";position: absolute;left:-4px;top: -4px;} #file:after{width:20px;height:5px;border-top:3px solid #EEB422;border-bottom:3px solid #EEB422;content: "";position: absolute;left: 5px;top: 25px;} #history{width:35px;height:35px;border:4px solid #EEB422;border-radius: 50%;margin:20px;position:relative;display: inline-block;top: 5px;} #history:before{width:14px;height:14px;border-bottom:4px solid #EEB422;border-left:4px solid #EEB422;content: "";position: absolute;left:14px;top: 3px;} #video{width:50px;height:35px;background:#EEB422;border-radius: 20%;margin:20px;position:relative;display: inline-block;top: -5px;} #video:before{width:6px;height:6px;border:11px solid transparent;border-right:11px solid #EEB422;content: "";position: absolute;left:35px;top: 4px;} #video:after{width:10px;height:10px;border:6px solid transparent;border-top:6px solid #EEB422;border-left:6px solid #EEB422;transform:rotate(45deg);-webkit-transform:rotate(45deg);content: "";position: absolute;left:13px;top: 35px;} #tags{width:50px;height:25px;background:#EEB422;border-radius: 35% 0% 0% 35%;transform:rotate(45deg);-webkit-transform:rotate(45deg);margin:20px;margin-left:35px;position:relative;display: inline-block;top: -5px;} #tags:before{width:10px;height:10px;border-radius:50%;background:#fff;content: "";position: absolute;left:7px;top: 7px;} #phone{width:50px;height:50px;border-left:6px solid #EEB422;border-radius:20%;transform:rotate(-30deg);-webkit-transform:rotate(-30deg);margin:20px;margin-right:0px;position:relative;display: inline-block;top: -5px;} #phone:before{width:15px;height:15px;background:#EEB422;border-radius: 20%;content: "";position: absolute;left:-2px;top: 1px;} #phone:after{width:15px;height:15px;background:#EEB422;border-radius: 20%;content: "";position: absolute;left:-3px;top: 34px;} #profile{width: 40px;height:15px;background:#EEB422;border-radius: 45% 45% 0 0;margin:20px;position:relative;display: inline-block;top: 0px;} #profile:before{width: 20px;height:22px;background:#EEB422;border-radius:40%;content: "";position: absolute;left: 10px;top: -22px;} </style> <body> <div id="wraper"> <div id="power"></div> <div id="play"></div> <div id="pause"></div> <div id="stop"></div> <div id="comment"></div> <div id="like"></div> <div id="search"></div> <div id="home"></div> <div id="photo"></div> <div id="email"></div> <div id="file"></div> <div id="history"></div> <div id="video"></div> <div id="tags"></div> <div id="phone"></div> <div id="profile"></div> </div> </body> </html>
这个效果来自:http://www.w3cfuns.com/blog-5444604-5402127.html
有大神用伪元素创建了84种小图标,具体可查看http://nicolasgallagher.com/pure-css-gui-icons/
5、显示打印网页的URL
<style> @media print { a[href]:after { content: " (" attr(href) ") "; } } </style><body> <a href="http://www.baidu.com">百度</a> </body>
6、给blockquote添加引号
经常用到给blockquote 引用段添加巨大的引号作为背景,可以用 ::before 来代替 background 。好处是即可以给背景留下空间,还可以直接使用文字而非图片:
<meta charset="utf-8"/> <style type="text/css"> blockquote::before { content: open-quote; color: #ddd; z-index: -1; font-size:80px; } </style> <blockquote>引用一个段落,双引号用::before伪元素实现</blockquote>
7、超链接特效
举例:配合 CSS定位实现一个鼠标移上去,超链接出现方括号的效果
<meta charset="utf-8" /> <style type="text/css"> body{ background-color: #425a6c; } a { position: relative; display: inline-block; outline: none; color: #fff; text-decoration: none; font-size: 32px; padding: 5px 20px; } a:hover::before, a:hover::after { position: absolute; } a:hover::before { content: "\5B"; left: -10px; } a:hover::after { content: "\5D"; right: -10px; } </style> <a>鼠标移上去出现方括号</a>
更多创意链接特效可参考: Creative Link Effects 。
8、::before和::after实现多背景图片
举例:一个标签应用5张背景图
原效果来自:Multiple Backgrounds and Borders with CSS 2.1
这个效果看的真的是脑洞大开,虽然多背景图用css3的background-image很容易就能实现。但是这篇文章是10年写的,已经过去5年了,想想也正是他们这样的尝试和努力才加速了css3标准的制定,让今天的开发更easy。今天的我们又能为5年后的开发人员做些什么贡献呢?
本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/4459991.html有问题欢迎与我讨论,共同进步。
link 与 @import之对比
页面中使用CSS的方式主要有3种:行内添加定义style属性值,页面头部内嵌调用和外面链接调用,其中外面引用有两种:link和@import。外部引用CSS两种方式link和@import的方式分别是:
XML/HTML代码
<link rel="stylesheet" rev="stylesheet" href="CSS文件" type="text/css" media="all" />
XML/HTML代码
<style type="text/css" media="screen">
@import url("CSS文件");
</style>
两者都是外部引用CSS的方式,但是存在一定的区别:
区别1:link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。
区别2:link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。
区别3:link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。
区别4:ink支持使用Javascript控制DOM去改变样式;而@import不支持。
补充:@import最优写法
@import的写法一般有下列几种:
@import 'style.css' //Windows IE4/ NS4, Mac OS X IE5, Macintosh IE4/IE5/NS4不识别
@import "style.css" //Windows IE4/ NS4, Macintosh IE4/NS4不识别
@import url(style.css) //Windows NS4, Macintosh NS4不识别
@import url('style.css') //Windows NS4, Mac OS X IE5, Macintosh IE4/IE5/NS4不识别
@import url("style.css") //Windows NS4, Macintosh NS4不识别
由上分析知道,@import url(style.css) 和@import url("style.css")是最优的选择,兼容的浏览器最多。从字节优化的角度来看@import url(style.css)最值得推荐。
转自http://www.cnblogs.com/zbo/archive/2010/11/17/1879590.html
学习前端前必知的——HTTP协议详解
前端人士必备的知识点,无论你是否有经验,看了此文绝对有收获
此文针对前端爱好者,前端求职者(话说面试时很容易考到哦)
原文参考博客园http://kb.cnblogs.com/page/130970/#statecode
什么是HTTP协议
协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器
目前我们使用的是HTTP/1.1 版本
Web服务器,浏览器,代理服务器
当我们打开浏览器,在地址栏中输入URL,然后我们就看到了网页。 原理是怎样的呢?
实际上我们输入URL后,我们的浏览器给Web服务器发送了一个Request, Web服务器接到Request后进行处理,生成相应的Response,然后发送给浏览器, 浏览器解析Response中的HTML,这样我们就看到了网页,过程如下图所示
我们的Request 有可能是经过了代理服务器,最后才到达Web服务器的。
过程如下图所示
代理服务器就是网络信息的中转站,有什么功能呢?
1. 提高访问速度, 大多数的代理服务器都有缓存功能。
2. 突破限制, 也就是FQ了
3. 隐藏身份。
URL详解
URL(Uniform Resource Locator) 地址用于描述一个网络上的资源, 基本格式如下
schema://host[:port#]/path/.../[;url-params][?query-string][#anchor]
scheme 指定低层使用的协议(例如:http, https, ftp)
host HTTP服务器的IP地址或者域名
port# HTTP服务器的默认端口是80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/
path 访问资源的路径
url-params
query-string 发送给http服务器的数据
anchor- 锚
URL 的一个例子
http://www.mywebsite.com/sj/test;id=8079?name=sviergn&x=true#stuff
Schema: http
host: www.mywebsite.com
path: /sj/test
URL params: id=8079
Query String: name=sviergn&x=true
Anchor: stuff
HTTP协议是无状态的
http协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系,对http服务器来说,它并不知道这两个请求来自同一个客户端。 为了解决这个问题, Web程序引入了Cookie机制来维护状态.
HTTP消息的结构
先看Request 消息的结构, Request 消息分为3部分,第一部分叫请求行, 第二部分叫http header, 第三部分是body. header和body之间有个空行, 结构如下图
第一行中的Method表示请求方法,比如"POST","GET", Path-to-resoure表示请求的资源, Http/version-number 表示HTTP协议的版本号
当使用的是"GET" 方法的时候, body是为空的
比如我们打开博客园首页的request 如下
GET http://www.cnblogs.com/ HTTP/1.1
Host: www.cnblogs.com
我们用Fiddler 捕捉一个博客园登录的Request 然后分析下它的结构, 在Inspectors tab下以Raw的方式可以看到完整的Request的消息, 如下图
我们再看Response消息的结构, 和Request消息的结构基本一样。 同样也分为三部分,第一部分叫request line, 第二部分叫request header,第三部分是body. header和body之间也有个空行, 结构如下图
HTTP/version-number表示HTTP协议的版本号, status-code 和message 可另行了解
我们用Fiddler 捕捉一个博客园首页的Response然后分析下它的结构, 在Inspectors tab下以Raw的方式可以看到完整的Response的消息, 如下图
Get和Post方法的区别
Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET,POST,PUT,DELETE. 一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,改,增,删4个操作。 我们最常见的就是GET和POST了。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息.
我们看看GET和POST的区别
1. GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中.
2. GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
3. GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。
4. GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.
状态码
Response 消息中的第一行叫做状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。
状态码用来告诉HTTP客户端,HTTP服务器是否产生了预期的Response.
HTTP/1.1中定义了5类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别
1XX 提示信息 - 表示请求已被成功接收,继续处理
2XX 成功 - 表示请求已被成功接收,理解,接受
3XX 重定向 - 要完成请求必须进行更进一步的处理
4XX 客户端错误 - 请求有语法错误或请求无法实现
5XX 服务器端错误 - 服务器未能实现合法的请求
看看一些常见的状态码
200 OK
最常见的就是成功响应状态码200了, 这表明该请求被成功地完成,所请求的资源发送回客户端
如下图, 打开博客园首页
302 Found
重定向,新的URL会在response中的Location中返回,浏览器将会使用新的URL发出新的Request。
例如在IE中输入http://www.google.com. HTTP服务器会返回304, IE取到Response中Location header的新URL, 又重新发送了一个Request.
304 Not Modified
代表上次的文档已经被缓存了, 还可以继续使用,
例如打开博客园首页, 发现很多 Response 的status code 都是304
提示: 如果你不想使用本地缓存可以用Ctrl+F5强制刷新页面
400 Bad Request 客户端请求与语法错误,不能被服务器所理解
403 Forbidden 服务器收到请求,但是拒绝提供服务
404 Not Found
请求资源不存在(输错了URL)
比如在IE中输入一个错误的URL, http://www.cnblogs.com/tesdf.aspx
500 Internal Server Error 服务器发生了不可预期的错误
503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常
HTTP Request header
使用Fiddler 能很方便的查看Reques header, 点击Inspectors tab -> Request tab -> headers 如下图所示.
header 有很多,比较难以记忆,我们也按照Fiddler那样把header 进行分类,这样比较清晰也容易记忆。
Cache 头域
If-Modified-Since
作用: 把浏览器端缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中。
例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT
实例如下图
If-None-Match
作用: If-None-Match和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时,将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag. 使用这样的机制将提高网站的性能
例如: If-None-Match: "03f2b33c0bfcc1:0"
实例如下图
Pragma
作用: 防止页面被缓存, 在HTTP/1.1版本中,它和Cache-Control:no-cache作用一模一样
Pargma只有一个用法, 例如: Pragma: no-cache
注意: 在HTTP/1.0版本中,只实现了Pragema:no-cache, 没有实现Cache-Control
Cache-Control
作用: 这个是非常重要的规则。 这个用来指定Response-Request遵循的缓存机制。各个指令含义如下
Cache-Control:Public 可以被任何缓存所缓存()
Cache-Control:Private 内容只缓存到私有缓存中
Cache-Control:no-cache 所有内容都不会被缓存
还有其他的一些用法, 我没搞懂其中的意思, 请大家参考其他的资料
Client 头域
Accept
作用: 浏览器端可以接受的媒体类型,
例如: Accept: text/html 代表浏览器可以接受服务器回发的类型为 text/html 也就是我们常说的html文档,
如果服务器无法返回text/html类型的数据,服务器应该返回一个406错误(non acceptable)
通配符 * 代表任意类型
例如 Accept: */* 代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)
Accept-Encoding:
作用: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate),(注意:这不是只字符编码);
例如: Accept-Encoding: gzip, deflate
Accept-Language
作用: 浏览器申明自己接收的语言。
语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等;
例如: Accept-Language: en-us
User-Agent
作用:告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.
我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上,服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。
例如: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)
Accept-Charset
作用:浏览器申明自己接收的字符集,这就是本文前面介绍的各种字符集和字符编码,如gb2312,utf-8(通常我们说Charset包括了相应的字符编码方案);
例如:
Cookie/Login 头域
Cookie:
作用: 最重要的header, 将cookie的值发送给HTTP 服务器
Entity头域
Content-Length
作用:发送给HTTP服务器数据的长度。
例如: Content-Length: 38
Content-Type
作用:
例如:Content-Type: application/x-www-form-urlencoded
Miscellaneous 头域
Referer:
作用: 提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的,比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。
例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT
Transport 头域
Connection
例如: Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
例如: Connection: close 代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。
Host(发送请求时,该报头域是必需的)
作用: 请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的
例如: 我们在浏览器中输入:http://www.guet.edu.cn/index.html
浏览器发送的请求消息中,就会包含Host请求报头域,如下:
Host:http://www.guet.edu.cn
此处使用缺省端口号80,若指定了端口号,则变成:Host:指定端口号
HTTP Response header
同样使用Fiddler 查看Response header, 点击Inspectors tab ->Response tab-> headers 如下图所示
我们也按照Fiddler那样把header 进行分类,这样比较清晰也容易记忆。
Cache头域
Date
作用: 生成消息的具体时间和日期
例如: Date: Sat, 11 Feb 2012 11:35:14 GMT
Expires
作用: 浏览器会在指定过期时间内使用本地缓存
例如: Expires: Tue, 08 Feb 2022 11:35:14 GMT
Vary
作用:
例如: Vary: Accept-Encoding
Cookie/Login 头域
P3P
作用: 用于跨域设置Cookie, 这样可以解决iframe跨域访问cookie的问题
例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR
Set-Cookie
作用: 非常重要的header, 用于把cookie 发送到客户端浏览器, 每一个写入cookie都会生成一个Set-Cookie.
例如: Set-Cookie: sc=4c31523a; path=/; domain=.acookie.taobao.com
Entity头域
ETag
作用: 和If-None-Match 配合使用。 (实例请看上节中If-None-Match的实例)
例如: ETag: "03f2b33c0bfcc1:0"
Last-Modified:
作用: 用于指示资源的最后修改日期和时间。(实例请看上节的If-Modified-Since的实例)
例如: Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT
Content-Type
作用:WEB服务器告诉浏览器自己响应的对象的类型和字符集,
例如:
Content-Type: text/html; charset=utf-8
Content-Type:text/html;charset=GB2312
Content-Type: image/jpeg
Content-Length
指明实体正文的长度,以字节方式存储的十进制数字来表示。在数据下行的过程中,Content-Length的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。
例如: Content-Length: 19847
Content-Encoding
WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。
例如:Content-Encoding:gzip
Content-Language
作用: WEB服务器告诉浏览器自己响应的对象的语言者
例如: Content-Language:da
Miscellaneous 头域
Server:
作用:指明HTTP服务器的软件信息
例如:Server: Microsoft-IIS/7.5
X-AspNet-Version:
作用:如果网站是用ASP.NET开发的,这个header用来表示ASP.NET的版本
例如: X-AspNet-Version: 4.0.30319
X-Powered-By:
作用:表示网站是用什么技术开发的
例如: X-Powered-By: ASP.NET
Transport头域
Connection
例如: Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
例如: Connection: close 代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。
Location头域
Location
作用: 用于重定向一个新的位置, 包含新的URL地址
实例请看304状态实例
HTTP协议是无状态的和Connection: keep-alive的区别
无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。
HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。
从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。
深入了解——CSS3新增属性
目录
CSS3 选择器(Selector)
写过 CSS 的人应该对 CSS 选择器不陌生,我们所定义的 CSS 属性之所以能应用到相应的节点上,就是因为 CSS 选择器模式。参考下述代码:
清单 1. CSS 选择器案例
Body > .mainTabContainer div > span[5]{ Border: 1px solod red; Background-color: white; Cursor: pointer; }
此处的 CSS 选择器即:“body > .mainTabContainer div span[5]” 代表这这样一条路径:
1. “body”标签直接子元素里 class 属性值为“mainTabContainer”的所有元素 A
2. A 的后代元素(descendant)里标签为 div 的所有元素 B
3. B 的直接子元素中的第 5 个标签为 span 的元素 C
这个 C 元素(可能为多个)即为选择器定位到的元素,如上的 CSS 属性也会全部应用到 C 元素上。
以上为 CSS2 及之前版本所提供的主要定位方式。现在,CSS3 提供了更多更加方便快捷的选择器:
清单 2. CSS3 选择器案例
1 Body > .mainTabContainer tbody:nth-child(even){ 2 Background-color: white; 3 } 4 5 Body > .mainTabContainer tr:nth-child(odd){ 6 Background-color: black; 7 } 8 9 10 :not(.textinput){ 11 Font-size: 12px; 12 } 13 14 Div:first-child{ 15 Border-color: red; 16 }
如上所示,我们列举了一些 CSS3 的选择器,在我们日常的开发中可能会经常用到,这些新的 CSS3 特性解决了很多我们之前需要用 JavaScript 脚本才能解决的问题。
1. tbody: nth-child(even), nth-child(odd):此处他们分别代表了表格(tbody)下面的偶数行和奇数行(tr),这种样式非常适用于表格,让人能非常清楚的看到表格的行与行之间的差别,让用户易于浏览。tbody为语义化标签
2. : not(.textinput):这里即表示所有 class 不是“textinput”的节点。同时:not(也可包含伪元素如:empty)
div:first-child:这里表示所有 div 节点下面的第一个直接子节点。
除此之外,还有很多新添加的选择器:
E:nth-last-child(n) E:nth-of-type(n) E:nth-last-of-type(n) E:last-child E:first-of-type E:only-child E:only-of-type E:empty E:checked E:enabled E:disabled E::selection E:not(s)
这里不一一介绍。深入了解
@Font-face 特性
Font-face 可以用来加载字体样式,而且它还能够加载服务器端的字体文件,让客户端显示客户端所没有安装的字体。
先来看一个客户端字体简单的案例:
清单 3. Font-face 客户端字体案例
<p><font face="arial">arial courier verdana</font></p>
我们可以通过这种方式直接加载字体样式,因为这些字体(arial)已经安装在客户端了。清单 3 这种写法的作用等同于清单 4:
清单 4. 字体基本写法
<p><font style="font-family: arial">arial courier verdana</font></p>
相信这种写法大家应该再熟悉不过了。
接下来我们看看如何使用服务端字体,即:未在客户端安装的字体样式。
参看如下代码:
清单 5. Font-face 服务端字体案例
@font-face { font-family: BorderWeb; src:url(BORDERW0.eot); } @font-face { font-family: Runic; src:url(RUNICMT0.eot); } .border { FONT-SIZE: 35px; COLOR: black; FONT-FAMILY: "BorderWeb" } .event { FONT-SIZE: 110px; COLOR: black; FONT-FAMILY: "Runic" }
清单 5 中声明的两个服务端字体,其字体源指向“BORDERW0.eot”和“RUNICMT0.eot”文件,并分别冠以“BorderWeb”和“Runic”的字体名称。声明之后,我们就可以在页面中使用了:“ FONT-FAMILY: "BorderWeb" ” 和 “ FONT-FAMILY: "Runic" ”。
这种做法使得我们在开发中如果需要使用一些特殊字体,而又不确定客户端是否已安装时,便可以使用这种方式。
Word-wrap & Text-overflow 样式
Word-wrap
先来看看 word-wrap 属性,参考下述代码:
清单 6. word-wrap 案例
<div style="width:300px; border:1px solid #999999; overflow: hidden"> wordwrapbreakwordwordwrapbreakwordwordwrapbreakwordwordwrapbreakword </div> <div style="width:300px; border:1px solid #999999; word-wrap:break-word;"> wordwrapbreakwordwordwrapbreakwordwordwrapbreakwordwordwrapbreakword </div>
比较上述两段代码,加入了“word-wrap: break-word”,设置或检索当当前行超过指定容器的边界时是否断开转行,文字此时已被打散。所以可见如下的差别:
图 1. 没有 break-word
图 2. 有 break-word
Text-overflow
知道了 word-wrap 的原理,我们再来看看 text-overflow,其实它与 word-wrap 是协同工作的,word-wrap 设置或检索当当前行超过指定容器的边界时是否断开转行,而 text-overflow 则设置或检索当当前行超过指定容器的边界时如何显示,见如下示例:
清单 7. Text-overflow 案例
.clip{text-overflow:clip; overflow:hidden; white-space:nowrap; width:200px;background:#ccc;} .ellipsis{text-overflow:ellipsis; overflow:hidden; white-space:nowrap; width:200px; background:#ccc;} <div class="clip"> 不显示省略标记,而是简单的裁切条 </div> <div class="ellipsis"> 当对象内文本溢出时显示省略标记 </div>
如清单 7 所示,这里我们均使用“overflow: hidden”,对于“text-overflow”属性,有“clip”和“ellipsis”两种可供选择。见图 3 的效果图。
图 3. Text-overflow 效果图
这里我们可以看到,ellipsis 的显示方式比较人性化,clip 方式比较传统,我们可以依据需求进行选择。
文字渲染(Text-decoration)
CSS3 里面开始支持对文字的更深层次的渲染,我们来看看下面的例子:
清单 8. Text-decoration 案例
div { -webkit-text-fill-color: black; -webkit-text-stroke-color: red; -webkit-text-stroke-width: 2.75px; }
这里我们主要以 webkit 内核浏览器为例,清单 8 的代码效果如图 4:
图 4. Text-decoration 效果图
Text-fill-color: 文字内部填充颜色
Text-stroke-color: 文字边界填充颜色
Text-stroke-width: 文字边界宽度
CSS3 的多列布局(multi-column layout)
CSS3 现在已经可以做简单的布局处理了,这个 CSS3 新特性又一次的减少了我们的 JavaScript 代码量,参考如下代码:
清单 9. CSS3 多列布局
.multi_column_style{ -webkit-column-count: 3; -webkit-column-rule: 1px solid #bbb; -webkit-column-gap: 2em; } <div class="multi_column_style"> ................. ................. </div>
这里我们还是以 webkit 内核浏览器为例:
Column-count:表示布局几列。
Column-rule:表示列与列之间的间隔条的样式
Column-gap:表示列于列之间的间隔
清单 9 的代码效果图如图 5:
图 5. 多列布局效果图
颜色
css1和css2只能通过以下三种方式来表示颜色
- 颜色名称
eg:color:red
- HEX方式
(语法:#RRGGBB或#RGB 各点的取值范围为00-FF)
- RGB方式
(语法:RGB(R,G,B) 各点的取值范围为0~255或者0%~200%)
css3针对上述模式不能表示透明,增加了如下表示方法
-
RGBA模式
语法:RGBA(R,G,B,A) R红色 G绿色 B蓝色 A透明
各点取值跟RGB类似 A的取值为0~1之间
eg:rgba(255,0,0,0.5)表示半透明红色
- HSL模式(色轮模式)
语法:HSL(H,S,L) H色调 S饱合度 L亮度
H取值为0~360之间 其中0或者360表示红色 120表示绿色 240表示蓝色
S和L取值都是0%到100%之间
- HSLA模式
语法及各点取值跟HSL模式一下,唯一不同在于后面的A表示透明度
eg:hsl(360,50%,50%,0.5) 红色
其次在css3中可以使用color:transparent和使用滤镜filter:alpha(opacity=50) (不过滤镜仅仅限于IE)
清单 10. 圆角案例
border-radius: 15px;
参见下面圆角效果:
Figure xxx. Requires a heading
CSS3 的渐变效果(Gradient)
线性渐变
左上(0% 0%)到右上(0% 100%)即从左到右水平渐变:
清单 13. 左到右的渐变
background-image:-webkit-gradient(linear,0% 0%,100% 0%,from(#2A8BBE),to(#FE280E));
这里 linear 表示线性渐变,从左到右,由蓝色(#2A8BBE)到红色(#FE280E)的渐变。效果图如下:
图 6. 简单线性渐变效果图
同理,也可以有从上到下,任何颜色间的渐变转换:
图 7. 各种不同线性渐变效果图
还有复杂一点的渐变,如:水平渐变,33% 处为绿色,66% 处为橙色:
清单 14. 复杂线性渐变
background-image:-webkit-gradient(linear,0% 0%,100% 0%,from(#2A8BBE), color-stop(0.33,#AAD010),color-stop(0.33,#FF7F00),to(#FE280E));
这里的“color-stop”为拐点,可见效果图:
图 8. 复杂线性渐变效果图
径向渐变
接下来我们要介绍径向渐变(radial),这不是从一个点到一个点的渐变,而从一个圆到一个圆的渐变。不是放射渐变而是径向渐变。来看一个例子:
清单 15. 径向渐变(目标圆半径为 0)
backgroud: -webkit-gradient(radial,50 50,50,50 50,0,from(black),color-stop(0.5,red),to(blue));
前面“50,50,50”是起始圆的圆心坐标和半径,“50,50,0”蓝色是目标圆的圆心坐标和半径,“color-stop(0.5,red)”是断点的位置和色彩。这里需要说明一下,和放射由内至外不一样,径向渐变刚好相反,是由外到内的渐变。清单 15 标识的是两个同心圆,外圆半径为 50px,内圆半径为 0,那么就是从黑色到红色再到蓝色的正圆形渐变。下面就是这段代码的效果:
图 9. 径向渐变(目标圆半径为 0)效果图
如果我们给目标源一个大于 0 半径,您会看到另外一个效果:
清单 16. 径向渐变(目标圆半径非 0)
backgroud: -webkit-gradient(radial,50 50,50,50 50,10,from(black),color-stop(0.5,red),to(blue));
这里我们给目标圆半径为 10,效果图如下:
图 10. 径向渐变(目标圆半径非 0)
您可以看到,会有一个半径为 10 的纯蓝的圆在最中间,这就是设置目标圆半径的效果。
现在我再改变一下,不再是同心圆了,内圆圆心向右 20px 偏移。
清单 17. 径向渐变(目标圆圆心偏移)
backgroud: -webkit-gradient(radial,50 50,50,70 50,10,from(black),color-stop(0.5,red),to(blue));
这里我们给目标圆半径还是 10,但是圆心偏移为“70,50”(起始圆圆心为“50,50”)效果图如下:
图 11. 径向渐变(目标圆圆心偏移)
想必您明白原理了,我们可以做一个来自顶部的漫射光,类似于开了盏灯:
清单 18. 径向渐变(漫射光)
backgroud:-webkit-gradient(radial,50 50,50,50 1,0,from(black),to(white));
其效果如下:
图 12. 径向渐变(漫射光)
CSS3 的阴影(Shadow)和反射(Reflect)效果
首先来说说阴影效果,阴影效果既可用于普通元素,也可用于文字,参考如下代码:
清单 19. 元素和文字的阴影
.class1{ text-shadow:5px 2px 6px rgba(64, 64, 64, 0.5); } .class2{ box-shadow:3px 3px 3px rgba(0, 64, 128, 0.3); }
设置很简单,对于文字阴影:表示 X 轴方向阴影向右 5px,Y 轴方向阴影向下 2px, 而阴影模糊半径 6px,颜色为 rgba(64, 64, 64, 0.5)。其中偏移量可以为负值,负值则反方向。元素阴影也类似。参考一下效果图:
图 13. 元素和文字的阴影效果图
接下来我们再来谈谈反射,他看起来像水中的倒影,其设置也很简单,参考如下代码:
清单 20. 反射
.classReflect{ -webkit-box-reflect: below 10px -webkit-gradient(linear, left top, left bottom, from(transparent), to(rgba(255, 255, 255, 0.51))); }
设置也很简单,大家主要关注“-webkit-box-reflect: below 10px”,他表示反射在元素下方 10px 的地方,再配上渐变效果,可见效果图如下:
图 14. 反射效果图
CSS3 的背景效果
CSS3 多出了几种关于背景(background)的属性,我们这里会简单介绍一下:
首先:“Background Clip”,该属确定背景画区,有以下几种可能的属性:
* background-clip: border-box; 背景从 border 开始显示 ;
* background-clip: padding-box; 背景从 padding 开始显示 ;
* background-clip: content-box; 背景显 content 区域开始显示 ;
* background-clip: no-clip; 默认属性,等同于 border-box;
通常情况,我们的背景都是覆盖整个元素的,现在 CSS3 让您可以设置是否一定要这样做。这里您可以设定背景颜色或图片的覆盖范围。
其次:“Background Origin”,用于确定背景的位置,它通常与 background-position 联合使用,您可以从 border、padding、content 来计算 background-position(就像 background-clip)。
* background-origin: border-box; 从 border. 开始计算 background-position;
* background-origin: padding-box; 从 padding. 开始计算 background-position;
* background-origin: content-box; 从 content. 开始计算 background-position;
还有,“Background Size”,常用来调整背景图片的大小,注意别和 clip 弄混,这个主要用于设定图片本身。有以下可能的属性:
* background-size: contain; 缩小图片以适合元素(维持像素长宽比)
* background-size: cover; 扩展元素以填补元素(维持像素长宽比)
* background-size: 100px 100px; 缩小图片至指定的大小 .
* background-size: 50% 100%; 缩小图片至指定的大小,百分比是相对包 含元素的尺寸 .
最后,“Background Break”属性,CSS3 中,元素可以被分成几个独立的盒子(如使内联元素 span 跨越多行),background-break 属性用来控制背景怎样在这些不同的盒子中显示。
* background-break: continuous; 默认值。忽略盒之间的距离(也就是像元 素没有分成多个盒子,依然是一个整体一 样)
* background-break: bounding-box; 把盒之间的距离计算在内;
* background-break: each-box; 为每个盒子单独重绘背景。
这种属性让您可以设定复杂元素的背景属性。
最为重要的一点,CSS3 中支持多背景图片,参考如下代码:
清单 21. 多背景图片
div { background: url(src/zippy-plus.png) 10px center no-repeat, url(src/gray_lines_bg.png) 10px center repeat-x; }
此为同一元素两个背景的案例,其中一个重复显示,一个不重复。参考一下效果图:
图 15. 多背景图片
CSS3 的盒子模型
盒子模型为开发者提供了一种非常灵活的布局方式,但是支持这一特性的浏览器并不多,目前只有 webkit 内核的新版本 safari 和 chrome 以及 gecko 内核的新版本 firefox。
下面我们来介绍一下他是如何工作的,参考如下代码:
清单 22. CSS3 盒子模型
<div class="boxcontainer"> <div class="item"> 1 </div> <div class="item"> 2 </div> <div class="item"> 3 </div> <div class="item flex"> 4 </div> </div>
默认情况下,如果“boxcontainer”和“item”两个 class 里面没有特殊属性的话,由于 div 是块状元素,所以他的排列应该是这样的:
图 16. CSS3 盒子模型效果图
下面,我们加入相关 CSS3 盒子模型属性:
清单 23. CSS3 盒子模型(水平排列)
.boxcontainer { width: 1000px; display: -webkit-box; display: -moz-box; -webkit-box-orient: horizontal; -moz-box-orient: horizontal; } .item { background: #357c96; font-weight: bold; margin: 2px; padding: 20px; color: #fff; font-family: Arial, sans-serif; }
注意这里的“display: -webkit-box; display: -moz-box;”,它针对 webkit 和 gecko 浏览器定义了该元素的盒子模型。注意这里的“-webkit-box-orient: horizontal;”,他表示水平排列的盒子模型。此时,我们会看到如下效果:
图 17. CSS3 盒子模型(水平排列)效果图
细心的读者会看到,“盒子”的右侧多出来了很大一块,这是怎么回事呢?让我们再来看一个比较有特点的属性:“flex”, 参考如下代码:
清单 24. CSS3 盒子模型(flex)
<div class="boxcontainer"> <div class="item"> 1 </div> <div class="item"> 2 </div> <div class="item"> 3 </div> <div class="item flex"> 4 </div> </div> .flex { -webkit-box-flex: 1; -moz-box-flex: 1; }
您看到什么区别了没?在第四个“item 元素”那里多了一个“flex”属性,直接来看看效果吧:
图 18. CSS3 盒子模型(flex)效果图
第四个“item 元素”填满了整个区域,这就是“flex”属性的作用。如果我们调整一下“box-flex”的属性值,并加入更多的元素,见如下代码:
清单 25. CSS3 盒子模型(flex 进阶)
<div class="boxcontainer"> <div class="item"> 1 </div> <div class="item"> 2 </div> <div class="item flex2"> 3 </div> <div class="item flex"> 4 </div> </div> .flex { -webkit-box-flex: 1; -moz-box-flex: 1; } .flex2 { -webkit-box-flex: 2; -moz-box-flex: 2; }
我们把倒数第二个元素(元素 3)也加上“box-flex”属性,并将其值设为 2,可见其效果图如下:
图 19. CSS3 盒子模型(flex 进阶)效果图
由此可见,元素 3 和元素 4 按比例“2:1”的方式填充外层“容器”的余下区域,这就是“box-flex”属性的进阶应用。
还有,“box-direction”可以用来翻转这四个盒子的排序,“box-ordinal-group”可以用来改变每个盒子的位置:一个盒子的 box-ordinal-group 属性值越高,就排在越后面。盒子的对方方式可以用“box-align”和“box-pack”来设定。
了解更多爆料
CSS3 的 Transitions, Transforms 和 Animation
Transitions
先说说 Transition,Transition 有下面些具体属性:
transition-property:用于指定过渡的性质,比如 transition-property:backgrond 就是指 backgound 参与这个过渡
transition-duration:用于指定这个过渡的持续时间
transition-delay:用于制定延迟过渡的时间
transition-timing-function:用于指定过渡类型,有 ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier
可能您觉得摸不着头脑,其实很简单,我们用一个例子说明,参看一下如下代码:
清单 26. CSS3 的 Transition
<div id="transDiv" class="transStart"> transition </div> .transStart { background-color: white; -webkit-transition: background-color 0.3s linear; -moz-transition: background-color 0.3s linear; -o-transition: background-color 0.3s linear; transition: background-color 0.3s linear; } .transEnd { background-color: red; }
这里他说明的是,这里 id 为“transDiv”的 div,当它的初始“background-color”属性变化时(被 JavaScript 修改),会呈现出一种变化效果,持续时间为 0.3 秒,效果为均匀变换(linear)。如:该 div 的 class 属性由“transStart”改为“transEnd”,其背景会由白(white)渐变到红(red)。
Transform
再来看看 Transform,其实就是指拉伸,压缩,旋转,偏移等等一些图形学里面的基本变换。见如下代码:
清单 27. CSS3 的 Transform
.skew { -webkit-transform: skew(50deg); } .scale { -webkit-transform: scale(2, 0.5); } .rotate { -webkit-transform: rotate(30deg); } .translate { -webkit-transform: translate(50px, 50px); } .all_in_one_transform { -webkit-transform: skew(20deg) scale(1.1, 1.1) rotate(40deg) translate(10px, 15px); }
“skew”是倾斜,“scale”是缩放,“rotate”是旋转,“translate”是平移。最后需要说明一点,transform 支持综合变换。可见其效果图如下:
图 20. CSS3 的 Transform 效果图
现在您应该明白 Transform 的作用了吧。结合我们之前谈到的 Transition,将它们两者结合起来,会产生类似旋转,缩放等等的效果,绝对能令人耳目一新。
Animation
最后,我们来说说 Animation 吧。它可以说开辟了 CSS 的新纪元,让 CSS 脱离了“静止”这一约定俗成的前提。以 webkit 为例,见如下代码:
清单 28. CSS3 的 Animation
@-webkit-keyframes anim1 { 0% { Opacity: 0; Font-size: 12px; } 100% { Opacity: 1; Font-size: 24px; } } .anim1Div { -webkit-animation-name: anim1 ; -webkit-animation-duration: 1.5s; -webkit-animation-iteration-count: 4; -webkit-animation-direction: alternate; -webkit-animation-timing-function: ease-in-out; }
首先,定义动画的内容,如清单 28 所示,定义动画“anim1”,变化方式为由“透明”(opacity: 0)变到“不透明”(opacity: 1),同时,内部字体大小由“12px”变到“24px”。然后,再来定义 animation 的变化参数,其中,“duration”表示动画持续时间,“iteration-count”表示动画重复次数,direction 表示动画执行完一次后方向的变化方式(如第一次从右向左,第二次则从左向右),最后,“timing-function”表示变化的模式。
其实,CSS3 动画几乎支持所有的 style 变化,可以定义各种各样的动画效果以满足我们用户体验的需要。
这里,我们介绍了 CSS3 的主要的新特性,这些特性在 Chrome 和 Safari 中基本都是支持的,Firefox 支持其中的一部分,IE 和 Opera 支持的较少。读者们可以根据集体情况有选择的使用。
结束语
本文介绍了 Web 开发中关于 CSS3 的一些内容,由浅入深的逐步引出 CSS3 的各种相关属性。基于各个 CSS3 属性的原理,通过实际的源代码介绍各个 CSS3 新特性的特点,使用方式以及使用中需要注意的地方。在每个新特性的代码示例后面,通过示例图,给 Web 开发人员一种比较直观的视觉感受。在 Web2.0 越来越流行的今天,熟练掌握并能很好的运用 CSS3 的一些特性会给我们的项目带来前所未有的用户体验效果。
菜鸟进阶——grunt
开始学习 Grunt
它就是一个工具框架,有很多插件扩展它的功能。
是一套前端自动化工具,基于nodeJS的命令行工具,一般用于:
① 压缩文件
②合并文件
③简单语法检查
Grunt 基于 Node.js ,用 JS 开发,这样就可以借助 Node.js 实现跨系统跨平台的桌面端的操作,例如文件操作等等。此外,Grunt 以及它的插件们,都作为一个 包 ,可以用 NPM 安装进行管理。
所以 NPM 生成的 package.json 项目文件,里面可以记录当前项目中用到的 Grunt 插件,而 Grunt 会调用 Gruntfile.js 这个文件,解析里面的任务(task)并执行相应操作。
如果你对 Node.js、NPM 这些名词不太熟悉,建议先去搜索了解一下,因为下面的命令会涉及到它们,但是本文不会过多介绍。
安装 Grunt
Grunt 依赖 Node.js 所以在安装之前确保你安装了 Node.js。(可在官网上下载)然后开始安装 Grunt。
实际上,安装的并不是 Grunt,而是 Grunt-cli,也就是命令行的 Grunt,这样你就可以使用 grunt 命令来执行某个项目中的 Gruntfile.js 中定义的 task 。但是要注意,Grunt-cli 只是一个命令行工具,用来执行,而不是 Grunt 这个工具本身。
安装 Grunt-cli 需要使用 NPM,使用下面一行即可在全局范围安装 Grunt-cli ,换句话说,就是你可以在任何地方执行 grunt 命令:
npm install -g grunt-cli
需要注意,因为使用 -g 命令会安装到全局,可能会涉及到系统敏感目录,如果用 Windows 的话,可能需要你用管理员权限,如果用 OS X / Linux 的话,你可能需要加上 sudo 命令。
下面我们新建一个项目目录,并新建一些文件,这里我准备了一份很简单的项目,放在了 Github 上,下面操作将以此来操作,你可以下载或者 clone 下来: https://github.com/yujiangshui/gruntxx
生成 package.json 文件
这个 package.json 文件其实是 Node.js 来描述一个项目的文件,JSON 格式。生成这个文件超级简单,推荐用命令行交互式的生成一下:
打开命令行,cd gruntxx
文件夹下面,输入指令 npm init
之后,就出来很多信息,然后开始填写项目名称,填写好了之后回车即可。其实这里你一路回车下去也无妨,但是建议你细细的填一下,不明白的跳过好了。
填写好了之后,查看目录就会发现生成 package.json 文件了,这样就算生成好了。
其实就是一个文件而已,你觉得这种方式麻烦,完全可以新建一个文件,然后将类似下面的代码复制进去,改一下对应选项,保存成 package.json 文件就可以:
{ "name": "my-project-name", "version": "0.1.0", "devDependencies": { } }
最后我生成的代码如下:
{ "name": "gruntxx", "version": "0.0.1", "description": "学习 grunt", "repository": { "type": "git", "url": "https://github.com/yujiangshui/gruntxx.git" }, "author": "Jiangshui", "license": "MIT", "bugs": { "url": "https://github.com/yujiangshui/gruntxx/issues" }, "homepage": "https://github.com/yujiangshui/gruntxx" }
但这时我们还没有在项目文件中安装 Grunt 以及相关任务插件。
安装 Grunt 和所需要的插件
就现在的这个示例项目而言,我打算让 Grunt 帮忙实现下面几个功能:检查每个 JS 文件语法、合并两个 JS 文件、将合并后的 JS 文件压缩、将 SCSS 文件编译、新建一个本地服务器监听文件变动自动刷新 HTML 文件。
差不多就是这些,根据这些任务需求,需要用到:
- 合并文件:grunt-contrib-concat
- 语法检查:grunt-contrib-jshint
- Scss 编译:grunt-contrib-sass
- 压缩文件:grunt-contrib-uglify
- 监听文件变动:grunt-contrib-watch
- 建立本地服务器:grunt-contrib-connect
它们的命名和文档都很规范,因为这些是官方提供的比较常用的插件。这些插件同时都是 NPM 管理的包,比如 grunt-contrib-concat - npm 你也可以在这上面看到用法等。
下面我们就要在这个项目中安装这些插件,执行命令:
npm install grunt --save-dev
表示通过 npm 安装了 grunt 到当前项目,同时加上了 —save-dev 参数,表示会把刚安装的东西添加到 package.json 文件中。不信你打开 package.json 文件看下,是不是多了
"devDependencies": { "grunt": "^0.4.5" }
没错,这个的意思就是当前项目依赖 grunt,后面是它的版本,咱们不用管。如果安装的时候没有添加 —save-dev 参数,这里就不会出现了,你需要自行添加上去。
下面我们来安装 Grunt 的插件,当然,不需要一个个的安装,太麻烦了,我们可以:
npm install --save-dev grunt-contrib-concat grunt-contrib-jshint grunt-contrib-sass grunt-contrib-uglify grunt-contrib-watch grunt-contrib-connect
等待一大串乱七八糟的下载状态,我们把 grunt 和相关插件都安装好了,不信看下是不是多了一个 node_modules 文件夹?打开看下,里面就是咱们刚安装的插件。
配置 Gruntfile.js 的语法
插件也装好了,开始写任务吧!既然是要程序来读取执行,必要要有一定的语法规范,下面来简单的说一下:
首先要明白,这是一个 JS 文件,你可以写任意的 JS 代码,比如声明一个 对象 来存储一会要写任务的参数,或者是一个变量当作开关等等。
然后,所有的代码要包裹在
module.exports = function(grunt) { ... };
里面。没有为什么。
在这里面的代码,除去你自己写的乱七八糟的 JS,与 Grunt 有关的主要有三块代码:任务配置代码、插件加载代码、任务注册代码。
顾名思义,这三块代码,任务配置代码就是调用插件配置一下要执行的任务和实现的功能,插件加载代码就是把需要用到的插件加载进来,任务注册代码就是注册一个 task,里面包含刚在前面编写的任务配置代码。
这样,就可以用 grunt 来执行注册的一个 task 从而根据任务配置代码调用需要的插件来执行相应的操作。
下面来分别看一下这三块代码的写法。
任务配置代码
grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } });
可以看出,具体的任务配置代码以对象格式放在 grunt.initConfig
函数里面,其中先写了一句 pkg: grunt.file.readJSON('package.json')
功能是读取 package.json 文件,并把里面的信息获取出来,方便在后面任务中应用(例如下面就用了 <%= pkg.name %>
来输出项目名称),这样可以提高灵活性。之后就是 uglify 对象,这个名字是固定的,表示下面任务是调用 uglify 插件的,首先先配置了一些全局的 options 然后新建了一个 build 任务。
也就是说,在 Uglify 插件下面,有一个 build 任务,内容是把 XX.js 压缩输出到 xx.min.js 里面。如果你需要更多压缩任务,也可以参照 build 多写几个任务。
至于怎么写出来 options 里面的参数和 build 里面的参数内容,这才是 grunt 学习的难点,你需要查看每个插件的用法,根据用法来编写任务,可以看下grunt-contrib-uglify 的官方文档,往下面拉你就可以看到参数和使用方法了。
这样,我们就新建了一个基于 uglify 的任务 build,功能是把 src/<%= pkg.name %>.js
压缩输出 build/<%= pkg.name %>.min.js
。
插件加载代码
这个就超级简单了,由于上面任务需要用到 grunt-contrib-uglify,当 grunt-contrib-uglify 安装到我们的项目之后,写下下面代码即可加载:
grunt.loadNpmTasks('grunt-contrib-uglify');
任务注册代码
插件也加载了,任务也布置了,下面我们得注册一下任务,使用
grunt.registerTask('default', ['uglify']);
来注册一个任务。上面代码意思是,你在 default 上面注册了一个 Uglify 任务,default 就是别名,它是默认的 task,当你在项目目录执行 grunt 的时候,它会执行注册到 default 上面的任务。
也就是说,当我们执行 grunt 命令的时候,uglify 的所有代码将会执行。我们也可以注册别的 task,例如:
grunt.registerTask('compress', ['uglify:build']);
如果想要执行这个 task,我们就不能只输入 grunt 命令了,我们需要输入 grunt compress
命令来执行这条 task,而这条 task 的任务是 uglify 下面的 build 任务,也就是说,我们只会执行 uglify 里面 build 定义的任务,而不会执行 uglify 里面定义的其他任务。
这里需要注意的是,task 的命名不能与后面的任务配置同名,也就是说这里的 compress 不能命名成 uglify,这样会报错或者产生意外情况
OK,加上这三块代码,我们的示例 Gruntfile.js 就是这样子的:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
// Default task(s).
grunt.registerTask('default', ['uglify']);
};
这就是官方那个坑爹示例,貌似 uglify 的参数好像不对,反正我之前学习的时候,没法运行这个配置,下面我们来根据示例项目和我们的需求配置一下。
配置 Gruntfile.js
先从简单的入手,我们先来配置一下编译 Scss 文件的 task。先新建一个 Gruntfile.js 文件,把大体的配置结构复制进去:
module.exports = function(grunt) {
var sassStyle = 'expanded';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.registerTask('outputcss',['sass']);
grunt.registerTask('default');
};
应该可以看懂把?这里不再赘述了,我们来根据 Sass 文档,编写一个 Sass 任务 output :
module.exports = function(grunt) {
var sassStyle = 'expanded';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
output : {
options: {
style: sassStyle
},
files: {
'./style.css': './scss/style.scss'
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.registerTask('outputcss',['sass']);
grunt.registerTask('default');
};
意思就是将 ./scss/style.scss
这个文件以 sassStyle 变量存储的方式编译成 根目录下面的 style.css 文件。
下面拿起命令行,cd 到当前文档目录,执行一下 grunt 命令,结果报错 undefined,没错,因为我们的 default task 里面没有定义任何任务,然后执行 grunt outputcss
命令,提示编译 Scss 文件成功,当然前提是你的 Scss 语法正确,如果有问题就不会成功。
下面我们打算先把 src 目录下面的两个 JS 文件合并起来,然后再用 jshint 检测一下是否有语法问题,如果正确,再用 uglify 对合并起来的文件进行压缩。
参照 grunt-contrib-concat 的官方文档,我们可以写出下面的任务:
module.exports = function(grunt) {
var sassStyle = 'expanded';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
output : {
options: {
style: sassStyle
},
files: {
'./style.css': './scss/style.scss'
}
}
},
concat: {
options: {
separator: ';',
},
dist: {
src: ['./src/plugin.js', './src/plugin2.js'],
dest: './global.js',
},
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('outputcss',['sass']);
grunt.registerTask('concatjs',['concat']);
grunt.registerTask('default');
};
执行 grunt concatjs
之后,就会发现根目录多了一个 global.js 文件,里面是两个文件合并起来的。然后类似的继续看 uglify 和 jshint 的文档,我们就可以根据需求写出下面任务:
module.exports = function(grunt) {
var sassStyle = 'expanded';
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
output : {
options: {
style: sassStyle
},
files: {
'./style.css': './scss/style.scss'
}
}
},
concat: {
options: {
separator: ';',
},
dist: {
src: ['./src/plugin.js', './src/plugin2.js'],
dest: './global.js',
},
},
uglify: {
compressjs: {
files: {
'./global.min.js': ['./global.js']
}
}
},
jshint: {
all: ['./global.js']
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('outputcss',['sass']);
grunt.registerTask('concatjs',['concat']);
grunt.registerTask('compressjs',['concat','jshint','uglify']);
grunt.registerTask('default');
};
其中注册了一个 compressjs 任务 grunt.registerTask('compressjs',['concat','jshint','uglify']);
意思就是依次执行 合并、检查、压缩 任务。我们把刚生成的 global.js 文件删掉,在命令行执行 grunt compressjs
任务,结果 jshint 报错了:
未完待续····
$(#form :input)与$(#form input)的区别
相信大家都很奇怪这两者的区别
我从两个方面简单介绍下
1. $("form :input") 返回form中的所有表单对象,包括textarea、select、button等
$("form input")返回form中的所有input标签对象
2. form input 是属于层级选择器(将每一个选择器匹配到的元素合并后一起返回)
form :input是属于表单选择器(匹配所有input,textarea,select,button等)