@LiTAOo
2018-07-28T02:53:00.000000Z
字数 53883
阅读 1928
CSS
mdn
学习笔记
目录
CSS是如何工作的
当浏览器想要呈现一个HTML文档时,会结合其文档内容以及附加在其上的样式信息。处理的过程大致分为两个阶段:
DOM具有类似树状的结构,HTML文档中的每一个元素、属性、文本信息都会成为DOM树状结构中的一个节点。这些节点是按照与其它节点的关系来定义的,如某些节点是另一些节点的父节点;子节点拥有兄弟节点等。
DOM是CSS与HTML文档内容交汇融合的地方。
假设有如下HTML代码:
<p>
Let's use:
<span>Cascading</span>
<span>Style</span>
<span>Sheets</span>
</p>
在DOM中,根据以上代码转化而成的节点关系如下:
P
├─ "Let's use:"
├─ SPAN
| └─ "Cascading"
├─ SPAN
| └─ "Style"
└─ SPAN
└─ "Sheets"
得到由HTML文档转化成的DOM节点后,浏览器开始解析与之相关的CSS信息,并将其加入到DOM中。
如何在HTML中链接CSS信息
通常有三种方式可以使得在HTML链接CSS信息:
外部链接
这种方式是指将CSS信息存放在与HTML相独立的文件中,且文件以.css作为扩展名,在HTML中,通过在头部中使用<link>
对外部的CSS文件进行链接,如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My CSS experiment</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Hello World!</h1>
<p>This is my first CSS example</p>
</body>
</html>
这种方式通常是链接CSS信息的最好的方式;因为不仅一份CSS文件可供多个HTML文档使用,且在修改CSS信息时也十分方便。
内部链接
这种方式是将CSS信息包含在HTML文档中,具体来说就是将CSS信息放入HTML头部中的<style></style>
:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My CSS experiment</title>
<style>
h1 {
color: blue;
background-color: yellow;
border: 1px solid black;
}
p {
color: red;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<p>This is my first CSS example</p>
</body>
</html>
内联链接
这种方式是针对特定的HTML元素添加CSS信息,通过style
属性完成:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My CSS experiment</title>
</head>
<body>
<h1 style="color: blue;background-color: yellow;border: 1px solid black;">Hello World!</h1>
<p style="color:red;">This is my first CSS example</p>
</body>
</html>
需要注意的是,这是最差的一种链接方式,因为这种方式将会造成极差的代码可维护性。不到万不得已的时候,千万不要使用这种方式。
CSS语法基础
CSS语法中最基础的部分由两部分构成:
属性和值一起构成了一条CSS声明;多条CSS声明一起构成了CSS声明块;最终,CSS声明块与选择器一起构成了CSS规则集。
h1 {
colour: blue;
background-color: yellow;
border: 1px solid black;
}
p {
color: red;
}
p, li {
text-decoration: underline;
}
CSS声明
CSS声明的结构如下:
需要注意的是,在CSS声明中无论是属性还是值都是区分大小写的;如果一个属性是未知的或对应的值无效,以此构成的CSS声明会被视为是无效的,在此情况下,CSS会完全忽略该条CSS声明;此外,CSS中的英文拼写是以美式拼写为标准,若把color
拼写为colour
则会被视为错误的拼写。
CSS声明块
CSS声明块的结构如下:
在声明块中,每条声明之间使用;
分隔,最后一条声明可以不添加;
(添加其实是一种更好的习惯)。
CSS选择器和CSS规则集
CSS规则集的结构如下:
作用在CSS声明块前方的对象称为CSS选择器,其作用是为了确定当前CSS声明块想要作用的HTML元素对象。CSS选择器本质上是一种匹配模式,通过定义不同的组合规则,从而选取特定的某个或某组HTML元素,来达到专门设置样式的目的。CSS选择器与CSS声明块一起构成了CSS规则集。
一个HTML元素可能会被多个选择器选中,假设这些选择器所关联的CSS声明块中包含对相同文本特征的不同设置,则最终HTML元素呈现何种状态将根据CSS的级联关系(优先级)确定。
如果在一组选择器中,某个选择器是无效的,那么将忽略该选择器,而该组中剩余的选择器仍有效。
CSS注释
/*This is a piece of CSS comment.*/
CSS简写
一些属性如font
、background
、padding
、border
、margin
等被称为简写属性,因为这些属性在设置对应的值都有一个特点:为了方便,允许将多个不同用途的值设置在同一行内。这样不仅可以节省时间空间,也会使得代码更加精简整洁。
假如有如下设置:
padding-top: 10px;
padding-right: 15px;
padding-bottom: 15px;
padding-left: 5px;
可以简写为:
padding: 10px 15px 15px 5px;
设置的顺序为顺时针(上、右、下、左)
另外的一个例子为:
background-color: red;
background-image: url(bg-graphic.png);
background-position: 10px 10px;
background-repeat: repeat-x;
background-scroll: fixed;
可以简写为:
background: red url(bg-graphic.png) 10px 10px repeat-x fixed;
简单选择器
元素选择器
元素选择器是指直接使用HTML中的元素名作为CSS的选择器以此来选中相应的元素,如:
/* All p elements are red */
p {
color: red;
}
/* All div elements are blue */
div {
color: blue;
}
类选择器
对于HTML元素,有:
<ul>
<li class="first done">Create an HTML document</li>
<li class="second done">Create a CSS style sheet</li>
<li class="third">Link them all together</li>
</ul>
对于CSS选择器来说,有:
/* The element with the class "first" is bolded */
.first {
font-weight: bold;
}
/* All the elements with the class "done" are strike through */
.done {
text-decoration: line-through;
}
需要注意的是,在CSS选择器的书写上,需要在类名前添加.
。
如果某一个HTML元素需要添加多个CSS类选择器,则有:
<p class="base-box warning important">My first paragraph.</p>
ID选择器
在HTML元素方面,需要为元素定义其特有的ID
,如:
<p id="polite"> — "Good morning."</p>
<p id="rude"> — "Go away!"</p>
在CSS选择器方面,需要在元素ID前添加#
以选中特定ID的HTML元素:
#polite {
font-family: cursive;
}
#rude {
font-family: monospace;
text-transform: uppercase;
}
通用选择器
使用*
可以用来指代所有的元素,如下:
* {
padding: 5px;
border: 1px solid black;
background: rgba(255,0,0,0.25)
}
这样产生的作用是会对所有HTML元素产生影响,因为所有的元素都被选中了。
属性选择器
[attr]
:选中所有包含属性attr
的元素,无论attr
为何值。[attr=val]
:选中所有包含属性attr
,且attr
的值等于val
的元素。[attr~=val]
:选中所有包含属性attr
,且attr
的值中包含val
(如有多个值,则val
用空格与其他值进行分隔)的元素。[attr|=val]
:选中所有包含属性attr
,且attr
的值正好是val
或以val-
开头的元素。[attr^=val]
:选中所有包含属性attr
,且attr
的值以val
开头的元素。[attr$=val]
:选中所有包含属性attr
,且attr
的值以val
结尾的元素。[attr*=val]
:选中所有包含属性attr
,且attr
的值包含字符串val
的元素。关于属性选择器的练习,可参考:Attribute selectors.
伪选择器
伪选择器又可分为伪类选择器和伪元素选择器:
伪类选择器
伪类选择器用来选中处于特定状态下的元素,如当一个元素被鼠标指针悬停在其上时,当一个复选框被选中时等;常用的伪类选择器有:
:active :left
:any :link
:checked :not()
:default :nth-child()
:dir() :nth-last-child()
:disabled :nth-last-of-type()
:empty :nth-of-type()
:enabled :only-child
:first :only-of-type
:first-child :optional
:first-of-type :out-of-range
:fullscreen :read-only
:focus :read-write
:focus-within :required
:hover :right
:indeterminate :root
:in-range :scope
:invalid :target
:lang() :valid
:last-child :visited
:last-of-type
伪元素选择器
伪元素选择器可以用来选择与元素相关的部分空间,如元素的第一行,第一个字符,元素之前的空间,元素之后的空间等等,常用的伪元素选择器有:
::after
::before
::first-letter
::first-line
::selection
::backdrop
关于伪元素选择器的示例可参考:Pseudo-classes and pseudo-elements.
选择器组合
当仅用一个选择器来选择元素时,选择情况十分局限,当利用两个选择器并定义它们之间的关系来选择元素时,就能得到多种情况的元素选择。
假设有A,B两个选择器,则如下列表定义了利用A,B进行组合之后形成的元素选择规则:
关于选择器组合的示例,可参考:Combinators and groups of selectors.
CSS属性的值有多种类型,常见的类型包括:数值、百分比、颜色、坐标位置、函数返回值等。
数值
数值类型包括带单位数值和不带单位数值:
带单位值
属于绝对单位的单位有:
一般情况下,使用较多的是px,其它单位不常使用。
属于相对单位的单位有:
<html>
)中一个字体的大小。需要注意的是,使用最频繁且浏览器支持性最好的单位是em,ex,ch、rem不常使用且浏览器支持性没有em高;vw,vh通常用于响应式布局。
不带单位数值
当想要把元素的margin
或padding
设置移除时,最简单有效的方法是:
margin: 0;
另一个使用不带单位数值的例子是文本行间距,相当于是原有基础的倍数:
p {
line-height: 1.5;
}
这样文本行间距就被设置为原来的1.5倍。
百分比
百分比其实也是一种相对数值,它可以用于设置当前元素长度或宽度始终等于父代元素长度或宽度的某个百分比。这样,当父代容器的长宽发生改变时,子元素的长宽也会等比例发生改变,而使用px或em时,其长度或宽度将始终不变。
如:
.boxes:nth-child(2) {
background-color: blue;
width: 75%;
}
百分比的使用通常是为了进行响应式布局,以便在视口尺寸发生改变时,网页内容也能进行相应变化。
颜色
颜色的表示有多种形式,通常称作色彩系统,常用的色彩系统包括:关键字、十六进制数值、RGB、HSL、RGBA/HSLA、不透明度(Opacity)。
关键字
如red、blue、yellow等:
p {
background-color: red;
}
目前大约有165个不同的关键字来代表不同的颜色,详情可参考:full color keyword list.
十六进制数
可用形如#xxxxxx
的形式来代表一种颜色,如:
p:nth-child(1) {
background-color: #ff0000;
}
其中每两位代表RGB中的一种颜色亮度(0-255),从左到右顺序依次表示红色、绿色、蓝色。
RGB
p:nth-child(1) {
background-color: rgb(255,0,0);
}
HSL
p:nth-child(1) {
background-color: hsl(0,100%,50%);
}
从左到右顺序依次是色调(hue)、饱和度(saturation)、亮度(lightness);其中,色调的取值空间为0-360,饱和度和亮度的取值空间都是0-100%。
RGBA and HSLA
在RGB和HSL的基础上增加了透明度,位于最后一项,取值空间为0-1:
p:nth-child(1) {
background-color: rgba(255,0,0,0.5);
}
p:nth-child(2) {
background-color: hsla(240,100%,50%,0.5);
}
不透明度(Opacity)
准确来说,不透明度设置的是整个元素(包括该元素中的所有子元素)的样式,而不只是单纯地设置背景颜色中的不透明度,如:
<p>This paragraph is using RGBA for transparency</p>
<p>This paragraph is using opacity for transparency</p>
若其CSS设置为:
/* Red with RGBA */
p:nth-child(1) {
background-color: rgba(255,0,0,0.5);
}
/* Red with opacity */
p:nth-child(2) {
background-color: rgb(255,0,0);
opacity: 0.5;
}
其效果为:
通过对比可见,由opacity设置的元素,其内部(背景颜色、文字)所有内容的透明度都发生了变化。
针对不同色彩系统的转换,可参考:HSL to RGB / RGB to HSL / Hex Colour Converter.
函数返回值
函数返回值也可以作为CSS属性的值,如之前看到的rgb()
、hsl()
等;其它的一些使用示例如下:
/* calculate the new position of an element after it has been rotated by 45 degress */
transform: rotate(45deg);
/* calculate the new position of an element after it has been moved across 50px and down 60px */
transform: translate(50px, 60px);
/* calculate the computed value of 90% of the current width minus 15px */
width: calc(90%-15px);
/* fetch an image from the network to be used as a background image */
background-image: url('myimage.png');
当多个CSS选择器选中同一个元素时,且当这些选择器所对应的CSS规则中包含对该元素的相同设置(比如都有关于该元素字体或背景颜色的设置)时,此时元素应该选择哪个CSS规则作为最终的样式呢?其实,CSS内部有一套级联(优先级)评判机制,用于解决这样的冲突问题。最终元素的样式主要由CSS级联和CSS继承所决定。
CSS级联
在CSS级联中,哪个选择器所对应的规则会被最终设置到相应的元素上,按重要性从高到低依次取决于三个因素:
在该机制中,首先看能否通过CSS的重要性来确定出结果,若不能,则进一步根据特异性来判别;若还不能判断出结果,最终按照CSS规则的代码声明顺序进行确定。
重要性(importance)
在CSS中,有一条特殊的语句可以保证让你的CSS声明在与其它冲突声明的优先级确定中胜出:!important
例如有如下HTML代码:
<p class="better" id="winning">One selector to rule them all!</p>
假设为其添加CSS代码为:
#winning {
background-color: red;
border: 1px solid black;
}
.better {
background-color: gray;
border: none !important;
}
按照正常情况来说,由于ID选择器(#winning)的优先级比类选择器(.better)的级联优先级要高(后文会得到介绍,现在先当成结论来用),故上述HTML中的段落的背景颜色应该为红色,且被包围在一个具有1px宽的黑色实心边框内;但是,由于在.better
选择器对应的CSS规则中,有border: none !important;
,那么根据重要性>特异性,HTML段落关于border的样式设置最终采用的是border: none
。
需要注意的是,在使用!important
时需要格外小心——不到万不得已的情况下千万不要使用它;因为使用它会打乱CSS级联的正常工作模式,使得在调试CSS问题时变得异常棘手(特别时在比较大型的CSS文件中)。
此外,针对!important
的作用效果还与其所处的文件类型有关——如用户自定义的样式表可以覆盖开发者指定的样式表,这样可以满足用户的一些自定义需求(如近视的用户可能会把字体设置为原来的两倍)
具有冲突的声明其级联优先级将按照以下顺序确定(重要性从低到高):
!important
设置!important
设置特异性(specificity)
特异性主要是用来衡量不同选择器类型的特殊程度——即可以匹配多少元素,例如元素选择器(如p
)在进行选择时,通常可以一次性同时选择到大量的元素,故其特异性较低;而类选择器(如.class)相比较而言,可以选择到的元素较少,故其特异性比元素选择器高;对于ID选择器而言,其一次只能选择到一个元素(因为不同元素无法具有相同的ID),其特异性最高;综上,三者的特异性排序为:ID选择器>类选择器>元素选择器。
CSS选择器的特异性可以通过数值大小进行衡量,假设称其为特异性值。特异性值的计算是通过四种不同的积分进行累加得到的,这四种积分的大小分别是:1000,100,10,1;不同的积分用于指代不同类型的选择器:
style
属性中时,该CSS样式设置的特异性值为1000,否则为0。下图是一个计算选择器特异性值的示例,最左侧是整个选择器的组合方式,最右侧是整个选择器通过计算得出的特异性值:
另外,假设有如下HTML代码:
<div id="outer" class="container">
<div id="inner" class="container">
<ul>
<li class="nav"><a href="#">One</a></li>
<li class="nav"><a href="#">Two</a></li>
</ul>
</div>
</div>
其CSS代码为:
/* specificity: 0101 */
#outer a {
background-color: red;
}
/* specificity: 0201 */
#outer #inner a {
background-color: blue;
}
/* specificity: 0104 */
#outer div ul li a {
color: yellow;
}
/* specificity: 0113 */
#outer div ul .nav a {
color: white;
}
/* specificity: 0024 */
div div li:nth-child(2) a:hover {
border: 10px solid black;
}
/* specificity: 0023 */
div li:nth-child(2) a:hover {
border: 10px dashed black;
}
/* specificity: 0033 */
div div .nav:nth-child(2) a:hover {
border: 10px double black;
}
通过代码注释,可以看到每一个CSS规则集的选择器部分的特异性值。
CSS代码声明顺序
上文中提到,当重要性和特异性都无法确定出CSS样式的设置级联优先级时,最终将会参考CSS代码的顺序;该规则为:后出现的声明将会覆盖先出现的声明。
如:
p {
color: blue;
}
/* This rule will win over the first one */
p {
color: red;
}
CSS规则覆盖问题
在利用CSS级联优先级进行样式覆盖时,需要注意的是覆盖发生在属性(property)级别——具有较高级联优先级的样式属性覆盖低级联的样式属性,而并不是直接替换整个CSS规则。事实上,只要CSS规则匹配到了相应元素,就会把样式叠加到其上,只有当遇到样式设置冲突时,才会使用级联优先级来确定冲突的样式采用何种设置。
比如有如下示例:
<p>I'm <strong>important</strong></p>
其CSS代码为:
/* specificity: 0002 */
p strong {
background-color: khaki;
color: green;
}
/* specificity: 0001 */
strong {
text-decoration: underline;
color: red;
}
由于p strong
和strong
都能匹配到元素<strong>
,所以它们内部的所有样式都会被设置到<strong>
元素上,然而,对于冲突的属性color
,根据级联优先级,将使用p strong
的设置,但其它已设置的样式不会发生改变。
其最终效果为:
CSS继承
对于HTML中的元素来说,会默认继承部分父代的CSS样式,而其它的一些样式则不会被继承。
font-family
、color
等CSS属性而言,子元素默认继承父元素的样式设置通常是较为合理的,这样一来可以直接通过设置<html>
元素的字体类型和字体颜色达到统一设置整个页面的字体和字体颜色的目的,而无需做烦人的单独设置每个元素样式的工作。margin
、padding
、border
、background-image
等,如果子元素默认继承父元素的样式设置就不合理了,因为这样一来就会使得整个页面变得一团糟。如过想要了解哪些CSS属性可以被默认继承而哪些不能,可以参考CSS Reference.
如何人为设置CSS属性继承
CSS提供了4个特殊的通用CSS属性值来指定继承:
initial
会自动变为inherit
。inherit
,否则将被设置为initial
。需要注意的是,initial
和unset
在IE浏览器中不被支持。
统一设置所有CSS属性的继承性
在CSS属性中,有一个特殊的属性——all
,它用于指代所有的CSS属性,可以使用上面介绍的inherit
,initial
,unset
,revert
直接作为all
的属性值以达到统一设置CSS属性的继承性的目的。如all:inherit
表示将所有的CSS属性都设置为继承自父元素。
从CSS的角度来看,每一个HTML元素都可以看做一个矩形的盒子,其内部包括内容(content)、内填充(padding)、边框(border)、外边界(margin),该模型称为盒模型。
盒模型的示意图如下所示:
width
和height
width
和height
用来设置盒内容的宽度和高度,盒内容既可以是元素包含的文本内容,也可以是嵌套在该元素内的子元素的盒模型
padding
padding是指位于内边框和外内容框之间的部分。为了设置其大小,可以使用padding
进行统一设置四边的大小,也可以使用padding-top
、padding-left
、padding-right
、padding-bottom
单独设置。
border
border是指位于外边界内侧与内填充外侧之间的部分。默认情况下,border
的大小为0。为了设置它,可以使用border
属性,如:border: 1px solid black
,这种设置方法会统一设置四边,如果想要单独设置每一边,可以使用border-top
、border-right
、border-bottom
、border-left
。如果只想单独设置某个属性(如宽度、颜色等),可以使用border-width
、border-style
、border-color
。如果只想单独设置某一边的某个属性,可以使用border-top-width
、border-top-style
、border-top-color
等。
margin
margin位于边框的外侧区域,用于分隔该盒模型与其它盒模型,其表现与padding
类似,既可以通过margin
设置,也可以使用margin-top
、margin-left
、margin-right
、margin-bottom
进行设置,需要注意的是,如果两个盒模型相邻且都具有margin
值,则最终在页面上渲染的结果为,两个盒模型之间的间隔为取两者之间margin
较大的值。
可以通过使用box-sizing:border-box
来改变盒模型的类型,默认情况下height
与width
是作用于盒内容的,当使用上述语句时,盒模型将变为:
此时的height
与width
将直接作用于border。
高级的盒模型操作
overflow
如果将元素盒子的大小(即长和宽)设置为固定值,则有可能会遇到元素中的内容所需空间大于指定的元素盒子大小,这时在默认情况下,盒内容会溢出到盒子外面。为了控制该情况下的表现,可以使用overflow
属性,其最常见的值为:
auto
:如果盒内的内容过多,则溢出的部分将被隐藏,并且会出现一个滚动条工具以供读者滚动查看剩余的信息。hidden
:直接将溢出的部分进行隐藏。visible
:当内容过多,则溢出的部分显示在盒模型外(默认情况)其呈现效果依次如下:
background clip
盒模型的背景通常是由背景颜色和背景图片组成的,这两者被附加到盒模型的底部作为背景,可以通过background-color
和background-image
进行设置。默认情况下,CSS对背景颜色或背景图片的渲染延伸至盒模型的边框(border)外侧,那么,如果想改变这种默认的设置,使其按照自己的意愿只延伸至内容边界时,可以使用background-clip
属性:
假如有如下HTML代码:
<div class="default"></div>
<div class="padding-box"></div>
<div class="content-box"></div>
在其上添加的CSS代码为:
div {
width : 60px;
height : 60px;
border : 20px solid rgba(0, 0, 0, 0.5);
padding: 20px;
margin : 20px 0;
background-size : 140px;
background-position: center;
background-image : url('https://mdn.mozillademos.org/files/11947/ff-logo.png');
background-color : gold;
}
.default { background-clip: border-box; }
.padding-box { background-clip: padding-box; }
.content-box { background-clip: content-box; }
则最终的效果为:
outline
即使outline
看起来与border
类似,但实际上它并不是盒模型的一部分。因此使用它并不会像border
那样改变盒模型的大小,它只是单纯地绘制在盒模型之上的边界轮廓(更具体地说,outline
绘制在盒模型的外边界(border)且位于盒模型的margin区域):
假如有如下CSS代码:
border: 5px solid blue;
outline: 10px dashed red;
其样式效果为:
更多关于outline
的信息,可参考outline-reference.
盒模型的种类
盒模型的种类的种类可以分为:内联型、半内联型、块级型,可以通过CSS属性display
进行指定,对于的属性值分别为:inline
、inline-block
、block
。默认情况下,在HTML中,块级元素如(<p>
、<div>
、<h1>
等)被设置为display:block
,而内联元素如(<span>
、<img>
等)被设置为display:inline
,关于三者在呈现效果上的不同,可以查看如下的示例:
假设如下HTML代码:
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<span class="inline">Mauris tempus turpis id ante mollis dignissim.</span>
Nam sed dolor non tortor lacinia lobortis id dapibus nunc.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<span class="block">Mauris tempus turpis id ante mollis dignissim.</span>
Nam sed dolor non tortor lacinia lobortis id dapibus nunc.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<span class="inline-block">Mauris tempus turpis id ante mollis dignissim.</span>
Nam sed dolor non tortor lacinia lobortis id dapibus nunc.
</p>
其CSS代码如下:
p {
padding : 1em;
border : 1px solid black;
}
span {
border : 1px solid green;
/* That makes the box visible, regardless of its type */
background-color: yellow;
}
.inline { display: inline; }
.block { display: block; }
.inline-block { display: inline-block; }
其各自的样式效果如下:
关于盒模型种类的详细介绍,参考:Types of CSS boxes.
浏览器如何处理出错的CSS规则
使用dev-tools调试CSS错误
以firefox为例,可以在键盘上按下F12
打开开发者工具,可看到如下信息:
其中左下方的区域称为DOM查看器,右下方的区域包含的内容称为CSS规则,每当在DOM查看器中选中并点击一个元素时,在CSS规则域中就会显示出与该元素相关的所有CSS样式设置信息。这样的信息十分有用,特别是当出现一个无效的CSS声明时,在CSS规则域中会使用一条删除线对其进行标注以表明该条声明没有对当前元素产生作用,且在声明的后方还会给出警告的标志,如下所示:
另外,在CSS规则查看区域的每条CSS声明的前方,都具有一个复选框来供开发者选择是否使能该条CSS声明,该功能将十分有助于调试。
使用W3C CSS验证工具进行CSS语法检查
与HTML一样,W3C也提供了CSS的验证工具以供检查CSS的语法错误:W3C-CSS Validator.
其界面如下所示:
与HTML验证一样,CSS验证同样支持三种输入方式:
需要注意的是,这种方式提供的错误检测功能十分有限,只能进行简单的语法错误检查。不过一般可用在对大型CSS文件使用开发者工具进行详细检查之前的简单语法检查,这样可以事先排除那些基础的语法错误。
color
使用color
属性来设置元素内容的前景颜色(一般为内部的文字,不过也包括下划线和上划线等),如:
p {
color: red;
}
Font families
该属性可以用于设置文本的字体类型,其值可以为一个或多个字体类型。浏览器将会依次对指定的字体类型进行检查,直到选择出第一个被浏览器本身支持的字体类型,然后应用到当前文本上。如果font-family
所指定的字体类型浏览器都不支持,则浏览器对文本将会采取默认的字体设置,关于font-family
的简单使用如下:
p {
font-family: arial;
}
Web safe fonts
当谈到文本字体的使用时,就不得不提及字体的可用性。在进行网页制作时,应该确保文本使用的字体能被尽量多的浏览器或操作系统支持,否则将会产生较差的用户体验。幸运的是,存在一些通用的字体类型,它们在各种操作系统(Windows,Mac,Linux,Android,iOS)下都具有良好的支持性。这样的字体类型称为web安全字体。
常见的web安全字体及其说明如下:
更一般的是,如果我们无法确定某些web安全字体在Windows或Mac系统上的支持性,可以参考cssfontstack.com.
默认字体
CSS定义了5个通用的内置字体类型:serif
,sans-serif
,monospace
,cursive
,fantasy
;需要注意的是serif
,sans-serif
,monospace
字体类型的表现较为稳定且可预测,而cursive
,fantasy
在不同的浏览器或操作系统中的表现相对不稳定,因此在使用它们的时候应该小心,至少应该先对其效果进行测试以保证万无一失。
以上5种字体类型的介绍如下所示:
Font stacks
正因为在为文本设置字体类型时无法确保其可用性,因此可以考虑设置多个备用类型以供浏览器选择:
p {
font-family: "Trebuchet MS", Verdana, sans-serif;
}
一个比较好的实践方法是,通常在font-family
值的末尾添加一个CSS通用的字体类型;这样如果之前的字体类型都无法使用时,至少还有可用的字体类型。
需要注意的是,如果字体类型名超过一个单词,如Trebuchet MS
,此时应该将其放在双引号内,如"Trebuchet MS"
。
字体大小
可以通过font-size
属性来设置字体大小,其支持的单位包括:em
,rem
,px
等,其使用的示例为:
html {
font-size: 10px;
}
h1 {
font-size: 2.6rem;
}
p {
font-size: 1.4rem;
color: red;
font-family: Helvetica, Arial, sans-serif;
}
Font style
font-style
用于控制文本的倾斜,可取值如下(一般比较少用到,可能会用于取消HTML设置的倾斜效果)
normal
:将文本设置为正常字体(取消倾斜)italic
:将文本设置为相应字体的倾斜字体,如果相应字体没有斜体字体,那么将会使用oblique
来模拟字体的斜体。oblique
:单纯地将正常字体倾斜来代表(模拟)其斜体状态。Font weight
font-weight
用于设置文本的粗体,常用的取值如下(事实上基本只会用到bold
和normal
)
normal
,bold
:正常或加粗文本lighter
,bolder
:设置当前元素文本的粗体比父元素更小/大一些100
-900
:利用数值范围更加精细地控制文本地粗体程度Text transform
text-transform
使得字体可以根据需要进行变形,常用的值包括:
none
: 失能变形uppercase
:将所有的英文字母变为大写lowercase
:将所有的英文字母变为小写capitalize
:将每个单词的第一个字母大写full-width
:将所有的字形变换为形如w r i t t e n i n s i d e a f i x e d - w i d t h s q u a r e,这有点类似于等宽字体,它可以使得诸如拉丁文字、中日韩文等字形进行对齐。Text decoration
text-decoration
用于设置/取消设置在字体上的装饰(你可能常用于取消链接默认自带的下划线),常用的取值如下:
none
:取消现在已有的所有文本装饰underline
:对文本添加下划线overline
:对文本添加上划线line-through
:对文本添加删除线需要注意的是text-decoration
可以一次性接受多个值,比如text-decoration:underline overline
;另外text-decoration
是一个简记属性,设置的类型包括:text-decoration-line
,text-decoration-style
,text-decoration-color
。
文字阴影
text-shadow可用于为文字添加阴影,如:
text-shadow: 4px 4px 5px red
四个值的作用依次如下:
需要注意的是,对于1和2来说,正值意味着阴影将向右/下偏移,同理,负值将意味着阴影向左/上偏移。另外也可以对text-shadow
设置多组值:
text-shadow: -1px -1px 1px #aaa,
0px 4px 1px rgba(0,0,0,0.5),
4px 4px 5px rgba(0,0,0,0.7),
0px 0px 7px rgba(0,0,0,0.4);
其效果大致如下:
文本对齐
text-align
用于控制文本在盒模型内容中对齐的方式,常用的值包括:
left
:文本左对齐right
:文本右对齐center
:文本居中行高
line-height
用于设置每一行文本的高度,它既可以接受带单位值也可以接受不带单位数值。当接受不带单位的数值是,其表示的意义是用该值乘以当前文本的字体大小得到的值,一般推荐的设置为1.5-2,如:
line-height: 1.5;
字母间距和单词间距
使用letter-spacing
和word-spacing
分别设置字母间距和单词的间距,如:
p::first-line {
letter-spacing: 2px;
word-spacing: 4px;
}
其效果如下所示:
其它值得关注的文本属性
参考Other properties worth looking at,这些属性相比于以上介绍的属性而言更为高级,但也十分有用,适合进阶阶段掌握。
字体简写
众多与字体相关的属性都可以一个font
简写属性进行设置,其顺序依次为:font-style
,font-variant
,font-weight
,font-stretch
,font-size
,line-height
,font-family
其中,font-size
,font-family
是必须的。
另外在font-size
和line-height
之间必须用/
进行分隔:
font: italic normal bold normal 3em/1.5 Helvetica, Arial, sans-serif;
浏览器对列表的默认样式设置
参考示例为Default lists styling.
可以通过开发者工具发现:
<ul>
和<ol>
元素都同时具有一个16px(1em)的上下margin
和40px(2.5em)的左padding
<li>
没有任何的padding
和margin
默认设置<dl>
同时具有一个16px(1em)的上下margin
,但没有任何的padding
设置<dd>
有40px(2.5em)的左margin
<p>
同时具有一个16px(1em)的上下margin
处理列表的间距
当对列表进行样式设置的时候,应该与周围的元素(如<p>
,<img>
等)保持相同的垂直间距和水平间距。具体的做法可以是:
<ol>
,<ul>
,<dl>
中的字体大小设置成与<p>
一致<li>
,<dt>
,<dd>
与<p>
的行高(line-height)保持一致专用于列表的特定设置
在CSS中,有一些专门用于设置列表(<ol>
,<ul>
)的属性,如下:
list-style-type
用于设置列表前小图标的样式和类型,如(方形、圆形、数字、字母、罗马数字等),详情可参考list-style-type,如:
ol {
list-style-type: upper-roman; //罗马数字
}
其效果为:
list-style-position
设置小图标放置的位置(在列表项内部还是在外部,默认为外部),当想将其设置在列表项内部时,有:
ol {
list-style-type: upper-roman;
list-style-position: inside;
}
其效果为:
可以用该图与上图进行对比来查看小图标处在列表项内部和外部的区别。
list-style-image
使用自定义的图片来代替内置的小图标,如:
ul {
list-style-image: url(star.svg);
}
不过使用该属性具有一些限制,那就是无法控制小图标所处的位置和大小等,更好的选择一般是使用background
属性族,如:
ul {
padding-left: 2rem;
list-style-type: none;
}
ul li {
padding-left: 2rem;
background-image: url(star.svg);
background-position: 0 0;
background-size: 1.6rem 1.6rem;
background-repeat: no-repeat;
}
<ul>
中将list-style-type
设置为none
,即列表项前不加载任何默认的小图标。background-image
用于设置自定义的背景图片background-position
用于设置图片出现的位置,其值是一个二维(x,y)坐标,元素空间的左上角为(0,0)background-size
用于设置背景的大小background-repeat
:默认情况下,背景图片会一致不断重复直到填充满整个由background-size
设置的背景区域,但在该情况下,我们只希望它出现一次,所以应该将其设置为no-repeat
通过以上设置,列表的效果为:
list-style
简写
以上提到有关list-style
的属性都可以通过list-style
进行简写,如:
ul {
list-style-type: square;
list-style-image: url(example.png);
list-style-position: inside;
}
与如下写法是完全等价的:
ul {
list-style: square url(example.png) inside;
}
在list-style
中,type
,image
,position
三者的顺序可以任意书写,在默认情况下(不设置其值),三者的默认设置为disc
(圆点)、none
、outside
;如果image
和type
同时设置了,则type
将作为image
的后备(fallback)。
控制有序列表的计数方式
通常可以在HTML中进行设置
起始数字
<ol start="4">
<li>Toast pitta, leave to cool, then slice down the edge.</li>
<li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
<li>Wash and chop the salad.</li>
<li>Fill pitta with salad, humous, and fried halloumi.</li>
</ol>
效果为:
倒序计数
<ol start="4" reversed>
<li>Toast pitta, leave to cool, then slice down the edge.</li>
<li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
<li>Wash and chop the salad.</li>
<li>Fill pitta with salad, humous, and fried halloumi.</li>
</ol>
效果为:
指定数字
<ol>
<li value="2">Toast pitta, leave to cool, then slice down the edge.</li>
<li value="4">Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
<li value="6">Wash and chop the salad.</li>
<li value="8">Fill pitta with salad, humous, and fried halloumi.</li>
</ol>
效果为:
链接的状态
网页中的链接在不同情况下,可能处于的状态有如下5个:
:link
对其进行标记。:visited
进行标记。:hover
标记。Tab
键对链接进行选中,另一种是刚刚用鼠标点击完链接,鼠标还未点击到其它地方。在CSS中通过伪类:Focus
标记。:active
进行标记。链接的默认样式
在浏览器中,如果没有指定链接的样式,那么浏览器将会对其采取默认的样式设置,参考A simple link,可以发现链接的默认样式有如下特点:
focus
状态时,会被一个矩形轮廓线所包围默认的样式可以被如下的CSS属性关闭/改变:
color
用于改变链接文本字体的颜色cursor
用于改变鼠标指针的图案类型text-decoration
用于改变链接中的下划线outline
用于改变链接处于聚焦状态时的矩形轮廓线如何对链接进行样式设置
首先用CSS标记出链接的各个状态:
a {
}
a:link {
}
a:visited {
}
a:focus {
}
a:hover {
}
a:active {
}
需要注意的是,这样书写的顺序很重要,因为某一些状态的效果是在另一些状态的基础上叠加的,比如第一个规则a
将会影响后续所有的规则,另外当链接被active
时,它实际上也是在被hover
的,如果随意打乱该顺序,可能将无法按照你想要的效果进行渲染。为了记住关于链接的规则设定顺序,可以简记为 L o V e F ears H A te.
接下来看一个示例:
有如下HTML代码:
<p>There are several browsers available, such as <a href="#">Mozilla
Firefox</a>, <a href="#">Google Chrome</a>, and
<a href="#">Microsoft Edge</a>.</p
为其添加如下CSS代码:
body {
width: 300px;
margin: 0 auto;
font-size: 1.2rem;
font-family: sans-serif;
}
p {
line-height: 1.4;
}
a {
outline: none;
text-decoration: none;
padding: 2px 1px 0;
}
a:link {
color: #265301;
}
a:visited {
color: #437A16;
}
a:focus {
border-bottom: 1px solid;
background: #BAE498;
}
a:hover {
border-bottom: 1px solid;
background: #CDFEAA;
}
a:active {
background: #265301;
color: #CDFEAA;
}
其效果可参考Styling links.
关于对该链接设置的CSS规则说明如下:
outline
和text-decoration
用于取消链接的默认样式设置。color
,目的是为了当链接处于link
或visited
状态时,文本颜色不同以作区分。focus
或hover
状态下时,为链接增加了背景颜色和下划线的样式设置,关于此处用border-bottom
实现下划线的方法,有两点需要注意: border-bottom
而不使用text-decoration
的原因是因为border-bottom
设置出的下划线表现更好,具体表现为前者的下划线会显示得更低一些(因为实质上是边框),这样产生的下划线不会截断一些字母(如y和g)下图是使用text-decoration
产生的下划线,可以看到字母p被截断: border-bottom
的值被设置为1px solid
,而并没有为其指定颜色,这样做的好处是,在默认情况下,如果不设置边框的颜色,那么边框的颜色会与文本的颜色保持一致。这样在链接处于不同状态时,当文本颜色变化,下划线的颜色也会随之变化。active
状态时,为链接设置一个醒目的样式。 为链接添加图标
为链接添加图标可以对当前的链接产生修饰和解释的作用,当链接是一条外部链接时,可以使用外部链接图标对该链接进行修饰,如:
为了实现这样的效果,首先先添加HTML代码:
<p>For more information on the weather, visit our <a href="http://#">weather page</a>,
look at <a href="http://#">weather on Wikipedia</a>, or check
out <a href="http://#">weather on Extreme Science</a>.</p>
然后为其添加CSS代码:
body {
width: 300px;
margin: 0 auto;
font-family: sans-serif;
}
p {
line-height: 1.4;
}
a {
outline: none;
text-decoration: none;
padding: 2px 1px 0;
}
a:link {
color: blue;
}
a:visited {
color: purple;
}
a:focus, a:hover {
border-bottom: 1px solid;
}
a:active {
color: red;
}
a[href*="http"] {
background: url('https://mdn.mozillademos.org/files/12982/external-link-52.png') no-repeat 100% 0;
background-size: 16px 16px;
padding-right: 19px;
}
我们将注意力放到最后一条规则上(之前的规则已经介绍过作用):通过使用background
简写属性完成了图标的添加,首先设置了图片的路径,然后将其声明为no-repeat
以便其只出现一次,然后指定其出现的水平位置位于<a>
元素盒模型的区域的最右侧(关于百分比的计算公式为(容器宽度-图片宽度)×百分比),然后在垂直方向上距离顶部0px。
随后通过background-size
为图标指定大小,指定固定大小以后,如果传入的图片比该尺寸大,则浏览器会自动缩放和剪裁图片以匹配该尺寸。但是如果是在IE9浏览器之前,只能人工进行操作。
最后,通过padding-right
为该图标安排一个19px宽的空间。
将链接的样式设置为按钮
在浏览网站时,能经常看到网页都具有导航栏,导航栏中包含一个个矩形的选项,用于在网页之间跳转,其外观大致如Styling links as buttons所示,实际上,其本质就是由一个个链接组成的列表项再加以CSS进行修饰达到的效果,为了设计出这样的样式,首先添加HTML代码:
<ul>
<li><a href="#">Home</a></li><li><a href="#">Pizza</a></li><li><a href="#">Music</a></li><li><a href="#">Wombats</a></li><li><a href="#">Finland</a></li>
</ul>
随后是CSS代码:
body,html {
margin: 0;
font-family: sans-serif;
}
ul {
padding: 0;
width: 100%;
}
li {
display: inline;
}
a {
outline: none;
text-decoration: none;
display: inline-block;
width: 19.5%;
margin-right: 0.625%;
text-align: center;
line-height: 3;
color: black;
}
li:last-child a {
margin-right: 0;
}
a:link, a:visited, a:focus {
background: yellow;
}
a:hover {
background: orange;
}
a:active {
background: red;
color: white;
}
关于该CSS代码的作用如下:
<ul>
元素自带的padding
(左padding)并且将<ul>
的宽度设置为外部容器宽度的100%(即<body>
)<li>
元素在默认情况下是block
元素,在本例中,我们需要将多个<li>
放在同一行,所以我们需要将<li>
的盒模型类型改为inline
<a>
是inline
元素,但我们既想要设置它的高度和宽度,又想将它们放在同一行内,所以应该将其改为inline-block
margin-right
设置为空白,但这时有一个问题,最后一个链接空间将不够,因为它也被设置了0.625%的右margin,这时需要取消,否则它只能被放置到第二行。line-height: 3
即16px * 3= 48px.另外需要注意到一个极其容易被忽视的细节:在HTML中,我们将所有的<li>
都写在了同一行,且互相之间没有空格和换行;这样做的目的是,因为我们在CSS中将<li>
设置成了inline
元素,在HTML中,对于inline
元素之间,如果存在空格或换行,那么最终在页面显示时,会在它们之间产生一个空格。
Font families回顾
之前提到过,为了在网页中添加字体,可以在CSS中使用属性font-family
,该属性可以取多个值,并且浏览器会依次检查给出的每个值,直到找出第一个浏览器所在操作系统支持的字体,并以此来设置文字的字体,其使用方法如下:
p {
font-family: Helvetica, "Trebuchet MS", Verdana, sans-serif;
}
这样有关字体的工作方式虽然好,但是一般对于网络开发者来说,可以选择的字体类型还是十分有限的。因为目前只有少数的一些字体能够确保在各个常用的操作系统上拥有较好的兼容性,也就是所谓的Web安全字体。关于font-family
的值比较好的声明顺序是:优先声明想要尝试的字体类型,然后是可替代的Web安全字体,最后是系统的默认字体。但是这样一来通常会增加在网页开发过程中测试各个字体是否表现良好的时间开销。
Web字体
基于上述的问题,有一种绝佳的替代方案,那就是Web字体,且这种机制可以支持到IE6,其工作方式是利用CSS的特性,允许将字体存放在专门的文件(字体文件)中,然后在CSS中指定该文件的路径,使得网页和字体文件一同被浏览器加载(就像图片的加载方式一般)。这样一来,只要是支持Web字体功能的浏览器都能够渲染出你想要的字体类型。接下来将详细介绍该工作方式的使用方法:
首先,需要添加一个@font-face
块到CSS文件内容的起始位置,它的作用是指定了将要被加载的字体文件信息:
@font-face {
font-family: "myFont";
src: url("myFont.ttf");
}
其中的font-family
指代的是你为该字体类型的命名,src
表指代了对应字体文件的路径。
之后便可以在CSS中使用该字体:
html {
font-family: "myFont", "Bitstream Vera Serif", serif;
}
关于Web字体需要牢记的重点是:
.ttf
、WOFF/WOFF2
等),因此出于良好的跨浏览器支持性考虑,需要提供为同一种字体类型提供多种不同格式的字体文件Web字体使用实践
寻找字体
字体通常是被字体代工厂制作的,并且被存储为多种文件格式,通常有三种类型的网站可以获取到字体:
以Font Squirrel为例,打开该网站选择自己想要的字体(可以通过左侧的FIND FONTS
栏进行关键词标记以过滤字体种类),随后点击下载:
随后解压得到的ZIP压缩包(Web字体通常以压缩包的形式提供,内部包含了该字体的使用许可和字体文件),你可能在解压获得的文件夹中找到多个字体文件,这是同一种字体的不同变体(如小粗、中粗、斜体等):
选择一种你需要的变体即可。
生成不同的Web字体文件格式
进入Fontsquirrel 网站对应的Webfont Generator,选择上传字体文件Upload Fonts
,同意条款后点击下载Download your kit
,随后将其解压,放到与CSS和HTML文件路径相同的目录下;在该文件夹下,包含的内容有:
.tff
、.woff
、.woff2
等)@font-face
代码块将Web字体添加到自己的网页中
stylesheet.css
文件,将里面的@font-face
代码块复制到自己网页的CSS文件内容的顶端url()
包含的路径名,加上存放Web字体文件目录的名字
font-family: 'zantrokeregular', serif;
使用在线字体提供服务
前面提到了Google Font
,接下来将介绍如何使用其提供的字体:
+
号Family Selected
栏<link>
元素到HTML的<head>
中,并且该<link>
最好放在现有的所有<link>
之前
font-family: 'Gaegu', cursive;
@font-face
语法详解
参考@font-face in more detail.
盒模型属性使用注意事项
height
不像width
那样可以接受百分数作为其值,当对其使用百分数时,不会产生任何效果;height
只对特定的值起作用(如px
,em
,rem
等),另外,默认情况下(不指定height
的值)盒模型的高度总是等于其内容(box content)的高度。border
同height
一样,也不接受百分数值。margin
的较大值(称为margin collapsing)高级盒模型属性
对于盒模型的内容尺寸来说,如果不想指定其尺寸为特定值,而只想给其尺寸大小一个范围约束的话,可以使用min-width
,max-width
,min-height
,max-height
。
关于这些属性的使用,一个典型的情况是:将当前盒模型内容的宽度设定为其父元素盒模型内容的某个特定的百分数,但是在随着父元素盒模型内容尺寸变化的同时,又不想让当前元素盒模型内容过大或过小,此时就可以使用min-width
和max-width
进行约束,如:
width: 70%;
max-width: 1280px;
min-width: 480px;
通常还可以搭配另一条语句一起使用,可以使当前元素出于父元素盒模型内容的居中位置:
margin: 0 auto;
还有一个关于图片或视频元素的使用示例,当使用如下设置时,可以进行响应式布局:
display: block;
margin: 0 auto;
max-width: 100%;
背景是如何规定的
content
),padding
,border
区域下方的区域。默认情况下,元素的背景延伸至元素的外边框(border
),但是可以通过background-clip
进行修改margin
区域下方,因为margin
并不算作元素的一部分,它是存在与元素外的区域。background-color
background-color
的默认值不是white
而是transparent
background-color
常用来作为background-image
或background
等属性的后备内容(fallback)background-image
使用方法:
background-image: url(https://mdn.mozillademos.org/files/13026/fire-ball-icon.png);
关于background-image
属性的使用,需要牢记于心的是,该属性的使用不带有任何语义色彩,只是纯属为了装饰作用;带有语义的是HTML中的<img>
。
background-repeat
background-repeat
指定背景图片将以何种方式进行平铺(重复),默认情况下的取值是repeat
,即同时以水平方向和垂直方向平铺背景图片直到占满整个元素背景空间;该属性的常用取值及对应的效果如下:
no-repeat
:只会被显示一次 repeat-x
:在水平方向平铺直到占满整个元素背景空间 repeat-y
:在垂直方向上平铺直到占满整个元素背景空间 repeat
:同时在水平方向和垂直方向上进行平铺直到占满整个元素背景空间 background-position
background-position
用于指定背景图片在元素背景区域出现的位置,通常该属性需要两个值,分别指定水平方向上的位置(x)和垂直方向上的位置(y),需要注意的是,元素背景区域的左上角为坐标原点(0,0),该属性可以接受的值为:
//absolute values
background-position: 200px 25px
//relative values
background-position: 20rem 2.5rem
//percentage
background-position: 90% 25%
//keywords
background-position: right center
其中需要注意的点有:
right
,left
,center
,top
,bottom
background-position
只有一个值,那么该值将被认为是用来设置水平方向位置的值,垂直方向上会被设置为center
background-gradients
background-image
除了指定背景图片,也有额外的用法,那就是颜色渐变,其作用是可以使得背景被设置为一个颜色逐渐变化的背景色,其中一种就是线性渐变,可以通过linear-gradient()
函数实现:
background-image: linear-gradient(to bottom, orange, yellow);
linear-gradient()
函数最少需要3个参数:第一个是用来指定颜色变化的方向,如上例从背景的顶部朝着背景的底部进行渐变;第二个参数用来指定初始时刻的颜色;第三个参数用来指定最后时刻的颜色。
关于第一个参数,除了使用to bottom
,to right
,to left
之类的关键词,也可以使用角度(0°
代表顶部,90°
代表右侧,360°
又回到顶部)。
也可以在指定颜色时,在其后方添加额外的信息,称为颜色停止:
background-image: linear-gradient(to bottom, yellow, orange 40%, yellow);
意思是,首先从黄色开始向底部渐变,当到达距离元素背景顶部40%高度时,渐变为橘色,当到达元素背景底部时,又渐变回黄色。(颜色停止也可使用em
,rem
,px
)
如果想要重复效果的颜色渐变,可以使用repeating-linear-gradient()
函数:
background-image: repeating-linear-gradient(to right, yellow, orange 25px, yellow 50px);
该代码定义了一个总宽度为50px的颜色渐变,该渐变将一直重复直到整个元素背景的宽度被填满。
background-attachment
针对于背景的操作,我们还可以用background-attachment
来指定背景将如何根据内容的滚动而变化,其可取值为:
scroll
:整个页面滚动时,元素的背景会随之滚动,当元素的内容滚动时,背景不受影响fixed
:无论页面还是元素内容滚动,背景都不会滚动local
:无论页面还是元素内容滚动时,背景都会随之滚动为了形象地看出它们的区别,可参考:background-attachment.html.
background简写
以上介绍的所有与背景相关的属性都可以由background
统一设置,如:
background: yellow linear-gradient(to bottom, orange, yellow) no-repeat left center scroll;
任何没有被指定到的值,将被设置成其默认值,若想知道相关属性的默认值以及background
属性可以指定哪些与背景相关的属性,参考background.
多背景
在一个元素上,不是只能为其指定单一的背景,而是可以指定多个,如下:
background: url(image.png) no-repeat 99% center,
url(background-tile.png),
linear-gradient(to bottom, yellow, #dddd00 50%, orange);
background-color: yellow;
需要注意的是,如果需要为元素指定多个背景,则指定背景的顺序需要格外小心,否则可能不会按照自己所想的效果呈现;背景设置的机制是:各个背景相互堆叠到其它背景上,第一个背景堆在第二个上,第二个堆在第三个上,以此类推。
当多背景特性被引入前,普遍的做法是利用<div>
来实现:
<div class="background1">
<div class="background2">
<div class="background3">
<p>My content</p>
</div>
</div>
</div>
因此为了兼容旧版本的IE,恐怕只能使用这种方式。
background-size
使用background-size
来指定背景的尺寸大小,如:
background-image: url(myimage.png);
background-size: 16px 16px;
background-size
的值中,第一个用于指定背景的水平方向尺寸,第二个用于指定背景的垂直方向尺寸。
border回顾
border可以简写以进行统一设置:
border: 2px solid red;
border可以进行单独设置:
border-top
,border-bottom
,border-left
,border-right
border-width
,border-style
,border-color
border-top-width
,border-top-style
,border-top-color
等默认情况下,如果在设置border时,只指定了style
,如:
border: solid;
则width
会被设置为3px,color
会被设置成与元素文本相同的颜色。
border radius
使用border-radius属性来实现圆角边框,效果如下:
border-radius
使用语法如下:
//同时设置四个角的圆半径(x和y方向都为20px)
border-radius: 20px;
//左上(右下)的圆半径(x和y方向都为20px),右上(左下)的圆半径(x和y方向都为10px)
border-radius: 20px 10px;
//左上:20px,右上(左下):10px,右下:50px
border-radius: 20px 10px 50px;
//左上,右上,右下,左下
border-radius: 20px 10px 50px 0;
border-radius
不仅可以接受px
单位的值,也可以接受rem
,em
,百分比单位的值,不过需要特别注意的是,当使用百分比时,此时边框角的圆半径x和y会分开计算,公式为:
x=元素水平尺寸(包括content,padding,border)× 百分比
y=元素垂直尺寸(包括content,padding,border)× 百分比
如:
border-radius: 10%;
之前设置border-radius
时,圆半径的x和y都是相同的,如果想单独设置x和y,则使用/
分隔:
//四个角的圆半径x=10px,y=20px
border-radius: 10px / 20px;
//左上(右下)圆半径:x=10px,y=20px 右上(左下)圆半径:x=30px,y=40px
border-radius: 10px 30px / 20px 40px;
//左上:x=10px,y=20px 右上:x=30px,y=40px 右下:x=10px,y=50px 左下:x=20px,y=40px
border-radius: 10px 30px / 20px 40px 50px;
//四个角:x=40%,y=20%
border-radius: 40% / 20%;
border-image
如果想为边框设置图案,光靠border
属性自带的样式是不够的,这时需要使用border-image
属性:
首先准备好3×3或4×4或5×5网格状的边框图,如下:
border-image-source: url(border-image.png);
浏览器拿到该图后,会将其分成8块(不算中间的空白):
2中切割的方法取决于切割尺寸的设置(用border-image-slice
设置),假设整个图片是160px × 160px,则按上图的方法切割的话,应该设置:
border-image-slice: 40;
被切割出来的8个部分会被自动设置到元素的边框的对应位置(四个角对应于边框的四个角,上、下、左、右会被用来以伸缩或重复的方式填满元素边框的四条边)
为边框图案预留出位置:
border: 30px solid black;
background-clip: padding-box
使用border-image-repeat
指定切割出来的四条边的图案将以何种方式来充填元素的边框,可取的值有:
stretch
:直接进行伸缩来充填边框: repeat
:直接按切割出来的图案进行平铺以充满边框,不过一般情况会出现图案碎片: round
:将切割出来的图案进行平铺以充满边框,为了保持美观会进行适当伸缩: space
:将切割出来的图案进行平铺以充满边框,为了保持美观会引入空白: 一般情况下,strecth
不推荐使用,使用的比较多的是round
因此,关于border-image
的所有设置可以写成:
border: 20px solid black;
background-clip: padding-box;
border-image-source: url(https://mdn.mozillademos.org/files/13060/border-image.png);
border-image-slice: 40;
border-image-repeat: round;
另外也可以使用border-image
进行简写:
border-image: url(border-image.png) 40 round;
参考Styling tables.
关于表格的样式设置,要点有:
1. 使得表格被标记得越简单越好,为了增强其自适应性,可以考虑多使用百分比。
2. 使用table-layout: fixed
使得表格的表现更可控,其效果是可以使得表格中单元格(<tbody>
)的宽度设置依照第一行中头部单元格的宽度设置。
3. 使用border-collapse: collapse
使表格的边框更简单好看。
4. 在HTML中,使用<thead>
,<tbody>
,<tfoot>
对表格的不同内容进行分类,这样在CSS设置样式时,能够更加轻松
5. 使用斑马条纹区分表格主体(<tbody>
)的每一行
6. 使用text-align
对<th>
和<td>
中的文本进行对齐。
Flexbox的作用
在以前,可供进行CSS布局且具有良好跨浏览器兼容性的技术为浮动(float)和定位,通常它们都能较好地解决布局问题,但一旦遇到某些特定的布局需求时,将会变得捉襟见肘,比如如下一些简单的布局需求对它们来说要么不便实现,要么根本做不到:
Flexbox可以使得以上布局变得更加简单
使元素成为flexible box
如果想要一些元素成为flexible box,则只需在包含它们的容器(父元素)上添加属性:
display: flex;
该属性的作用是使得当前元素的所有直接子元素成为flex item;如果希望内联子元素也成为flex item,则可使用inline-flex
作为display
的值
flex模型说明
当元素们作为flexible boxes进行摆放时,它们通常以两个轴作为参考,如下图:
display:flex
的父元素称为flex container。flex-direction
flex-direction
用于设置主轴方向是水平方向还是竖直方向(作用对象为flex container);默认情况下,其值为row
(水平方向),若想改成竖直方向,可以设置为:
flex-direction: column;
不仅如此,还可以设置flex items摆放的方向为水平或竖直的反方向:row-reverse
和column-reverse
。
flex-wrap
当在flex container中摆放flex items时会出现一个问题,如果container的大小固定,随着flex items的不断增多,最终会导致溢出,从而破坏整个布局,如下:
为了解决这个问题,使用(作用对象为flex container):
flex-wrap: wrap;
该属性的作用是可以指定flex items究竟是被强制放在一行内(假设主轴是row
)还是可以允许将溢出的部分放到多行内,默认情况下flex-wrap
为nowrap
,即强制放在一行中,而wrap
则允许将flex items放到多行:
flex-flow简写
以上提到的flex-direction
和flex-wrap
可以通过flex-flow
进行简写,如:
flex-direction: row;
flex-wrap: wrap;
与
flex-flow: row wrap;
等价。
flex items尺寸的灵活性
位于flex container中同一行(假设主轴是row
)的各flex item通过比例的方式来划分大小,通过在各flex item上设置flex
(作用对象为flex item)来指定,如:
flex: 1;
它表示占该空间的1份;假设有A,B,C三个处于同一行的flex item,分别对它们设置:
A {
flex: 1;
}
B {
flex: 1;
}
C {
flex: 2;
}
则这样设置的意思是,将整行空间平均分成1+1+2=4份,A占1份,B占1份,C占2份;其各自所占空间的比例为:1/4,1/4,2/4=1/2;
不过需要特别注意的是,该空间的分配是在事先除去各个flex item所需的padding和margin的基础上进行分配的,举个例子:假设整行的宽度有1000px,A,B,C都含有10px的padding和margin,则A,B,C按以上的比例分配,A(B)的空间为:(1000 - 3 * 40) / 4 + 40(padding + margin)= 260px;同理C的空间为220 * 2 + 40 = 480px。
另外,可以为每个flex item指定最小尺寸,如:
A {
flex: 1 100px;
}
B {
flex: 1 200px;
}
C {
flex: 2 200px;
}
其执行的过程为等价于“首先为各个flex item分配所需的padding和margin,随后先为A分配100px的宽度,为B分配200px的宽度,为C分配200px的宽度,最后将该行剩余的空间再按比例分配到A,B,C上”。
如此看来,flexbox的真正价值就在于其强大的灵活性/自适应性。
flex简写属性及其对应的单独属性
之前所用到的flex
属性实际上是可以同时设置3个单独属性的简写属性,它们分别是:
flex-grow
类似,其作用是设置按照多大的比例依次从各个flex item中匀出一定空间来腾给溢出的部分,最终使得flex items不溢出container。水平和垂直对齐
可以使用flex相关属性设置flex items在主轴和横轴上的对齐方式,假设有初始布局:
为了改变flex items在横轴上的对齐方式,使用align-items
(作用对象为flex container):
stretch
,表示各flex items在横轴上延伸以充满整个container,如果container在横轴方向上没有特定的尺寸(如没有特定的height),那么会在所有flex item中选出一个高度最大的item,随后所有flex item的高度都会延伸至该高度: center
表示所有的flex item维持它们本身的尺寸,但在横轴方向上居中对齐,这样一来就可以很方便地进行垂直居中: flex-start
和flex-end
在横轴上进行两端对齐,如: 需要注意的是,不仅可以使用align-items
对flex items进行统一设置,也可以使用align-self
(作用于flex item)设置到单个flex item以对align-items
的设置进行覆盖,如:
button:first-child {
align-self: flex-end;
}
其效果为:
为了改变flex items在主轴上的对齐方式,使用justify-content
(作用于flex container)
flex-start
center
居中: space-around
可以将flex items均匀分配在主轴上,并且会在两端留出一定空间: space-between
与space-around
类似,区别是在两端不会留出空间: 改变flex items的顺序
Flexbox同样提供了在不改变源码顺序的情况下如何改变flex items摆放顺序的方法,这是传统的布局方法所无法实现的。
与之相关的属性为order
(作用对象为flex item),如:
button:first-child {
order: 1;
}
order
的使用方法为:
order
都被设置为0order
值,则按源代码声明的顺序摆放order
可以设置成负值什么是网格布局
网格布局允许将一个容器的内部布局成一个具有多行和多列以及它们之间的间隙组成的网格,当定义好网格的整体布局后,就可以将容器内部的元素放置到特定的网格上,网格布局的示意图如下:
定义网格布局
与Flexbox类似,在容器上指定dispaly: grid
即可在该容器上定义出一个网格布局,容器内部的各个直接子元素都将成为grid item:
.container {
display: grid;
}
指定网格布局中每行的网格数及网格大小
使用grid-template-columns
属性(作用于container)即可设置该容器中每一行具有的网格数及网格的尺寸,如:
.container {
display: grid;
grid-template-columns: 200px 200px 200px;
}
即可定义出一个每行具有3个网格,每个网格宽度为200px的网格布局。
使用fr
创建出具有灵活尺寸的网格
除了可以在grid-template-columns
使用绝对单位(px),还可以使用fr
作为单位创建出具有自适应性的网格,如:
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
fr
与flex
中的比例类似,用于将容器中整行的可用空间按比例分配给该行定义的所有网格,如上即将整行可用空间平均分成3等份,分配给3个网格,再如使用如下设置时:
.container {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
}
最终的效果为:
不仅如此,fr
还可以与绝对单位混合使用,假定有:
.container {
display: grid;
grid-template-columns: 100px 2fr 1fr 1fr;
}
则空间分配情况是:先分配出一个100px宽的网格,随后将剩余可用空间按比例再分出3个网格:
指定网格之间的间隙大小
使用grid-column-gap
指定网格列之间的间隙,使用grid-row-gap
指定网格行之间的间隙,或可以使用grid-gap
同时设置两者:
.container {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
grid-gap: 20px;
}
其效果为:
关于grid-gap
使用,需要注意的是:目前在新出的标准中,gap
也可以用来设置间隙,其出现的目的就是可以使得需要设置间隙的地方都可以使用gap
来完成(通用性),不过目前支持该属性的浏览器还比较少,如果想用gap
,出于安全的考虑,应该同时包含gap
和grid-gap
,如:
.container {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
grid-gap: 20px;
gap: 20px;
}
重复进行相同的网格创建
使用repeat()
如下:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr 1fr 2fr);
grid-gap: 20px;
}
在repeat()
函数中,第一个参数是想要重复创建的次数,第二个参数是每一次创建的网格设置列表,按照如上的设置,将会在每行中创建出9个网格,且每个网格的设置为1fr 1fr 2fr 1fr 1fr 2fr 1fr 1fr 2fr
。
隐式及显式创建的网格
通过grid-template-columns
及grid-template-rows
属性设置后在对应方向上创建出的网格称为显式网格,显式网格的特点是其网格大小和每一行/列中的网格数都被显式地定义了。而隐式网格是浏览器为了保持网格布局而自动为多余的元素创建出的网格,隐式网格具有的特点是,由于没有为其指定某一方向上的大小,则在该方向上隐式网格会被设置为auto
,即自动匹配网格中的内容大小。假设只设置了grid-template-columns
,则在水平方向上,所有的网格为显式网格,在竖直方向上为隐式网格。如果只设置了grid-template-rows
,则在水平方向上,所有的网格为隐式网格,在竖直方向上为显式网格。如果同时设置了两者,则所有网格在水平和竖直方向上都是显式网格。不过也可以设置浏览器创建出的隐式网格的尺寸,使用grid-auto-rows
和grid-auto-columns
。为了理解显式网格和隐式网格,假定有CSS:
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
}
则效果为:
此时创建出的网格水平方向上已通过grid-template-columns
进行设置,所以创建出的网格是显式网格,但是在竖直方向上,由于没有设置grid-template-rows
,所以此时创建出的网格为隐式网格,其尺寸在竖直方向上匹配了网格中内容的大小。
为了修改竖直方向上隐式网格的尺寸,添加grid-auto-rows
属性:
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
grid-auto-rows: 100px;
}
但需要特别注意的是,grid-auto-rows
并不能改变该方向上网格仍是隐式网格的事实,要想将隐式网格变为显式网格,还是只能通过grid-template-rows
指定。
minmax()函数
之前提到可以使用grid-auto-rows
来指定浏览器在竖直方向上默认创建出的隐式网格的尺寸,但是使用固定尺寸的网格有一个致命缺陷,即当网格中的内容大于网格尺寸时,将会发生内容溢出的情况;因此,为了既可以指定一定大小的隐式网格尺寸,当网格内容超出指定尺寸时又能使网格大小随之增加时,可以使用如下设置:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
grid-gap: 20px;
}
minmax()
将grid-auto-rows
的尺寸限定在了一个范围:当网格内容不发生溢出时,grid-auto-rows
尺寸为100px,当网格内容发生溢出时,grid-auto-rows
尺寸自动增加以匹配网格内容。
在一行中创建尽可能多的最小尺寸网格
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: minmax(100px, auto);
grid-gap: 20px;
}
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))
的作用为,在容器内的一行中创建尽可能多的最小宽度为200px网格,如果有多余的空间剩余(不足200px的部分),则由于1fr
的设置,将平均地把多余空间分配给所有已有网格。
采用基于行/列线的方法将grid item放置到特定网格上
可以通过开发者工具看到网格布局的行线和列线:
因此可以通过为grid item指定行线和列线的方法将其放置到特定的网格上,与之相关的属性为:
grid-column-start
grid-column-end
grid-row-start
grid-row-end
也可以通过以下两个属性分别统一设置行和列:
grid-column
grid-row
如果同时设置起始线和终止线,则需要在它们中间添加/
假设对如上的网格布局进行如下设置:
header {
grid-column: 1 / 3;
grid-row: 1;
}
article {
grid-column: 2;
grid-row: 2;
}
aside {
grid-column: 1;
grid-row: 2;
}
footer {
grid-column: 1 / 3;
grid-row: 3;
}
其效果为:
另外,可以使用-1
来标记终止线,比如对于
header {
grid-column: 1 / 3;
grid-row: 1;
}
也可以写成:
header {
grid-column: -1 / -3;
grid-row: 1;
}
不过使用-1
标记终止线的方法只适用于显式网格,对隐式网格不起作用。
使用grid-template-areas放置grid item
除了使用基于行/列线的方法将grid item放置到特定网格上的方法,也可以使用grid-template-areas
,这种方法往往更为直观,如:
.container {
display: grid;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
grid-template-columns: 1fr 3fr;
grid-gap: 20px;
}
header {
grid-area: header;
}
article {
grid-area: content;
}
aside {
grid-area: sidebar;
}
footer {
grid-area: footer;
}
其效果为:
关于grid-template-areas
的使用,有以下需要注意的地方:
.
float
背景
float
最开始被引入是用来在文本中浮动图片,达到文本可以“包裹”在图片周围的效果。但随后网页制作人员发现float
不仅可以用来浮动图片,还可以用来浮动其它元素,以此来创建多列布局;所以后来float
被广泛用于多列布局的创建。不过随着新的布局技术的出现,如Flexbox及Grid,使得多列布局变得更加便捷且效果更好,因此把float
用作布局成为了传统的布局方式。
float
的使用
假设有如下的HTML代码:
<h1>Simple float example</h1>
<div class="box">Float</div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. </p>
<p>Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
为其添加基本的CSS代码:
body {
width: 90%;
max-width: 900px;
margin: 0 auto;
font: .9em/1.2 Arial, Helvetica, sans-serif
}
.box {
width: 150px;
height: 100px;
border-radius: 5px;
background-color: rgb(207,232,220);
padding: 1em;
}
在页面上呈现出的效果为:
为了使得文字浮于box周围,在box的CSS代码中添加两行声明:
.box {
float: left;
margin-right: 15px;
width: 150px;
height: 100px;
border-radius: 5px;
background-color: rgb(207,232,220);
padding: 1em;
}
页面变为:
float
工作原理
被设置了float
的元素,将会被从正常的布局流中移出,如初始状态的布局流为:
此时box未被设置float
属性,因此位于正常的布局流中,其下的<p>
位于它的下方;当box被设置为float: left
后,box从正常布局流中被移出:
原本位于box下方的<p>
向上移动,占据了box初始状态下的布局位置。
被设置为float:left
的box将会被塞到父容器的左侧位置,其后的所有内容都会向上移动,来环绕box,并填充box右侧的剩余空间。
可以在box上设置margin
来“推开”周围的文本,但是却不能靠在<p>
上设置margin
来“推开”box,原因如下:
假设在<p>
上设置margin-left: 20px;
则有:
究其原因,还是box已从正常的布局流中被移出了,为了更好地理解这句话,可以为<p>
设置背景颜色:
p:nth-of-type(1) {
background-color: rgb(79,185,227);
padding: 10px;
color: #fff;
}
再移动一下box的位置:将margin-right
变为margin
,则有:
综上可以看出,虽然<p>
中的文本环绕在box周围,但是<p>
的盒模型宽度还是占据了整个页面的宽度。
清除浮动
由之前的示例可以看出,当box被设置为float:left
时,后续的<p>
中文本将会环绕在box右侧,为了清除<p>
的环绕效果,需要使用clear
属性,如对第二个<p>
设置:
p:nth-of-type(2) {
clear: left;
}
则有:
关于clear
的取值说明为:
left
:清除左侧的浮动
right
:清除右侧的浮动
both
:清除两侧的浮动
如何使容器的空间包含住内部的float item
假设有如下HTML代码:
<div class="wrapper">
<div class="box">Float</div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate.</p>
</div>
可以看到,一个被赋予类名为wrapper
的<div>
容器内部含有两个组件,一个被设置为float item
的box,以及一个段落元素<p>
。
此时为整个容器设置背景颜色:
.wrapper {
background-color: rgb(79,185,227);
padding: 10px;
color: #fff;
}
我们想让容器的空间包含住内部的p
以及box,换句话说,我们希望容器的背景颜色能够包裹住两者所占空间,但事实上,只能得到如下的结果:
可以看到,容器的空间只包裹住了<p>
,而没有覆盖box,这是因为float item(即box)被移出了正常布局流,使得<div>
只能“察觉到”内部只含有<p>
,因此,<div>
此时的所占空间情况为:
为了实现我们想要的效果,即:
(<div>
空间占用情况:)
有三种方法,前面两种比较老旧,最后一种较新也比较恰当地处理了这个问题:
The clearfix hack
.wrapper::after {
content: "";
clear: both;
display: block;
}
Using overflow
.wrapper {
background-color: rgb(79,185,227);
padding: 10px;
color: #fff;
overflow: auto;
//如果还无法正常工作,可以再添加一条语句:
zoom: 1;
}
display: flow-root
.wrapper {
background-color: rgb(79,185,227);
padding: 10px;
color: #fff;
display: flow-root;
}
静态定位
静态定位,即position: static
,是每个元素在正常布局流中的默认设置。
相对定位
相对定位,即position: relative
,搭配top
,bottom
,left
,right
等属性设置元素相对于本身在初始位置下的相对位置,如设置:
position: relative;
top: 30px;
left: 30px;
则会产生类似如下的效果:
需要注意的是,虽然元素经过相对定位改变了最终的位置,但是却并没有因此影响到其它元素的位置;对其它元素而言,仿佛相对定位的元素位置没有发生过改变。
绝对定位
绝对定位,即position: absolute
,搭配top
,bottom
,left
,right
等属性设置元素相对于定位上下文的相对位置;其中,定位上下文指的是距离该元素最近的且被设置为position: relative
的祖先元素,但在默认情况下,定位上下文是<html>
,因此,当使用如下设置时:
position: absolute;
top: 30px;
left: 30px;
得到的效果是:
可以看到,由于没有特别指定定位上下文,所以绝对定位元素的定位上下文是整个页面(<html>
),同时还需要注意到,当被设置为绝对定位元素后,改变了周围其它元素的位置——绝对定位元素相对于其它元素来说仿佛根本就不存在!
这是因为,一旦元素被设置为绝对定位元素,该元素将被从正常布局流中移除,并且自身处于单独的页面层级,此时绝对定位元素既不受其它元素影响也不影响其它元素。
另外,还可以利用top
,bottom
,left
,right
,margin
等属性修改绝对元素的大小,假设对绝对元素设置如下:
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
此时元素的定位上下文没有指定则默认为<html>
,那么此时的效果为:
即将绝对元素的尺寸调整到了整个页面的尺寸大小。
z-index
当使用定位属性改变元素的位置时,可能会造成元素之间发生交叠的现象。那么当元素之间发生交叠时,是什么决定了某个元素在另一个元素的上方还是下方?默认情况下,定位元素叠加在非定位元素之上,那么,如果有多个定位元素发生交叠,此时将如何确定叠加顺序?
事实上,控制叠加顺序的属性为z-index
,相当于元素的Z轴,其正方向定义为垂直于屏幕向外;因此,z-index
值较大的定位元素将放在上面;默认情况下,每个元素关于z-index
的设置为auto
——其实就是0。
关于z-index
,还需注意的有:
z-index
值相等时,在HTML中后定义的元素将叠加在上方z-index
只能接受无单位的值,如:
z-index: 2;
固定定位
固定定位,即position: fixed
,搭配top
,bottom
,left
,right
等属性可以将元素定位到相对视口(viewport)的特定位置,其效果是无论页面的内容如何滚动变化,该元素始终处于屏幕的特定位置。
与绝对定位一样,当一个元素被设置为固定定位时,该元素将被从正常布局流中移除,其下元素将会向上移动填补该元素的位置,如同该元素不存在一样。
固定定位的示例可参考:fixed-positioning.html.
粘性定位
粘性定位,即position: sticky
,是一种较为新颖的定位方式,该方式介于静态定位和固定定位之间,被设置为粘性定位的元素正常情况下表现与静态定位一样,但当随着页面内容滚动,使得粘性定位元素与视口(viewport)之间的偏移满足设定条件时,该元素将表现得如同固定定位元素一样,固定在屏幕的某个位置,使用方法为:
.positioned {
position: sticky;
top: 30px;
}
有关粘性定位的示例,可参考:sticky-positioning.html.
使用column-count
和column-width
进行多列布局
假设有如下HTML代码:
<div class="container">
<h1>Simple multicol example</h1>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate.
Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse
ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit
quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique
elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit
cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis
dis parturient montes, nascetur ridiculus mus.</p>
</div>
其页面效果为:
现在需要为container
创建一个多列布局,首先可以使用column-count
:
.container {
column-count: 3;
}
column-count
可以为你创建指定数量的列,每一列的宽度由浏览器自行分配:
如果想让浏览器为你创建尽可能多的具有最小宽度的列,则可改为使用column-width
:
.container {
column-width: 200px;
}
此时浏览器将根据容器的宽度创建尽可能多的宽度至少为200px的列,多余的空间将被已有列平分:
设置多列布局的样式
要设置多列布局的样式,可供选择的选项只有两个:
column-gap
改变列之间的间隙column-rule
在列之间添加分割线 column-rule
的使用方法与border
类似,它是column-rule-color
,column-rule-style
,column-rule-width
三个属性的简写属性。若设置:
.container {
column-count: 3;
column-gap: 20px;
column-rule: 4px dotted rgb(79, 185, 227);
}
则页面效果为:
需要注意的是,column-rule
指定的分割线并不占用空间,它只是起到纯粹的渲染的效果;因此为了使得列之间的分割线看起来符合审美,应该适当调整column-gap
的大小。
内容分隔问题
位于多列布局中的元素,其内容为了适应多列布局的特点,在必要的地方会被浏览器自动分隔,如下:
在上图中可以看到,如果一个板块既有标题又有内容,那么当标题和内容不能作为一个整体被呈现反而被分隔开时,会造成不好的用户体验。为了告知浏览器某个板块的内容不能被分隔时,在该元素上使用break-inside: avoid
即可;同时,为了具有较好的浏览器支持性,最好再添加上page-break-inside: avoid
(作用一样),如:
.container {
column-width: 250px;
column-gap: 20px;
}
.card {
break-inside: avoid;
page-break-inside: avoid;
background-color: rgb(207, 232, 220);
border: 2px solid rgb(79, 185, 227);
padding: 10px;
margin: 0 0 1em 0;
}
页面呈现效果为:
使用float
进行双列布局
首先是HTML代码:
<h1>2 column layout example</h1>
<div>
<h2>First column</h2>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
</div>
<div>
<h2>Second column</h2>
<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
</div>
初始页面为:
添加CSS代码:首先设置容器的大小:
body {
width: 90%;
max-width: 900px;
margin: 0 auto;
}
随后设置两列的尺寸:
div:nth-of-type(1) {
width: 48%;
}
div:nth-of-type(2) {
width: 48%;
}
为两列添加浮动(一个左浮动一个又浮动,剩下的4%作为两列之间的间隙):
div:nth-of-type(1) {
width: 48%;
float: left;
}
div:nth-of-type(2) {
width: 48%;
float: right;
}
最终的页面效果为:
使用float
构造基本的网格系统(框架)
该部分将介绍如何使用float
构造出一个每行为12个网格的网格系统(框架),搭建好该框架以后,就可以轻易地构造出每行为2/3/4/6列的多列布局(因为12能被2,3,4,6中的任何一个数整除)。
假设我们需要搭建的网格系统其外部容器会随着屏幕尺寸的变化而变化,且最大值为980px,在此情况下,用于整个网格布局的空间为960px,每个网格的宽度为60px,网格与网格间隙为20px,首先是HTML代码:
<div class="wrapper">
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
<div class="col">6</div>
<div class="col">7</div>
<div class="col">8</div>
<div class="col">9</div>
<div class="col">10</div>
<div class="col">11</div>
<div class="col">12</div>
</div>
<div class="row">
<div class="col span1">13</div>
<div class="col span6">14</div>
<div class="col span3">15</div>
<div class="col span2">16</div>
</div>
</div>
初始页面效果为:
首先是外部容器(wrapper
)的CSS构造代码:
* {
box-sizing: border-box;
}
body {
width: 90%;
max-width: 980px;
margin: 0 auto;
}
.wrapper {
padding-right: 2.04081632653%;
}
页面效果图为:
可以看到wrapper
右侧设置了20px的padding(2.04081632653% = 20/980*100% ),剩余的内容占960px;
随后设置每列的CSS代码:
.col {
float: left;
margin-left: 2.08333333%;
width: 6.25%;
background: rgb(255, 150, 150);
}
其中margin-left
用于设置同一行各列之间的间距(2.08333333% = 20/960*100%),width
用于设置每列的宽度(6.25% = 60/960*100%)。为了对行与行之间进行一个分隔,添加:
.row {
clear: both;
}
页面效果为:
为了能根据需求扩展列的宽度,我们需要分别定义2-12列宽的网格长度:
/* Two column widths (12.5%) plus one gutter width (2.08333333%) */
.col.span2 { width: 14.58333333%; }
/* Three column widths (18.75%) plus two gutter widths (4.1666666) */
.col.span3 { width: 22.91666666%; }
/* And so on... */
.col.span4 { width: 31.24999999%; }
.col.span5 { width: 39.58333332%; }
.col.span6 { width: 47.91666665%; }
.col.span7 { width: 56.24999998%; }
.col.span8 { width: 64.58333331%; }
.col.span9 { width: 72.91666664%; }
.col.span10 { width: 81.24999997%; }
.col.span11 { width: 89.5833333%; }
.col.span12 { width: 97.91666663%; }
这样一来,第二列就变成了:
同时,为了使得列的位置能产生偏移,可以定义类似如下的代码:
.offset-by-one {
margin-left: 10.41666666%;
}
随后在HTML中,将:
<div class="col span6">14</div>
改为:
<div class="col span5 offset-by-one">14</div>
表示将其向右偏移一网格(包括网格之间的间隔),页面效果变为:
至此,一个每行为12个网格的网格系统(框架)搭建完成,随后就可以根据需要任意构造出每行含有2/3/4/6列的多列布局,且可以根据需要对它们的位置进行偏移。
为了使得计算过程更加直观,可以使用calc()
函数,用如下代码替代上面相应功能的代码:
.col.span2 { width: calc((6.25%*2) + 2.08333333%); }
.col.span3 { width: calc((6.25%*3) + (2.08333333%*2)); }
.col.span4 { width: calc((6.25%*4) + (2.08333333%*3)); }
.col.span5 { width: calc((6.25%*5) + (2.08333333%*4)); }
.col.span6 { width: calc((6.25%*6) + (2.08333333%*5)); }
.col.span7 { width: calc((6.25%*7) + (2.08333333%*6)); }
.col.span8 { width: calc((6.25%*8) + (2.08333333%*7)); }
.col.span9 { width: calc((6.25%*9) + (2.08333333%*8)); }
.col.span10 { width: calc((6.25%*10) + (2.08333333%*9)); }
.col.span11 { width: calc((6.25%*11) + (2.08333333%*10)); }
.col.span12 { width: calc((6.25%*12) + (2.08333333%*11)); }
使用flexbox搭建网格系统(框架)
基于flexbox搭建网格系统与基于float类似,其CSS代码如下:
* {
box-sizing: border-box;
}
body {
width: 90%;
max-width: 980px;
margin: 0 auto;
}
.wrapper {
padding-right: 2.04081632653%;
}
.row {
display: flex;
}
.col {
margin-left: 2.08333333%;
margin-bottom: 1em;
width: 6.25%;
flex: 1 1 auto;
background: rgb(255, 150, 150);
}
其中,对于flex: 1 1 auto
中的auto
来说,由于事先已经设置过width: 6.25%
,所以auto
表示flex-basis
将使用与width
相同的值。
此时得到的页面效果为:
可以看到,在第二行中,本来每列应该是60px(6.25%width
),但由于flexbox自身的自动扩展特性,所以4列扩展并平分了该行的剩余空间。因此,为了能够人为指定每列扩展的长度,依然需要添加span
类:
.col.span2 { width: calc((6.25%*2) + 2.08333333%); }
.col.span3 { width: calc((6.25%*3) + (2.08333333%*2)); }
.col.span4 { width: calc((6.25%*4) + (2.08333333%*3)); }
.col.span5 { width: calc((6.25%*5) + (2.08333333%*4)); }
.col.span6 { width: calc((6.25%*6) + (2.08333333%*5)); }
.col.span7 { width: calc((6.25%*7) + (2.08333333%*6)); }
.col.span8 { width: calc((6.25%*8) + (2.08333333%*7)); }
.col.span9 { width: calc((6.25%*9) + (2.08333333%*8)); }
.col.span10 { width: calc((6.25%*10) + (2.08333333%*9)); }
.col.span11 { width: calc((6.25%*11) + (2.08333333%*10)); }
.col.span12 { width: calc((6.25%*12) + (2.08333333%*11)); }
以及偏移功能:
.offset-by-one {
margin-left: calc(6.25% + (2.08333333%*2));
}
Flexbox相较于float的优越性
在布局的使用上,flexbox相较于float的优越性主要有:
第三方UI布局框架
除了自行设计布局样式,也可以使用现成的第三方UI框架进行快速布局,目前较为流行的UI框架包括Boorstrap和Foundation等。其原理就是第三方UI框架提供各种现成的.CSS
文件,使得开发者只需在HTML元素中引用相关CSS类即可完成布局。
关于使用Skeleton进行网格系统布局的操作示例,可参考:Third party grid systems.
查看各个浏览器的市场份额
参考:Statcounter
查看某特性在浏览器中的支持(兼容)性
在CSS中添加后备代码以提升兼容性
当使用Flexbox以及CSS grid这些特性时,最好为其提供后备版本的代码,因为不是所有的浏览器都支持这些特性,提供后备代码的目的是为了在浏览器无法支持这些新特性时,后面代码给出的样式效果能作为次优选择。
以下是一个简单的示例,首先有HTML代码:
<div class="wrapper">
<div class="item">Item One</div>
<div class="item">Item Two</div>
<div class="item">Item Three</div>
</div>
为了产生网格效果的布局,首先使用最传统的float
方式布局:
* {box-sizing: border-box;}
.wrapper {
background-color: rgb(79,185,227);
padding: 10px;
max-width: 400px;
display: flow-root;
}
.item {
float: left;
border-radius: 5px;
background-color: rgb(207,232,220);
padding: 1em;
}
页面效果为:
现在,我们想要引入CSS grid这个较新的特性,由于CSS规范给出:若float items被设置为grid items,则将会自动失去float items的行为而使用grid items行为,所以为了添加CSS grid,有:
* {box-sizing: border-box;}
.wrapper {
background-color: rgb(79,185,227);
padding: 10px;
max-width: 400px;
display: flow-root;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.item {
float: left;
border-radius: 5px;
background-color: rgb(207,232,220);
padding: 1em;
}
这样一来,支持CSS grid特性的浏览器将会使用CSS grid,而不支持的浏览器则会忽略所有与grid相关的CSS声明,而按float
方式处理元素。
布局特性覆盖方式
以下说明了当传统布局特性被同时设置为CSS grid以及Flexbox时,浏览器将会如何进行特性选择的问题:
Float and clear
如果floated 或 cleared items 成为flex或grid items,则相关功能将失效。
display: inline-block
被设置为display: inline-block
的元素成为flex或grid items后,inline-block
的效果将失效。
Multiple-column Layout
如果通过column-*
等属性定义的容器被设置为grid
container,则多列布局的效果将失效。
Flexbox
当把设置为flex
的容器同时设置为grid
容器时,flex
的效果将失效。
功能查询
可以使用如下代码查询display: grid
是否在浏览器中得到支持,如果得到支持,才执行内部的代码(前提是浏览器支持功能查询服务本身):
@supports (display: grid) {
.item {
width: auto;
}
}