CSS 教程
介绍 CSS 样式与布局基础，覆盖常用选择器、盒模型与排版要点。适合网页开发入门，帮你把页面样子调顺。

CSS高级功能
自定义属性
CSS 提供的属性（比如
font-weight、
line-height）都是标准给定的，但是 CSS 也允许用户自定义属性，这又称为“CSS 变量”。
自定义属性跟普通属性一样，也是定义在某个选择器里面，而且只对该选择器有效。因此自定义属性所在区块，相当于变量的作用域。
:root选择器之中，可以设置全局的自定义属性。
:root {
  --base: #ffc600;
  --spacing: 10px;
  --blur: 10px;
}
变量也可以在行内定义。
<html style = "--color: red;">
所有自定义属性都必须以两个连词线开头，并且大小写敏感。
使用时，通过
var()函数取出变量。
img {
  padding: var(--spacing);
  background: var(--base);
  -webkit-filter: blur(var(--blur));
  filter: blur(var(--blur));
}
var()函数接受第二个参数，指定默认值。如果某个自定义属性没有设置，默认值就会生效。
width: var(--custom-width, 20%);
下面是另一个例子。
foo {
  padding: var(--gutter, 10px 0 0 5px);
}
如果默认值包含逗号，那么
var()会将第一个逗号后面的所有值，当作默认值。
.someElement {
  font-family: var(--main-font, "lucida grande" , tahoma, Arial);
}
上面代码中，
--main-font的默认值是
"lucida grande" , tahoma, Arial。
var()内部还可以使用
var()。
.someElement {
  background-color: var(--first-color, var(--second-color, white));
}
上面代码中，如果没有设置
--first-color，默认值
var(--second-color, white)就会生效。如果
--second-color也没有设置，那么
white就会生效。
自定义属性可以是全局的，也可以是局部的。在
:root选择器里面定义的，就是全局变量，可以在任何其他选择器里面读取。而在其他选择器里面定义，就是局部变量，只能在该选择器里面读取。
下面代码中，局部变量可以覆盖全局变量。
:root { --text-color: green; }
div { --text-color: blue; }
.error { --text-color: red; }
* {
  color: var(--text-color);
}
上面代码中，一般文字是绿色，
div元素的文字是蓝色，
error类的文字是红色。
定义变量的时候，也可以读取其他变量。
:root {
  --brand-color: red;
  --header-text-color: var(--brand-color);
}
变量也可以与
calc函数结合使用。
:root {
  --container-width: 1000px;
  max-width: calc(var(--container-width) / 2);
}
变量不包含单位时，不能直接添加单位。
/* 无效 */
.quote {
  --t-padding: 20;
  padding-top: var(--t-padding)px;
}
/* 有效 */
.quote {
  --t-padding: 20;
  padding-top: calc(var(--t-padding) * 1px);
}
JavaScript 可以操作这些变量。
element.style.setProperty('--my-color', 'rebeccapurple');
element.style.getPropertyValue('--my-color');
// "rebeccapurple"
element.style.removeProperty('--my-color');
下面是例子。
// 取得变量值
var styles = window.getComputedStyle(document.documentElement);
var bgValue = String(styles.getPropertyValue('--background')).trim();
// 设置变量值
document.documentElement.style.setProperty('--background', 'black');
// 另一种写法
document.documentElement.style.setProperty('--h-color', 'var(--p-color)');
下面是一个监听事件的例子。
const docStyle = document.documentElement.style;
document.addEventListener('mousemove', (e) => {
  docStyle.setProperty('--mouse-x', e.clientX);
  docStyle.setProperty('--mouse-y', e.clientY);
});
下面是一个使用CSS变量的例子，只要
<input>的值发生变化，样式就会随之发生变化。
// get the inputs
const inputs = [].slice.call(document.querySelectorAll('.controls input'));
// listen for changes
inputs.forEach(input => input.addEventListener('change', handleUpdate));
inputs.forEach(input => input.addEventListener('mousemove', handleUpdate));
function handleUpdate(e) {
  // append 'px' to the end of spacing and blur variables
  const suffix = (this.id === 'base' ? '' : 'px');
  document.documentElement.style.setProperty(`--${this.id}`, this.value + suffix);
}
参考链接
CSS Variables Guide, Tony Martinez
supports
supports命令用来判断浏览器是否支持某项CSS功能。
@supports not (display: grid) {
  // 不支持网格布局
  // 老式浏览器代码
}
@supports (display: grid) {
  // 支持网格布局
  // 新式浏览器代码
}
另一个例子。
@supports (object-fit: cover) {
  img {
    object-fit: cover;
  }
  div {
    width: auto;
    background: green;
   // some other complex code for the fancy new layout
  }
}
initial-letter
initial-letter决定首字母的下沉样式。
/* 默认值 */
initial-letter: normal;
/* 占据1.5行高度 */
initial-letter: 1.5;
/* 占据3行高度 */
initial-letter: 3.0;
/* 占据3行高度，下沉2行高度 */
initial-letter: 3.0 2;
滤镜
网页的灰度显示。
html {
  -webkit-filter: grayscale(100%);
  filter: grayscale(100%);
}
CSS Shape
shape-outside属性使得行内（inline）的内容，围绕
outside指定的曲线排列。
shape-margin属性指定
shape-outside与内容之间的
margin。
.circle {
  width: 250px;
  height: 250px;
  background-color: #40a977;
  border-radius: 50%;
  float: left;
  -webkit-shape-outside: circle();
  shape-outside: circle();
}
circle函数可以使用
circle(r at x y)这样的形式，定义半径和圆心的坐标。注意，这里的坐标是相对于原始形状，而不是相对于父容器。
其他形状的函数。
ellipse()
polygon()
参考链接
How to Use CSS Shapes in Your Web Design, by Louie R.

CSS 动画
timer
linear：线性运行，各个时刻速度都一样。
ease: 快速加速，然后逐渐减速，CSS 的默认值。
ease-in：逐渐加速，结尾时变快，适用于退出页面显示的元素。
ease-out：开始时速度最快，然后逐渐慢下来，适用于进入页面显示的元素。
ease-in-out：主键加速然后变慢，与
ease相似，但开始时加速较慢，适合那些在页面有着明确开始和结束的动画。
#div1 {transition-timing-function：linear;} 
#div2 {transition-timing-function：ease;} 
#div3 {transition-timing-function：ease-in;} 
#div4 {transition-timing-function：ease-out ;} 
#div5 {transition-timing-function：ease-in-out;}
上面的代码等价于下面的代码。
#div1 {transition-timing-function: cubic-bezier(0,0,1,1);}
#div2 {transition-timing-function: cubic-bezier(0.25,0.1,0.25,1);}
#div3 {transition-timing-function: cubic-bezier(0.42,0,1,1);}
#div4 {transition-timing-function: cubic-bezier(0,0,0.58,1);}
#div5 {transition-timing-function: cubic-bezier(0.42,0,0.58,1);}
transition
transition属性定义元素状态变化的过渡。
transition: [*property] [*transition-duration] [transition-timing-function] [transition-delay];
transition属性一共有四个参数。
*property：元素的哪一个 CSS 属性需要过渡效果，该参数必需。
*transition-duration：过渡效果的持续时间，该参数必需。
transition-timing-function：定时函数，默认是
ease。
transition-delay：过渡从多少秒以后开始，默认是
0。
/*1*/ transition: background-color 2s;
/*2*/ transition: background-color 2s 0.5s;
/*3*/ transition: background-color 2s ease-in;
/*4*/ transition: background-color 2s ease-out 0.5s;
/*5*/ transition: background-color 2s, height 1s ease-in-out;
/*6*/ transition: all 1s ease-out;
animation
animation属性用来指定元素的动画效果。
animation: [*animation-name] [*animation-duration] [animation-timing-function] [animation-delay] [animation-iteration-count] [animation-direction] [animation-fill-mode] [animation-play-state];
*animation-name：关键帧的名字，该参数必需。
*animation-duration：动画持续的时间，该参数必需。
animation-timing-function：定时器函数，默认是
ease。
animation-delay：动画效果多少秒后开始，默认为
0。
animation-iteration-count：动画重复的次数，可以指定为一个整数，表示多少次，默认值是
infinite关键字，表示无限次。
animation-direction：动画方向，可能的值为
forward、
backward或
alternating，默认值为
normal。
animation-fill-mode：默认值为
none。
animation-play-state：动画默认是否生效，默认值为
running。
@keyframes bounce {
  0% {
    transform: scale(0.1);
    opacity: 0;
  }
  60% {
    transform: scale(1.2);
    opacity: 1;
  }
  100% {
    transform: scale(1);
  }
}
.ball {
  animation: bounce 2s infinite;
}
keyframes
首先，需要使用
keyframes定义一个动画。
keyframes rotation {
  from {
    transform: rotate(90deg);
  }
  to {
    transform: rotate(450deg);
  }
}
上面代码中，
keyframes关键字后面是动画名称（上例是
rotation），大括号内部是关键帧，
from表示起始帧，
to表示结束帧，其他帧由浏览器自动计算出来。
另一种定义方法是使用百分比，定义关键帧，
from就是
0%，
to就是
100%。
@keyframes color {
  0% {
    fill: #99002f
  }
  50% {
    fill: #ffc426
  }
  100% {
    fill: #99002f
  }
}
使用的时候，通过
animation属性将动画赋给指定元素即可。（Demo）
.second {
  animation: rotation 60s steps(60) infinite;
  transform-origin: 100% 50%;
}
animation属性是一个简写形式，它包括以下一些子属性。
animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
animation-fill-mode
svg path {
  animation: color 2s infinite cubic-bezier(.85,.01,.25,1);
}
/* 等同于 */
svg path {
  animation-name: color;
  animation-duration: 2s;
  animation-iteration-count: infinite;
  animation-timing-function: cubic-bezier(.85,.01,.25,1);
}
隐入（fade in）
@keyframes fade-in {
  0% { opacity: 0; }
  100% { opacity: 1; }
}
.fade-in {
  animation: fade-in 1s forwards linear;
}
上浮（fade up）
@keyframes fade-up {
  0% {
    opacity: 0; transform: translateY(3em);
  }
  100% {
    opacity: 1; transform: translateY(none);
  }
}
.fade-up {
  animation: fade-up 3s cubic-bezier(.05,.98,.17,.97) forwards;
}
左右摆动（wiggle）
@keyframes wiggle {
0%, 7% { transform: rotateZ(0); opacity: 0; }
15% { transform: rotateZ(-15deg); opacity: 1; }
20% { transform: rotateZ(10deg); }
25% { transform: rotateZ(-10deg); }
30% { transform: rotateZ(6deg); }
35% { transform: rotateZ(-4deg); }
40%, 100% { transform: rotateZ(0); }
}
上下弹跳（bounceAround）
.animation {
	…
	animation: bounceAround 1.1s ease-in-out infinite;
}
@keyframes bounceAround {
	0% {transform:translateY(0);}
	20% {transform:translateY(-60px) rotate(0deg);}
	25%{transform:translateY(20px) rotate(0deg);}
	35%, 55%{transform:translateY(0px) rotate(0deg);}
	60% {transform: translateY(-20px) rotate(0deg);}
	100%{transform: translateY(-20px) rotate(360deg);}
}

背景
如果不定义背景图片或者背景色，一个网页元素的背景就是透明的。
opaque
opaque的值在0到100之间。默认值是100，表示百分之百不透明，而0表示百分之百透明。
background-attachment
background-attachment属性设置背景图案的位置，是否在视口里面是固定的，也就是说，是否随着滚动条一起滚动。由于存在两种滚动条——视口的滚动条和区块的滚动条——因此
background-attachment的行为有三种模式，对应三个属性值。
scroll：这个是默认值，表示背景图片绑定区块的内容，会随着视口滚动条滚动，但不会随着区块滚动条滚动。
fixed：背景图片绑定视口，不会随着视口滚动条和区块滚动条滚动。
local：背景图片会随着视口滚动条和区块滚动条滚动。
background-repeat
background-repeat指定当背景图片小于容器时的平铺方式。
html {
  background-image: url(logo.png);
  background-repeat: repeat-x;
}
它可以取以下值。
repeat：背景图片沿容器的X轴和Y轴平铺，将会平铺满整个容器，可能会造成背景图片显示不全。
repeat-x： 背景图片沿容器的X轴平铺。
repeat-y：背景图片沿容器的Y轴平铺。
no-repeat：背景图片不做任何平铺。
round：背景图片沿容器的X轴和Y轴平铺，将会铺满整个容器。如果有多余空间，会升缩背景图片适应容器大小，不会造成图片显示不全。
space：背景图片沿容器的X轴和Y轴平铺，将会铺满整个容器。如果有多余空间，不会改变背景图片的大小，而是平均分配相邻图片之间的空间，不会造成图片显示不全。
background-repeat可以设置两个值，分别表示 X 轴和 Y 轴的重复方式。
.element {
/* background-repeat: horizontal vertical */
   background-repeat: repeat space;
   background-repeat: repeat repeat;
   background-repeat: round space;
}
background-repeat只设置一个值的时候，其实是下面方式的简写。
repeat：相当于
repeat repeat
repeat-x：相当于
repeat-x no-repeat
repeat-y：相当于
no-repeat repeat
no-repeat：相当于
no-repeat no-repeat
space：相当于
space space
round：相当于
round round
参考链接
单聊background-repeat，by 大漠

盒状模型
width
width: auto表示父元素提供的所有宽度（100%）。
max-width
max-width设为
none，可以让元素占满父元素的整个宽度。
overflow
overflow属性指定如果元素的大小超出容器时的行为。
visible：默认值，表示溢出的部分可见
hidden：表示溢出的部分不可见
scroll：表示发生溢出时，会显示滚动条，用户可以拖动滚动条，看到溢出的部分
clip
clip规则指定元素超出容器大小时，具体显示哪个部分。它只对绝对定位（absolute）和固定定位（fixed）的元素有效。
clip: rect(0px, 100px, 100px, 0px);
react函数四个参数的含义如下。
第一个参数：剪切后的顶边距离容器的顶边的距离
第二个参数：剪切后的右边界距离容器的左边界的距离
第三个参数：剪切后的底边距离容器的顶边的距离
第四个参数：剪切后的左边界距离容器的左边界的距离
clip: rect(auto 100px auto auto);
该规则已经被废除，但是浏览器还是普遍支持。
clip-path
clip-path是
clip规则的继承者，用来剪切元素的大小。它对所有定位方式都适用。
clip: rect(110px, 160px, 170px, 60px);
/* 等同于 */
clip-path: inset(10px 20px 30px 40px);
clip-path支持多种路径定义方式。
.clip-me {
  /* referencing path from an inline SVG <clipPath> */
  clip-path: url(#c1);
  /* referencing path from external SVG */
  clip-path: url(path.svg#c1);
  /* polygon */
  clip-path: polygon(5% 5%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
  /* circle */
  clip-path: circle(30px at 35px 35px);
  /* ellipse */
  clip-path: ellipse(65px 30px at 125px 40px);
  /* inset-rectangle() may replace inset() ? */
  /* rectangle() coming in SVG 2 */
  /* rounded corners... not sure if a thing anymore */
  clip-path: inset(10% 10% 10% 10% round 20%, 20%);
}
box-sizing
box-sizing指定盒状模型的宽度范围。
border-box：宽度包括padding和border
content-box：默认值，只包括内容区的宽度，不包括padding和border
*, *:after, *:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
object-fit
object-fit命令指定一个元素的大小应该如何适应它的容器，主要用于图像。它可以取以下的值。
fill：容器的宽度和高度就是元素的宽度和高度，会截去溢出的部分。
contain：元素会填满容器，不会改变长宽比，可能会有溢出。
cover：元素会填满容器，可能会改变长宽比，但不会有溢出。
none：元素不会改变的大小，具体的展示效果由默认算法决定
scale-down：展示效果会选择
none或
contain之中，对象尺寸较小的一个
inherit：使用父元素的值
initial：使用浏览器的默认值
unset：这个属性是
inherit和
initial的结合，如果该元素继承父元素，就采用
inherit，否则采用
initial

颜色
颜色关键字
CSS 允许使用关键字表示颜色，CSS2.1 设置了16个基本的颜色，CSS 3 又增加了131个。
六位颜色表示法
六位颜色表示法又称为 RGB 表示，分别使用两位十六进制数表示红色（R）、绿色（G）、蓝色（B），组合在一起就是六位，然后加上
#前缀，比如
#59007F。
每种颜色使用0～255表示浓度，0表示没有，255表示浓度最深。
如果一个十六进制颜色是由三对重复的数字组成的，如
#ff3344，可以缩写为
#f34。
八位颜色表示法
Chrome 浏览器支持八位的颜色表示法
RRGGBBAA，前六位是红、绿、蓝颜色值，后两位表示透明度（alpha transparency）。比如，
#ffffff80相当于
rgba(255, 255, 255, .5)。
alpha设置越接近0，颜色就越透明。如果设为0，就是完全透明的，就像没有设置任何颜色。类似地，1表示完全不透明。
HSL 和 HSLA 表示法
HSL 代表色相（hue）、饱和度（saturation）和亮度（lightness），其中色相的取值范围为0～360，饱和度和亮度的取值均为百分数，范围为0～100%。
红色为hsl(0,100%,50%);
黄色为hsl(60,100%,50%);
绿色为hsl(120,100%,50%);
青色为hsl(180,100%,50%);
蓝色为hsl(240,100%,50%);
紫红色为hsl(300,100%,50%);
用HSLA指定alpha透明度的方法与RGBA是一致的。
currentColor
currentColor是一个属性值，代表当前元素的
color属性的值。
.box {
  color: red;
  border: 1px solid currentColor;
  box-shadow: 0 0 2px 2px currentColor;
}
上面代码，
border和
box-shadow的颜色都与
color保持一致。这种写法的好处是，如果要修改
color，只要修改一处就可以了，不用修改三个地方。
currentColor的另一个用处，是让衍生类都继承基类的颜色。
.box {
    color: red;
}
.box .child-1 {
    background: currentColor;
}
.box .child-2 {
    color: currentColor;
    border 1px solid currentColor;
}
伪元素也可以使用
currentColor。
.box {
    color: red;
}
.box:before {
    color: currentColor;
    border: 1px solid currentColor;
}
参考链接
使用 currentColor 属性写出更好的 CSS 代码

常用组件
对话框
显示屏幕居中的对话框。
<div id="dialog">
  <p>I am the dialog's content</p>
  <button type="button">close dialog</button>
</div>
#dialog {
  position: fixed;
  top: 50%;
  left: 50%;
  width: 400px;
  height: 200px;
  transform: translate3d(-50%,-50%,0);
  background: white;
  border: 100% solid rgba(0, 0, 0, 2.5);
}
#dialog:before {
  content: "";
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.25);
  z-index: 999;
  /* fade in */
  transition: opacity 0.2s ease-in-out;
}
#dialog[hidden] {
  /*
    [hidden] usually sets display:none, which we
    need to revert in order to allow animations
  */
  display: block;
  /*
    actually hide the element,
    making its contents unaccessible
  */
  visibility: hidden;
  /*
    make sure the element is out of viewport
  */
  transform: translate3d(0px, -1px, 0px) scale(0);
  /*
    delay transform until animations are done
  */
  transition:
    visibility 0s linear 0.2s,
    transform 0s linear 0.2s;
}
参考链接
Accessible dialog tutorial

display 属性
display: none;会从文档流移除该元素及其子元素，仿佛它们是不存在的。它们占据的空间会释放出来。
display: inline;产生行内元素，没有自己的高度和宽度，由容器决定，前后不会产生换行。
display: block;产生块级元素，会占据一行，占满容器的宽度。
display: list-item;将元素渲染为一个列表项，行首产生一个列表标记，可以用
list-style定制样式。
display: inline-block;产生行内的块级元素，有自己的高和宽，但是前后不会产生换行。
表格相关的设置
table 对应
<table>元素
table-header-group 对应
<thead>
table-row	对应
<tr>
table-cell 对应
<td>
table-row-group 对应
<tbody>
table-footer-group 对应
<tfoot>
table-column-group 对应
<colgroup>
table-column 对应
<col>
table-caption 对应
<caption>
inline-table 将一个表格渲染具有
inline-block的形式
表格显示
div {
  display: table;
  display: table-cell;
  display: table-column;
  display: table-colgroup;
  display: table-header-group;
  display: table-row-group;
  display: table-footer-group;
  display: table-row;
  display: table-caption;
}
flexbox
display: flexbox;是一维布局，定义沿着一根直线的布局。这根直线可以折行。
grid
display: grid;是二维布局。
direction
direction命令指定元素的排列方向，默认是从左到右
ltr，可以设置为从右到左
rtl。
direction: rtl;
参考链接
How well do you know CSS display?, by Chen Hui Jing

常用功能
置中
transform方法。
容器设置相对定位。
.container {
  position: relative;
  width: 200px;
  height: 200px;
  overflow: hidden;
}
元素的左上角先定位在容器中央，然后向西北方向移动自身的
50%。
.container div {
  position: absolute;
  left: 50%;
  top: 50%;
  -webkit-transform: translate(-50%,-50%);
      -ms-transform: translate(-50%,-50%);
          transform: translate(-50%,-50%);
}
隐藏元素
彻底隐藏一个元素。
[hidden] {
  display: none;
}
在视觉上隐藏一个元素。
.visuallyhidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  border: 0;
  padding: 0;
  clip-path: inset(100%);
  clip: rect(0 0 0 0);
  overflow: hidden;
}
参考链接
Hiding DOM elements

字体
字体文件类型
内嵌OpenType（Embedded OpenType，.eot）。在使用@font-face时，Internet Explorer 8及之前的版本仅支持内嵌OpenType。内嵌OpenType是Microsoft的一项专有格式，它使用数字版权管理技术防止在未经许可的情况下使用字体。
TrueType（.ttf）和OpenType（.otf），台式机使用的标准字体文件类型。TrueType和OpenType得到了Mozilla Firefox（3.5及之后的版本）、Opera（10及之后的版本）、Safari（3.1及之后的版本）、Mobile Safari（iOS 4.2及之后的版本）、Google Chrome（4.0及之后的版本）及Internet Explorer（9及之后的版本）的广泛支持。这些格式不使用数字版权管理。
Web开放字体格式（Web Open Font Format，.woff）。这种较新的标准是专为Web字体设计的。Web开放字体格式的字体是经压缩的TrueType字体或OpenType字体。WOFF格式还允许在文件上附加额外的元数据。字体设计人员或厂商可以利用这些元数据，在原字体信息的基础上，添加额外的许可证或其他信息。这些元数据不会以任何方式影响字体的表现，但经用户请求，这些元数据可以呈现出来。Mozilla Firefox（3.6及之后的版本）、Opera（11.1及之后的版本）、Safari（5.1及之后的版本）、Google Chrome（6.0及之后的版本）及Internet Explorer（9及之后的版本）均支持Web开放字体格式。
可缩放矢量图形（Scalable Vector Graphics，.svg）。简言之，应避免对Web字体文件使用SVG。它更多地用于早期Web字体，因为它是iOS 4.1上移动Safari唯一支持的格式（还有可能引起一些崩溃的情况）。从iOS 4.2（于2011年初即被广泛使用）起，移动Safari开始支持TrueType。
font-size
font-size属性用于设置网页的字体大小。
下面是设置网页根字体大小的例子。
:root {
  font-size: 16px;
}
/* 也可以针对 html 元素设置
html {
  font-size: 16px;
}
然后，每个一级区块的
font-size采用
rem单位，内部属性使用
em单位。这时，
em的大小是基于
rem设置的。
button {
    font-size: 0.875rem;
    // All the internal/external value use in 'em'
    // This value use of your "font-size" as the basic font size
    // And you will not have any problem with the font size of the container ( Example bottom )
    padding: .5em 1em;
    border: .125em solid #e3e3e3;
    @media (min-width: 48rem){ // min-width: 768px
      font-size: 1.125rem;
    }
    @media (min-width: 62rem){ // min-width: 992px
      font-size: 1.375rem;
    }
}
font-smoothing
font-smooth属性主要用于控制浏览器对字体的渲染。比如，下面的设置可以减少字体渲染出现锯齿。
body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
font-display
有时，样式表指定的字体需要下载（称为 web font），
font-display属性用于控制浏览器在下载字体时的渲染行为。
@font-face {
  font-family: 'my-font';
  font-display: optional;
  src: url(my-font.woff2) format('woff2');
}
这里需要理解，浏览器对于下载字体的处理过程。
首先，浏览器发现样式表指定的字体，是一种需要下载的字体，会去检查缓存里面是否存在这种字体，如果不存在就开始从网上下载。这时，网页上使用这种字体的文字，会显示不出来，而展现一片空白。这段时间称为”阻塞期“（block），每种浏览器的”阻塞期“时间长度不尽相同，Chrome、Firefox 和 Safari 都是3秒，即文字会有3秒钟显示不出来，而 IE 是0秒，即没有阻塞期。
然后，阻塞期结束，如果字体已经下载完成，浏览器就会采用下载的字体进行渲染，文字就会显示出来。如果下载还没有结束，浏览器就会采用替代字体进行渲染，文字也会显示出来，但是与最终状态不一样，这段时间称为”替换期“（swap）。此时，浏览器其实还在下载字体。
最后，等到字体下载成功，这时浏览器会用下载的字体，替换现有的字体，这时网页会一闪。如果字体下载失败了，这时浏览器就会继续使用现有的字体，因此网页不会发生变化。
font-display可以取以下值。
（1）
font-display: block
这是浏览器的默认行为，即打开阻塞期。
（2）
font-display: swap
这个值会关闭阻塞期，直接进入替换期，即浏览器不会出现文字显示不出来的情况。
（3）
font-display: fallback
这个值设置阻塞期的长度是100毫秒，即文字有100毫秒显示不出来，然后立即进入替换期。等到字体下载结束，再使用下载的字体渲染。
（4）
font-display: optional
这个值设置阻塞期也是100毫秒。然后，等到100毫秒结束，浏览器发现字体已经下载完成，就使用下载的字体渲染，否则就不再下载，永久性使用替代字体渲染。它主要用于网速较慢的环境，不让用户长时间等到字体下载。
一般来说，正常情况下都推荐使用
font-display:optional。如果是图标字体等没有替代字体的情况下，可以使用
font-display: block。
参考链接
Font-display, by Monica Dinculescu

函数
CSS 提供一些函数，方便操作。
minmax
minmax提供一个长度范围，不小于较小值，不大于较大值。
minmax( min, max )
如果第二个参数
max小于第一个参数
min，那么
max会被忽略，等同于将长度设置为
min。
minmax(400px, 50%)
minmax(30%, 300px)
网格布局中，
max也允许设置为比例因子
fr，但
min不能设置为
fr。
minmax(200px, 1fr)
网格布局中，还可以使用关键字
max-content和
min-content，分别表示最大的和最小的可分配宽度。
minmax(100px, max-content)
minmax(min-content, 400px)
关键字
auto在
max位置等同于
max-content，在
min位置等同于
min-content。
minmax(max-content, auto)
minmax(auto, 300px)
minmax(min-content, auto)
image-set()
image-set()用来选取符合响应式条件的图片。
background-image: image-set( "foo.png" 1x, "foo-2x.png" 2x);

图像处理
filter
filter命令支持以下函数。
url()：使用svg滤镜
blur()：高斯模糊
brightness()：亮度
contrast()：对比度
drop-shadow()：阴影
grayscale()：灰度
hue-rotate()：色调旋转
invert()：色调分离
opacity()：透明
saturate()：饱和度
sepia()：加入褐色色调
filter: saturate(200%);
filter: sepia(100%);
filter: opacity(50%);
filter: url(resources.svg#c1);
filter: blur(5px);
filter: invert(100%);
filter: hue-rotate(90deg);
filter: brightness(0.5);
filter: contrast(200%);
filter: grayscale(50%);
filter: grayscale(0.5) blur(10px);
filter: drop-shadow(16px 16px 10px black);

CSS 概述
简介
CSS 用于定义网页的样式，比如每个网页元素的位置、大小、颜色等等。
CSS 随着网页的诞生而诞生。1996年12月，CSS 1.0 标准问世，目前广泛使用的是2000年4月发布的 CSS 3 标准。
CSS 3 采用模块化结构，每个模块都是独立定义的，定义完成以后，再加入 CSS 标准。截止2017年，CSS 共有88个模块，下面是其中一次主要模块。
Display
Box alignment
Flexible box
CSS Grid
Inline Layout
Position Layout
CSS Shapes
CSS Transforms
CSS 样式表就是一个文本文件，定义每个网页元素的样式规则。
样式规则
CSS 样式表由大量样式规则组成。每条样式规则分成两个部分：选择器（selector）和声明块（declaration block）。
选择器指明本条规则对哪些网页元素生效，声明块描述样式规则的具体内容。
h1 {
  color: red;
}
上面代码是一条样式规则，其中
h1是选择器，大括号的部分就是声明块。这个规则的意思是，
h1元素的颜色为红色。
声明块的内容，放在一对大括号里面。大括号之中是一个或多个键值对，每个键值对用分号结尾，给出一条样式描述。键值对的顺序并不重要。
h1 {
  background-color: yellow;
  color: red;
}
上面代码中，声明块里面包含两条样式描述，它们的顺序不重要，完全可以对调位置。
声明块可以写成多行，也可以写成一行。缩进和换行只是为了增加可读性，CSS 引擎会忽略它们。
h1 { color: red; }
上面代码中，声明块写成了一行。它与写成多行的效果是一样的。
CSS 允许重复声明某个样式，这时最后声明的键值对会覆盖前面的键值对。
h1 {
  color: red;
  color: black;
}
上面代码中，颜色属性申明了两次。后面声明的黑色，会覆盖前面声明的红色。
声明块里面的键值对，由键名和键值组成。键名称为 CSS 属性（property），由 CSS 标准给出，键值是该属性允许被赋予的一个值。
学习 CSS，主要就是学习各种各样的 CSS 属性。
CSS 注释
CSS 使用
/* ... */表示注释，可以是单行，也可以是多行。
h1 { /* 这是单行注释 */
  color: red;
}
/* 这是多行注释
h1 {
  color: red;
}
*/
上面代码中，多行注释包含整个
h1的样式规则，这意味着这个样式规则不会生效。
注意：注释不能嵌套。
CSS 的继承
某些 CSS 属性不仅影响网页元素本身，还会影响该元素的后代元素，这称为 CSS 的继承。
最典型的例子就是字体属性
font-family，网页根元素
html设置了字体以后，该网页的所有元素都会默认使用指定的字体。
以下是常见的可以继承的 CSS 属性。
文本
color（颜色，a元素除外）
direction（方向）
font（字体）
font-family（字体系列）
font-size（字体大小）
font-style（用于设置斜体）
font-variant（用于设置小型大写字母）
font-weight（用于设置粗体）
letter-spacing（字母间距）
line-height（行高）
text-align（用于设置对齐方式）
text-indent（用于设置首行缩进）
text-transform（用于修改大小写）
visibility（可见性）
white-space（用于指定如何处理空格）
word-spacing（字间距）
列表
list-style（列表样式）
list-style-image（用于为列表指定定制的标记）
list-style-position（用于确定列表标记的位置）
list-style-type（用于设置列表的标记）
表格
border-collapse（用于控制表格相邻单元格的边框是否合并为单一边框）
border-spacing（用于指定表格边框之间的空隙大小）
caption-side（用于设置表格标题的位置）
empty-cells（用于设置是否显示表格中的空单元格）
页面设置（对于印刷物）
orphans（用于设置当元素内部发生分页时在页面底部需要保留的最少行数）
page-break-inside（用于设置元素内部的分页方式）
widows（用于设置当元素内部发生分页时在页面顶部需要保留的最少行数）
其他
cursor（鼠标指针）
quotes（用于指定引号样式）
样式的优先级
如果多条规则都对同一个网页元素指定样式，只要 CSS 属性不发生冲突，那么这些规则都是有效的。
如果 CSS 属性发生冲突，那就存在一个优先级的问题：哪一条规则优先生效？
CSS 采用以下规则，决定样式规则的优先级。
特殊性（specificity）
顺序（order）
重要性（importance）
特殊性指的是选择器的具体程度，选择器越特殊，规则就越强。遇到冲突时，优先应用特殊性强的规则。特殊性最低的是元素名本身，然后是元素的
class属性，特殊性最高的是
id属性。建议在样式表中多使用
class选择器，避免使用
id选择器，这样的灵活性最好。
规则指的是，同样特殊性的规则，晚出现的优先级高。
重要性指的是，特别注明某条规则的重要程度要比其他所有规则高，方法是在声明的末尾加上
!important。由于可维护性很差，一旦出现问题，很难排查，除非是殊情况，否则不推荐使用这种方法。
p {
  color: orange !important;
}
样式表嵌入网页的方法
HTML 网页采用
<link>标签将 CSS 样式表嵌入网页。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Demo</title>
    <link rel="stylesheet" href="style.css" />
</head>
<body>
  ... ...
</body>
</html>
上面代码中，
<link>标签放在
<head>内部，
rel="stylesheet"指明这是样式表，
href属性给出样式表文件的网址。浏览器解析到这一行代码，就会去加载样式表。
上例的样式表文件是
style.css。样式表的后缀名通常是
.css，但也可以是其他后缀名。
网页也可以使用
<style>标签，直接包含样式规则。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Demo</title>
    <style>
    img {
        border: 4px solid red;
    }
    </style>
</head>
<body>
  ... ...
</body>
</html>
上面代码中，
<head>内部的
<style>标签直接包含了样式规则。
最后，针对某个网页元素的样式，也可以写在该元素的
style属性。
<img src="demo.jpg" style="border: 4px solid red;">
上面代码中，
style属性指定了
img元素的样式。
style属性只对当前元素生效，需要一个个指定，非常麻烦。由于多个样式表可以同时对一个元素生效，
style属性维护起来非也常困难，所以不建议使用，一般只用于 JavaScript 脚本指定动态样式，以及某些特殊情况。
内联样式由于位于外部样式表和嵌入样式表之后，优先级高于其他所有样式，除非其他地方与之冲突的样式标记了
!important。

响应式布局：media query
响应式布局（responsive）的含义是，网页会根据不同的媒介，自动采用不同的 CSS 规则。它主要通过 media 命令实现。
media命令用来规定 CSS 规则生效的媒介。
@media命令后面使用关键词，指定生效的条件。
@media print {
   …
}
@media screen {
   …
}
上面代码中，打印和显示屏分别使用不同的 CSS 规则。
媒介名称之前，还可以使用
not和
only关键字。
@media not screen {
   …
}
@media only screen {
   …
}
@media还允许使用表达式，指定 CSS 生效的条件。表达式可以放在圆括号之中。
@media (min-width: 800px) {
  p {
    font-size: 18px;
  }
}
上面代码中，
media命令规定，只有在屏幕宽度大于等于
800px时，
p元素的大小才等于
18px。
如果同时需要满足多个条件，可以使用
and关键字。下面的例子是为不同的设备指定不同的背景图片。
/* default is desktop image */
.someElement { background-image: url(sunset.jpg); }
@media only screen and (max-width : 1024px) {
  .someElement { background-image: url(sunset-small.jpg); }
}
下面是另一个例子。
.component__header {
  font-size: 2rem;
  @media (min-width: 1200px) {
    font-size: 3rem
  }
}
@media only screen
  and (max-width : 603px)
  and (max-height : 966px) {
  /* Styles here */
}

基本操作
垂直置中
（1）方法一
原理：子元素的 top, right, bottom, left, margin, and padding属性，针对的是父元素的维度；transform针对的子元素本身的维度。
父元素、子元素需有明确高度，不能是auto。
.children{
	background: #ffdb4c;
	height: 300px;
	position: relative;
	top: 50%;
	transform: translateY(-50%);
}
（2）方法二
.parent { position: relative; }
.child {
    position: absolute;
    left: 50%;
    top: 50%;
    -webkit-transform: translate(-50%, -50%);
    -moz-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
    -o-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}
（3）方法三
.parent { display: table; }
.child {
  display: table-cell;
  vertical-align: middle;
}
（5）行内置中
.parent { line-height: 500px; }
.child {
    display: inline-block;
    vertical-align: middle;
}
（6）方法四（只对图片有效）
.thumb {
  background-image: url(my-img.jpg);
  background-position: center;
  /* is this supported by IE8? I don't know */
  background-size: cover;
  height: 0;
  overflow: hidden;
  padding-bottom: 50%;
  width: 50%;
}
（7）方法五
.children {
  margin-top: calc(50% - 12.5%);
}
（8）方法六
.container {
  display: flex;
  justify-content: center;
  align-items: center;
}
（9）参考链接
Alignment and sizing in CSS
清理浮动
.clearfix:after{
  visibility:hidden;
  display:block;
  font-size:0;
  content:" ";
  clear:both;
  height:0;
}
.clearfix{
  zoom:1; /* for IE6 IE7 */
}

position
position属性用来指定一个元素在网页上的位置，一共有5种定位方式，即
position属性主要有五个值。
static
relative
fixed
absolute
sticky
下面就依次介绍这五个值。
static 属性值
static是
position属性的默认值。如果省略
position属性，浏览器就认为该元素是
static定位。
这时，浏览器会按照源码的顺序，决定每个元素的位置，这称为“正常的页面流”（normal flow）。每个块级元素占据自己的区块（block），元素与元素之间不产生重叠，这个位置就是元素的默认位置。
注意，
static定位所导致的元素位置，是浏览器自主决定的，所以这时
top、
bottom、
left、
right这四个属性无效。
relative，absolute，fixed
relative、
absolute、
fixed这三个属性值有一个共同点，都是相对于某个基点的定位，不同之处仅仅在于基点不同。所以，只要理解了它们的基点是什么，就很容易掌握这三个属性值。
这三种定位都不会对其他元素的位置产生影响，即不管有没有这个元素，其他元素的位置不变，因此元素之间可能产生重叠。
relative 属性值
relative表示，相对于默认位置（即
static时的位置）进行偏移，即定位基点是元素的默认位置。
它必须搭配
top、
bottom、
left、
right这四个属性一起使用，用来指定偏移的方向和距离。
div {
  position: relative;
  top: 20px;
}
上面代码中，
div元素从默认位置向下偏移
20px（即距离顶部
20px）。
absolute 属性值
absolute表示，相对于祖先元素（一般是父元素）进行偏移，即定位基点通常是父元素。
它有一个重要的限制条件：父元素不能是
static定位，否则定位基点会移到最近一个非
static定位的祖先元素。如果所有祖先元素都是
static定位，定位基点就变成整个网页的根元素
html。另外，
absolute定位也必须搭配
top、
bottom、
left、
right这四个属性一起使用。
/*
  HTML 代码如下
  <div id="father">
    <div id="son"></div>
  </div>
*/
#father {
  positon: relative;
}
#son {
  position: absolute;
  top: 20px;
}
上面代码中，父元素是
relative定位，子元素是
absolute定位，所以子元素的定位基点是父元素，相对于父元素的顶部向下偏移
20px。如果父元素是
static定位，上例的子元素就是距离网页的顶部向下偏移
20px。
注意，
absolute定位的元素会被“正常页面流”忽略，即在“正常页面流”中，该元素所占空间为零，周边元素不受影响。
fixed 属性值
fixed表示，相对于视口（viewport，浏览器窗口）进行偏移，即定位基点是浏览器窗口。这会导致元素的位置不随页面滚动而变化，好像固定在网页上一样。
它如果搭配
top、
bottom、
left、
right这四个属性一起使用，表示元素的初始位置是基于视口计算的，否则初始位置就是元素的默认位置。
div {
  position: fixed;
  top: 0;
}
上面代码中，
div元素始终在视口顶部，不随网页滚动而变化。
四、sticky 属性值
sticky跟前面四个属性值都不一样，它会产生动态效果，很像
relative和
fixed的结合：一些时候是
relative定位（定位基点是自身默认位置），另一些时候自动变成
fixed定位（定位基点是视口）。
因此，它能够形成“动态固定”的效果。比如，网页的搜索工具栏，初始加载时在自己的默认位置（
relative定位）。
页面向下滚动时，工具栏变成固定位置，始终停留在页面头部（
fixed定位）。
等到页面重新向上滚动回到原位，工具栏也会回到默认位置。
sticky生效的前提是，必须搭配
top、
bottom、
left、
right这四个属性一起使用，不能省略，否则等同于
relative定位，不产生“动态固定”的效果。原因是这四个属性用来定义“偏移距离”，浏览器把它当作
sticky的生效门槛。
它的具体规则是，当页面滚动，父元素开始脱离视口时（即部分不可见），只要与
sticky元素的距离达到生效门槛，
relative定位自动切换为
fixed定位；等到父元素完全脱离视口时（即完全不可见），
fixed定位自动切换回
relative定位。
请看下面的示例代码。（注意，除了已被淘汰的 IE 以外，其他浏览器目前都支持
sticky。但是，Safari 浏览器需要加上浏览器前缀
-webkit-。）
#toolbar {
  position: -webkit-sticky; /* safari 浏览器 */
  position: sticky; /* 其他浏览器 */
  top: 20px;
}
上面代码中，页面向下滚动时，
#toolbar的父元素开始脱离视口，一旦视口的顶部与
#toolbar的距离小于
20px（门槛值），
#toolbar就自动变为
fixed定位，保持与视口顶部
20px的距离。页面继续向下滚动，父元素彻底离开视口（即整个父元素完全不可见），
#toolbar恢复成
relative定位。
五、 sticky 的应用
sticky定位可以实现一些很有用的效果。除了上面提到“动态固定”效果，这里再介绍两个。
5.1 堆叠效果
堆叠效果（stacking）指的是页面滚动时，下方的元素覆盖上方的元素。下面是一个图片堆叠的例子，下方的图片会随着页面滚动，覆盖上方的图片（查看 demo）。
HTML 代码就是几张图片。
<div><img src="pic1.jpg"></div>
<div><img src="pic2.jpg"></div>
<div><img src="pic3.jpg"></div>
CSS 代码极其简单，只要两行。
div {
  position: sticky;
  top: 0;
}
它的原理是页面向下滚动时，每张图片都会变成
fixed定位，导致后一张图片重叠在前一张图片上面。详细解释可以看这里。
5.2 表格的表头锁定
大型表格滚动的时候，表头始终固定，也可以用
sticky实现（查看 demo）。
CSS 代码也很简单。
th {
  position: sticky;
  top: 0; 
}
需要注意的是，
sticky必须设在
<th>元素上面，不能设在
<thead>和
<tr>元素，因为这两个元素没有
relative定位，也就无法产生
sticky效果。详细解释可以看这里。
z-index
z-index表示元素重叠时的层次关系。这个值越高，对应的元素就在越上层。所有元素的默认
z-index是0。
由于静态布局的元素不会产生重叠，所以该属性对静态元素无效。只有元素是非静态布局（即
position属性的值不是
static），
z-index属性才有意义。如果没有设置
z-index，元素重叠时，HTML 代码中越后面出现的元素在越上层。
z-index属性的难点在于，一组设置了
z-index属性的元素，它们的堆叠顺序取决于，它们是否处在同一个堆叠上下文（stacking context）。三种情况会创建堆叠上下文。
网页的根元素（即
<html>元素）
网页元素是非静态布局，且
z-index属性不等于
auto
网页元素的
opacity属性小于1
同一个堆叠上下文之中，元素的堆叠（从下层到上层）按照以下顺序决定。
堆叠上下文的根元素
设置了定位、且
z-index为负值的元素
没有设置定位的元素
设置了定位、且
z-index为
auto的元素
设置了定位、且
z-index为正值的元素
/* HTML 代码如下
<div id="container">
  <div id="item-a">A</div>
  <div id="item-b">b</div>
</div>
<div id="item-c">C</div>
*/
div {
  width: 100px;
  height: 100px;
}
#item-a {
  background-color: red;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 3;
}
#item-b {
  background-color: blue;
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 2;
}
#item-c {
  background-color: yellow;
  position: absolute;
  top: 40px;
  left: 40px;
  z-index: 1;
}
上面代码中，
item-a在最上层，然后是
item-b，最下层是
item-c。
现在，对
item-a和
item-b父元素
container设一下定位。
#container {
  position: relative;
  z-index: 0;
}
/* 或者写成
#container {
  opacity: 0.99;
}
*/
结果就会变成
item-c在最上层，然后是
item-a，最下层是
item-b。这是因为这时
container形成一个独立的堆叠上下文，
item-a和
item-b处在这个上下文之中，与
item-c不再是同一个层级的关系了。
参考链接
What No One Told You About Z-Index, by Philip Walton

CSS 属性
inherit属性值
CSS 的许多属性可以继承，即子元素默认继承父元素的属性。比如，
body元素的字体样式，可以被页面的所有元素继承。
body {
  font-family: Arial, Helvetica, sans-serif;
}
上面代码中，
body设置了
font-family了，它的后代元素就不用设置这个属性了，除非需要改变字体。
根据标准，以下 CSS 属性可以继承。
azimuth
border-collapse
border-spacing
caption-side
color
cursor
direction
elevation
empty-cells
font-family
font-size
font-style
font-variant
font-weight
font
letter-spacing
line-height
list-style-image
list-style-position
list-style-type
list-style
orphans
pitch-range
pitch
quotes
richness
speak-header
speak-numeral
speak-punctuation
speak
speech-rate
stress
text-align
text-indent
text-transform
visibility
voice-family
volume
white-space
widows
word-spacing
其他属性默认不能继承，比如
border属性。父元素设置了
border以后，子元素如果要有边框，必须重新设一遍。
.main-list {
  border: 1rem solid #000;
  color: red;
  font-family: Verdana
}
.sub-list {
  border: 1rem solid #000;
}
上面代码中，
.sum-list是
.main-list的子元素，两者的边框必须各自设置。
CSS 提供了
inherit属性值，如果要让子元素继承父元素的属性，可以使用这个属性值。
.main-list {
  border: 1rem solid #000;
  color: red;
  font-family: Verdana;
}
.sub-list {
  border: inherit;
}
上面代码中，
.sub-list的
border属性，就继承了
.main-list，从而两者的边框都一样。它的好处是，如果要修改边框，只要修改一处即可。
initial 属性值
initial属性值可以将 CSS 属性设回初始值。它的主要用处是，让那些默认继承父元素的 CSS 属性不再继承，回到初始值。
.berries {
  border: 1rem solid #000;
  color: red;
  font-family: Verdana;
  margin-bottom: 10px;
}
.berries h1 {
  color: initial;
}
上面代码中，
.berries是
h1的父元素，而
color属性是可以继承的，如果不设置
h1的颜色，
h1就会是红色的。现在
h1的
color设为
initial，就不再继承父元素的颜色，而是回到浏览器给予
h1的默认颜色，即黑色。
unset 属性值
unset属性值的作用是，如果存在继承，则继承父元素的值（等同于
inherit），如果不存在继承，则重置为初始值（等同于
initial）。
unset的意思，就是去除当前样式表对该元素的样式设置。
h1 {
  color: blue;
}
div {
  border: 1rem solid #000;
  color: red;
  font-family: Verdana;
  margin-bottom: 10px;
}
.berries h1 {
  color: unset;
}
上面代码中，
div是
h1的父元素，如果不设置
.berries h1的
color属性，
h1会显示为蓝色，设成
color: unset以后，
h1继承了父元素的
color，显示为红色。
unset与
inherit的区别在于，如果不设置
div的
color，那么
.berries h1将显示为浏览器赋予的默认颜色（黑色），而不是红色。
h1 {
  color: blue;
}
div {
  border: 1rem solid #000;
  font-family: Verdana;
  margin-bottom: 10px;
}
.berries h1 {
  color: unset;
}
上面代码中，父元素
div没有设置颜色，这时子元素
.berries h1将显示为浏览器默认颜色（黑色），而不是蓝色。
revert 属性值
revert属性值用于消除当前样式表对该元素设置的样式，这也是它名字的含义（
还原），基本等同于
unset。具体来说，如果存在继承，该元素会显示继承的属性值，如果不存在继承，则分成以下两种情况。
revert用在网站提供的样式表：则显示用户演示表设置的值。如果不存在用户样式表，则浏览器赋予的默认值。
revert用在用户提供的样式表：显示浏览器赋予的默认值。
我们知道，样式表可以分成三层：用户提供的样式表，可以覆盖网站提供的样式表；网站提供的样式表，又可以覆盖浏览器的默认样式表。
revert主要针对的就是多层样式表同时存在的情况，然后用于去除本层样式表对元素的影响。
大多数情况下，
revert与
unset是一样的，主要差异是 CSS 属性的初始值与浏览器的默认值可能有差异。
<h3 style="font-weight: unset;">hello</h3>
<h3 style="font-weight: revert;">hello</h3>
上面代码中，
font-weight: unset会回到
font-weight的初始值，即
normal。而
<font-weight: revert>会回到浏览器对
h3的
font-weight默认值，一般是粗体。
如果想要清除当前样式表对该元素的所有设置，可以使用
all: revert。
<h3 style="all: revert;">hello</h3>
background-blend-mode
background-blend-mode属性指定背景的颜色混合模式，共有16个值可取：normal（默认值，即不混合）, multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, hue, saturation, color and luminosity（显示单色效果）。
可以显示多张背景图片的混合，或者背景图片与背景色的混合。
  background-image: url(...g);
  background-color: #51B7D3;
  background-blend-mode: luminosity;
background-image
background属性可以同时指定背景图和背景颜色。
body {
  background: url(sweettexture.jpg) blue;
}
background-position
background-position指定背景图的位置。
background-position: 100px 5px;
位置属性可以指定关键字。
top
right
bottom
left
center
background-blend-mode
background-blend-mode用于指定两种颜色混合的方式。
div {
  background: url(img/pattern.png), url(img/jellyfish.jpg), #f07e32;
  background-blend-mode: screen;
}
Demo：http://codepen.io/tutsplus/live/wMvoyj
教程：http://webdesign.tutsplus.com/tutorials/blending-modes-in-css-color-theory-and-practical-application--cms-25201
border-image
在边框上显示图像。
content
指定伪元素的内容。
.myDiv:after {
  content: "I am hardcoded text from the *content* property";
}
div[data-line]:after {
  content: attr(data-line); /* 属性名没有引号 */
}
div[data-line]:after {
  content: "[line " attr(data-line) "]";
}
counter
counter用来实现计数器。
<ol class="list">
    <li>a</li>
    <li>b</li>
    <li>c</li>
</ol>
li元素前面添加计数器的代码如下。
.list {
    counter-reset: i; //reset conunter
}
.list > li {
    counter-increment: i; //counter ID
}
.list li:after {
    content: "[" counter(i) "]"; //print the result
}
下面是一个高级用法的例子。
<div class="numbers">  
  <input id="one" type="checkbox"><label for="one">1</label>
  <input id="two" type="checkbox"><label for="two">2</label>
  <input id="three" type="checkbox"><label for="three">3</label>
  <input id="four" type="checkbox"><label for="four">4</label>
  <input id="five" type="checkbox"><label for="five">5</label>
  <input id="one-hundred" type="checkbox"><label for="one-hundred">100</label>
</div>  
<p class="sum">  
  Sum 
</p>  
然后，利用计数器做出一个累加计算器。
.numbers {
  counter-reset: sum;
}
#one:checked { counter-increment: sum 1; }
#two:checked { counter-increment: sum 2; }
#three:checked { counter-increment: sum 3; }
#four:checked { counter-increment: sum 4; }
#five:checked { counter-increment: sum 5; }
#one-hundred:checked { counter-increment: sum 100; }
.sum::after {
  content: '= ' counter(sum);
}
cursor
cousor属性用来指定鼠标形状。
.cursor_auto {
    cursor: auto;
}
.cursor_default {
    cursor: default;
}
.cursor_none {
    cursor: none;
}
.cursor_pointer {
    cursor: pointer;
}
.cursor_progress {
    cursor: progress;
}
.cursor_help {
    cursor: help;
}
.cursor_text {
    cursor: text;
}
.cursor_cell {
    cursor: cell;
}
.cursor_crosshair {
    cursor: crosshair;
}
.cursor_alias {
    cursor: alias;
}
.cursor_context-menu {
    cursor: context-menu;
}
.cursor_vertical-text {
    cursor: vertical-text;
}  /*not compatible with opera*/
.cursor_copy {
    cursor: copy;
}
.cursor_move {
    cursor: move;
}
.cursor_no-drop {
    cursor: no-drop;
}  /*not compatible with opera*/
.cursor_not-allowed {
    cursor: not-allowed;
}  /*not compatible with opera*/
.cursor_all-scroll {
    cursor: all-scroll;
}  /*not compatible with opera*/
.cursor_col-resize {
    cursor: col-resize;
}  /*not compatible with opera*/
.cursor_row-resize {
    cursor: row-resize;
}  /*not compatible with opera*/
.cursor_nesw-resize {
    cursor: nesw-resize;
}
.cursor_nwse-resize {
    cursor: nwse-resize;
}
.cursor_n-resize {
    cursor: n-resize;
}
.cursor_e-resize {
    cursor: e-resize;
}
.cursor_s-resize {
    cursor: s-resize;
}
.cursor_w-resize {
    cursor: w-resize;
}
.cursor_ns-resize {
    cursor: ns-resize;
}
.cursor_ew-resize {
    cursor: ew-resize;
}
.cursor_ne-resize {
    cursor: ne-resize;
}
.cursor_nw-resize {
    cursor: nw-resize;
}
.cursor_sw-resize {
    cursor: sw-resize;
}
.cursor_se-resize {
    cursor: se-resize;
}
.cursor_wait {
    cursor: wait;
}
.cursor_grab {
    cursor: grab;
}  /*only compatible with firefox and opera*/
.cursor_grabbing {
    cursor: grabbing;
}  /*only compatible with firefox and opera*/
.cursor_zoom-in {
    cursor: zoom-in;
}  /*not compatible with explorer*/
.cursor_zoom-out {
    cursor: zoom-out;
}  /*not compatible with explorer*/
.cursor_custom {
    cursor: url(image.gif), url(image.cur), auto;
}
display
display属性表示如何展示元素。
display: block;
display: flex;
filter
filter属性表示图片滤镜，支持grayscale, blur, sepia, saturate, opacity, brightness, contrast, hue-rotate, invert效果。
灰度效果。
img.bw {
  filter: grayscale(1);
}
动画效果。
img.bw {
	filter: grayscale(0);
}
img.bw.grey {
	filter: grayscale(1);
	transition-property: filter;
	transition-duration: 1s;	
}
其他例子。
/* 模糊 */
.myElement {
	-webkit-filter: blur(2px);
}
/* 组合效果 */
.myElement {
	-webkit-filter: blur(2px) grayscale(.5) opacity(0.8);
}
模糊与鼠标悬停效果相结合。
.spoiler {
	-webkit-filter: blur(20px);
	-webkit-transition-property: -webkit-filter;
	-webkit-transition-duration: .4s;
}
.spoiler:hover, .spoiler:focus {
	-webkit-filter: blur(0px);
}
flex
flex功能可以指定容器采用弹性布局。
div{
  display: flex;
}
filter
filter属性在指定元素上应用滤镜。
blur()：模糊，参数为模糊半径
brightness()：亮度，0%为全黑，100%为原始亮度
contrast()：对比度，0%为全黑，100%为原始对比度
grayscale()：灰度，0%为原始色彩，100%为完全灰度。
hue-rotate()：色调，0为原始色调，360为色彩轮旋转一周后回到原色调。
invert()：负片效果，0%为原始效果，100%为完全负片效果。
opacity()：透明度，0%为完全透明，100%为完全不透明。
saturate()：饱和度，0%为完全不饱和，100%为完全饱和。
sepia()：作旧效果，0%为原始效果，100%为完全作旧
drop-shadow()：阴影效果，设置同box-shadow接近
url()：引用定义在SVG文件中的滤镜
多个滤镜可以联合使用。
filter: sepia(1) brightness(150%) contrast(0.5);
mix-blend-mode
mix-blend-mode属性指定前景与背景的颜色混合模式，即前景色与背景色的混合。它的取值同background-blend-mode属性一样，也是16个值。
object-fit
定义内容如何适应容器的高和宽，比如不同大小的图片，如何放在同一个位置。
img {
  height: 100px;
  width: 100px;
  object-fit: contain;
}
object-fit可能的值共有五个。
object-fit: fill
object-fit: contain
object-fit: cover
object-fit: none
object-fit: scale-down
contain：图片自动升缩，以固有的长宽比，完整显示在容器中。
fill：图片自动填满容器，即使破坏原有的长宽比。
cover：保留图像的长宽比，但会自动升缩以填满容器，长度或宽度中较小的一个会完全在容器中展示，较大的一个会溢出。
none：完全忽视容器的大小，使用图片固有的长宽比。
scale-down: none或者contain中导致图片尺寸较小的那个值。
cover表示自动将图像的中心点，放置到容器的中心点，同时根据容器的大小，截取自身的大小。
img {
  object-fit: cover;
}
参考链接
MDN, object-fit
Chris Nager, Center and crop images with a single line of CSS
Chris Mills, Exploring object-fit
object-position
object-position设置容器中的对象（通常是图片）的垂直和水平位置，与background-position设置背景图片的写法相同。
img {
  height: 100px;
  width: 100px;
  object-fit: contain;
  object-position: top 70px;
}
pointer-events
该属性定义当前图形对象会不会成为鼠标动作的目标。
/* 图片将对鼠标行为无反应 */
img {
  pointer-events: none;
}
a[href="http://example.com"] {
  pointer-events: none;
}
一旦pointer-events设为none，就不会触发JavaScript事件。在该元素上点击，任何addEventListener添加的回调函数，都不会触发。
text-overflow
该属性定义了文本超出容器宽度后，如何处理。如果将多余文字显示成三点的省略号，可以像下面这样设置。
.ellipsis {
    overflow: hidden; 
    white-space: nowrap; 
    text-overflow: ellipsis;
}
上面代码第一行是隐藏溢出，第二行是防止断行，第三行是在行尾加上省略号。
position
position属性用来确定元素的定位。
position: relative;
position: sticky;
position: absolute;
position: fixed;
transition
/* Format */
transition: property || duration || timing-function || delay
/* Various Examples */
transition: all 300ms ease 0;
transition: all 0.5s ease-in-out 0;
transition: background 300ms cubic-bezier(.61,-0.67,0,1.45) 0;
transition: opacity 100ms ease 0, background 200ms ease-in-out 0, transform 200ms ease-out 0;
/* Cross Browser Prefixes */
-webkit-transition: all 300ms ease 0;
-moz-transition: all 300ms ease 0;
-o-transition: all 300ms ease 0;
transition: all 300ms ease 0;

响应式布局
图片自适应各种屏幕的写法。
img {
  width: 100%;
  height: auto;
}
如果使用
<img>或
<picture>元素的
srcset属性，上面这样的写法就够了。但是，对于普通的
<img>元素，还要加上
max-width: 100%;，这是为了防止图片大于容器宽度的情况。

变形
transform命令用于元素的变形，它有多种设置。
transform: scaleX(-1);
上面命令设置元素的
x坐标沿水平轴翻转，
y坐标不变。
scaleX(-1)会起到水平翻转的效果。

CSS的单位
inherit
大多数 CSS 属性默认继承它的父元素的设定，但是有一些属性默认不继承。比如，
input元素和
textarea元素的 CSS 属性，都是不继承父元素的。这时，可以强制它们继承。
* {
  font-family: inherit;
  line-height: inherit;
  color: inherit;
}
html {
  font-size: 125%;
  font-family: sans-serif;
  line-height: 1.5;
  color: #222;
}
上面代码中，首先强制所有元素的
font-family、
line-height和
color属性都继承父元素，然后在网页的根元素
html上设置具体的值。
em
em是一种相对单位，
1em等于当前元素的
font-size。一般来说，浏览器默认的字体大小是16像素，所以
1em默认等于16像素。
h1 { font-size: 20px } /* 1em = 20px */
p { font-size: 16px } /* 1em = 16px */
上面代码中，对于
h1元素，
1em相当于
20px；对于
p元素，
1em相当于
16px。
如果当前元素没有指定字体的像素大小，那么
1em等于父元素字体的像素大小。这一点非常重要，务必牢记。
html { font-size: 16px }
h1 { font-size: 2em } /* 16px * 2 = 32px */
上面代码中，
h1元素的字体大小是
2em，但是它没有指定像素字体大小，因此
2em等于2倍的父元素像素字体大小，也就是
32px。
em的一大好处是，很容易保持不同元素之间的比例关系，因此它比像素单位更合适用来设定字体大小。
html { font-size: 100%; }
h1 { font-size: 2em; }
p { font-size: 1em; }
上面代码中，
h1的字体大小就是
p的2倍。
整个网页的字体大小，如果全部使用
em单位，不使用像素单位，会引发一个问题。
em将会基于父元素计算，从而出现累积效应。
html { font-size: 100%; } /* 默认是 16px */
div { font-size: 2em; } /* 字体大小 32px */
p { font-size: 1em; } /* 字体大小 32px */
上面代码中，
html是
div的父元素，所以
div的
1em是基于
html计算的，因此
2em字体大小等于
32px。另一方面，
div是
p的父元素，所以
p的
1em实际上也是
32px。
除了字体大小，其他许多属性也可以使用
em，比如
margin和
padding，相当于间接由
font-size决定。
.header {
  font-size: 16px;
  padding: 0.5em 0.75em; /* 相当于 8px 12px */
  background: #7F7CFF;
}
上面代码中，
.header元素的字体大小是
16px，因此
1em等于
16px，所以
padding就相当于
8px 12px。
这里比较混淆的是，如果
font-size也使用
em，两者的计算基点是不一样的。
h1 {
  font-size: 2em; /* 1em = 16px */
  padding： 1em;  /* 1em = 32px */
}
上面代码中，
font-size是基于父元素计算的，如果父元素的字体大小是
16px，那么
font-size就是
32px；
padding是基于
font-size计算的，由于
h1的
font-size是
32px，所以
padding就是
32px。
由于以上的累积效应和计算基点差异的原因，造成
em不容易精确控制，实际开发中往往改用
rem。
rem
rem单位与
em几乎完全一致，只有一个差异，它总是等于根元素
<html>的
font-size大小，与当前元素或父元素的设置无关，这就避免了
em的缺陷。
h1 {
  font-size: 2rem; /* 1rem = 16px */
  margin-bottom: 1rem;
}
p {
  font-size: 1rem; /* 1rem = 16px */
  margin-bottom: 1rem;
}
上面代码中，不管
<h1>和
<p>在什么位置，
1rem的大小总是不变的。
那么，何时使用
rem，何时使用
em呢？一个规则是字体大小
font-size属性使用
rem，其他必须等比例缩放的属性使用
em。下面是一个例子。
button {
  font-size: 0.875rem;
  padding: .5em 1em;
  border: .125em solid #e3e3e3;
  @media (min-width: 48rem){ /* min-width: 768px */
    font-size: 1.125rem;
  }
  @media (min-width: 62rem){ /* min-width: 992px */
    font-size: 1.375rem;
  }
}
上面代码中，随着屏幕宽度的变化，字体大小会跟着改变，
padding和
border会始终保持比例关系。
vh，vw
vh表示百分之一的浏览器视口高度，
vw表示百分之一的浏览器视口宽度。每当视口的高度和宽度发生变化，它们就会自动重新计算。
html { font-size: 3vw; }
上面代码中，如果视口宽度增加，字体大小也会增加；视口宽度减小，字体大小也会减小。但是，如果宽度太小（比如
320px），这样算出来的字体会太小（
3px）；如果宽度太大（比如
1440px），字体又会太大（
43px）。因此，可以考虑使用
calc函数。
html { font-size: calc(18px + 0.25vw); }
vmin，vmax
vmin表示
vh与
vw之中较短的那个单位，
vmax则表示较长的那个单位。
一般来说，PC的屏幕是屏宽大于屏高，手机的屏幕是屏高大于屏宽。所以，很可能会出现，某一个区域在PC屏幕中宽度较小，在手机屏幕中宽度较大。这时，这两个单位就可以派上用处了。
h1 {
  font-size: 20vmin;
}
注意，上面的
h1使用
vmin单位时，当宽屏设备的视口宽度缩小时，它的字体大小是不变的，因为视口的高度没有改变。
ch
ch表示多少个字符。
width: 40ch;
上面代码表示宽度为40个字符。
calc()
calc方法用于计算值，常用于两种不同的单位之间的计算（比如百分比和绝对长度）。
实例1。每行放置4张图片，可以采用如下的代码。
img {
  float: left;
  width: calc(25% - 20px);
  margin: 10px;
}
实例2。动态排列图片，可以配合media query。
img {
  float: left;
  margin: 10px;
  width: calc(100% * 1 / 4 - 20px);
}
@media (max-width: 900px) {
  img {
    width: calc(100% * 1 / 3 - 20px);
  }
}
@media (max-width: 600px) {
  img {
    width: calc(100% * 1 / 2 - 20px);
  }
}
@media (max-width: 400px) {
  img {
    width: calc(100% - 20px);
  }
}
attr()
attr()用于读取网页元素的属性值。
div[data-line]:after { 
	content: "[line " attr(data-line) "]"; 
}
参考链接
Zell, REM vs EM – The Great Debate

打印样式
基本用法
@media print命令可以设置打印样式，即用户选择打印当前网页时，生效的 CSS 规则。
@media print {
  h1 { font-size: 16pt; }
}
上面代码设置的
h1样式，对屏幕浏览不产生效果，只有用户打印网页时才会生效。
@media print命令可以与正常样式规则混合使用。
p { margin: 1em 0; }
@media print {
  .related-articles { display: none; }
}
上面代码中，
p元素的样式对屏幕浏览和打印都有效，
.related-articles的样式只对打印有效。
如果要设置某些规则只对屏幕浏览有效，可以像下面这样写。
@media screen {
  /* 只对屏幕浏览有效 */
}
@media print {
  /* 只对打印有效 */
}
分页符
分页符属性用来设置页面的分页（即另起一页），共有三个相关属性。
page-break-before：元素之前分页
page-break-after：元素之后分页
page-break-inside：元素内部分页
这三个属性的值都是两个：
always（生效）和
avoid（避免）。
h1 {
  /* 总是在 h1 元素之前分页 */
  page-break-before: always;
}
section.city-map {
  /* 在元素之前和之后分页，即该元素单独占据一页 */
  page-break-before: always;
  page-break-after: always;
}
table {
  /* 表格尽可能不要分页 */
  page-break-inside: avoid;
}
orphans 属性，widow 属性
orphans属性和
widow属性设置某个元素如何跨页拆分。
orphans属性设置跨页前的行数少于多少行时，所有行都移到下一页打印。
p {
  orphans: 3;
}
上面代码设置，如果某个段落出现在上一页的结尾少于3行（比如只有两行），那么该段落全部移到下一页显示。
widow属性设置出现在新页面的行数，最少应该有几行。
p {
  widow: 2;
}
上面代码设置，如果某个段落出现在新页面的开头少于两行（比如只有一行），那么该段落全部移到上一页显示。
@page 命令
@page命令主要用来定义页面距。
@page {
  margin: 2cm;
}
此外，还可以用
:first、
:last、
:left、
:right和
:blank选择器，选中特殊页面。
@page:first {
  margin: 0;
}
上面代码设置第一页的页边距为
0。
技巧
重复表格的表头
如果希望打印表格的时候，每一页都出现表头，只需要使用
<thead>元素定义表头，
<tbody>元素定义表的数据部分即可。
<table>
  <thead>
    <tr>
      <th>City</th>
      <th>Population</th>
  </thead>
  <tbody>
    <tr>
      <td>Sydney</td>
      <td>4.627 million (2018)</td>
    </tr>
  </tbody>
</table>
上面代码中，如果表格跨页，表头的
City和
Population字段会在每一页都打印出来。
打印链接的网址
如果希望打印出链接的网址，可以使用
:after伪元素。
@media print {
  a[href]:after {
    content: "(" attr(href) ")";
  }
}
参考链接
Print CSS basics in 10 minutes, Paperplay

CSS 计数器
简介
counter-reset：新建或重置一个计数器。
counter-increment：指定计数器的值加1。
counter()：取出指定计数器的值。
counter-reset：counterName;
counter-increment: counterName;
counter(counterName);
下面是一个例子。
ul{
  counter-reset: section;
}
li{
  list-style-type: none;
  counter-increment: section;
}
li:before{
  content: counters(section, '-') '.';
}
counter-reset
counter-reset属性新建或重置计数器。计数器的值默认为
0。
可以使用第二个参数，修改计数器的默认值。
counter-reset: count -1;
上面示例将计数器的默认值设为
-1。
可以在一条语句里面，同时新建多个计数器。
counter-reset: counter1 1 counter2 4;
counter-reset: chapter section 1 page;
上面示例，第一行新建了两个计数器，第二行新建了三个计数器，并且计数器
section的默认值设为
1。
如果这个属性的值设为
none，则表示不重置计数器，可以用来取消上层规则的设置。
counter-increment
counter-increment属性默认将计数器的值加
1，但也可以使用第二个值，指定变化的幅度。
counter-increment: counter-name -1;
上面示例表示将计数器的值减
1。
可以在一条
counter-increment语句里面，同时改变多个计数器。
counter-increment: counter1 1 counter2 -4;
counter-increment: chapter section 2 page;
上面示例的第一行，计数器
counter1增加
1，计数器
counter2减去
4。第二行，计数器
chapter和
page增加
1，计数器
section增加2。
如果这个属性设为
none，表示不改变计数器的值。
counter()
counter()还有可选的第二个参数，设置计数器的值样式，默认是阿拉伯数字。
counter(countername, upper-roman)；
上面示例将计数器的值样式设为大写的罗马数字。
常用的样式值如下。
decimal-leading-zero：数字带有前导0。
lower-roman：小写的罗马数字。
upper-roman：大写的罗马数字。
lower-alpha：小写的英文字母。
upper-alpha：大写的英文字母。
也可以使用
@counter-style定义自己的规则。
@counter-style winners-list {
  system: fixed;
  symbols: url(gold-medal.svg) url(silver-medal.svg) url(bronze-medal.svg);
  suffix: " ";
}
上面示例是金牌、银牌、铜牌的计数符号。
@counter-style thumbs {
  system: cyclic;
  symbols: "\1F44D";
  suffix: " ";
}
ul {
  list-style: thumbs;
}
上面示例是将列表符号变成点赞。
@counter-style circled-alpha {
  system: fixed;
  symbols: Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ;
  suffix: " ";
}
.items {
  list-style: circled-alpha;
}
上面示例将列表符号变成带圈的英文字母。
counters()
counters()用来取出计数器的值，并且指定多重计数器之间的连接字符。
counters(name, strings, style);
它与
counter()的不同是多了一个
strings参数，表示子序号的连接字符串。
counters(countername, '-');
counters(countername, '.', upper-roman);
上面示例第一行中，计数器与子计数器的连接符号为
-。第二行为小数点。

表单的 CSS 设置
textarea
文本框（textarea）用于让用户输入大量文本。它的高度通常是固定的，如果用户输入的文本多于文本框的高度，文本框就会出现滚动条，只有拖动滚动条，才能看见文本的其余部分。
form-sizing属性让文本框具有自适应高度，随着用户输入的文本增加，而增加文本框的高度。
textarea {
  form-sizing: normal;
}
参考链接
Textareas with auto-increasing height using CSS

多栏式布局
多栏式布局是 CSS 原生提供的一种内容分栏显示的解决方案。
基本用法
column-count属性指定
div的子元素分成四栏。
div {
  column-count:4;
}
column-width属性指定每一栏的宽度。
div {
  column-width:100px;
}
上面代码中，
column-width属性指定每一栏的宽度是100像素。如果
div元素的宽度是800像素，那么内容就将分成8栏。
注意，
column-count与
column-width不应同时使用，它们之中同时只能有一个属性生效。另外，设定
position: fixed和
position: absolute子元素，将不纳入多栏式布局的栏计算。
间隔
多栏式布局对栏与栏之间的间隔，提供了如下属性。
column-gap：间隔宽度
column-rule-color：间隔线的颜色
column-rule-style：间隔线的样式，比如
dashed、
dotted等，默认是
solid
column-rule-width：间隔线本身的宽度
column-rule：
column-rule-color、
column-rule-style、
column-rule-width这三个属性的快捷形式。
div {
	column-gap: 20px;
	column-rule: 2px solid #33c;
}
上面代码指定栏与栏之间的间隔是
20px，间隔线的样式是
2px solid #33c。
column-span
column-span属性指定某个子元素可以占据多栏的宽度，比如标题。它只能设两个值
all和
none。
h2 {
  column-span: all;
}
column-fill
column-fill属性指定内容如何在多栏之间分配。
默认值
balance表示栏与栏是等高的，
auto表示只占据内容所需的空间。
内容的断点
浏览器会自己决定，内容在栏与栏之间如何断点。下面的三个属性可以调整这个行为。
break-inside属性决定子元素内部如何断点。它可以取以下值。
auto：默认值，表示子元素内部可以插入断点
avoid：避免在子元素内部插入所有类型（page、column、region）的断点
avoid-column：避免子元素内部插入栏与栏的断点
break-before属性决定子元素前方如何断点。它可以取以下值。
auto：默认值，子元素前方可以插入断点
avoid：避免在子元素前方插入所有类型（page、column、region）的断点
avoid-column：避免在子元素前方插入栏与栏的断点
column：子元素前方强制插入一个栏断点
break-after属性决定子元素后方如何断点。它可以取以下值。
auto：默认值，子元素后方可以插入断点
avoid：避免在子元素后方插入所有类型（page、column、region）的断点
avoid-column：避免在子元素后方插入栏与栏的断点
column：子元素后方强制插入一个栏断点
参考链接
Molly E. Holzschlag, CSS3 Multi-Column Layout

flex布局
网页布局（layout）是CSS的一个重点应用。
传统的布局有下面几种。
display: block;
display: inline;
display: list-item;
display: table;
display属性搭配position属性和float属性，是最常见的布局解决方案。
但是，这个方案基于盒状模型，对于那些特殊位置的布局非常不方便。比如，垂直居中就很不容易实现，代码好像一种破解，而不是正常的解决。
.element {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}
2009年，W3C提出了一种新的方案——Flex布局，用来简便地、完整地、响应式地实现各种页面布局。经过5年多的发展，Flex布局几乎得到了所有浏览器的支持。这意味着，你现在就能很安全地使用这项功能。
可以毫无疑问地说，Flex布局是未来的首选方案。本文介绍它的语法，主要是翻译和参考了下面两篇文章：A Complete Guide to Flexbox和A Visual Guide to CSS3 Flexbox Properties。
一、Flex布局是什么？
Flex 是 flexible box 的缩写，意为弹性的盒状布局，中文可以译为“弹性布局”。它的设计目的是为盒状模型提供最大的灵活性，可以在不知道容器大小或者容器大小可变的情况下，指定布局方式。
任何一个容器都可以指定为 Flex 布局。
.box {
  display: flex;
}
行内元素也可以使用 Flex 布局。
.box {
  display: inline-flex;
}
Webkit内核的浏览器，必须加上-webkit前缀。
.box{
  display: -webkit-flex; /* Safari */
  display: flex;
}
注意，设为Flex布局以后，子元素的float、clear和vertical-align属性将失效。
二、基本概念
采用 Flex 布局的元素，称为 Flex 容器（flex container），简称“容器”。它的所有子元素自动成为容器成员，称为 Flex 项目（flex item），简称“项目”。
容器默认存在两根轴：水平的主轴（main axis）和垂直的交叉轴（cross axis）。主轴的开始位置（与边框的交叉点）叫做main start，结束位置叫做main end；交叉轴的开始位置叫做cross start，结束位置叫做cross end。
项目默认沿主轴排列，在主轴占据的空间叫做 main size，在交叉轴占据的空间叫做 cross size。
三、容器的属性
以下 6 个属性设置在容器上。
flex-direction
flex-wrap
flex-flow
justify-content
align-items
align-content
3.1 flex-direction属性
flex-direction属性决定主轴的方向（即项目的排列方向）。
.box {
  flex-direction: row | row-reverse | column | column-reverse;
}
它可能有4个值。
row（默认值）：主轴为水平方向，起点在左端。
row-reverse：主轴为水平方向，起点在右端。
column：主轴为垂直方向，起点在上沿。
column-reverse：主轴为垂直方向，起点在下沿。
3.2 flex-wrap属性
默认情况下，项目都排在一条线（又称“轴线”）上。
flex-wrap属性定义，如果一条轴线排不下，如何换行。
.box{
  flex-wrap: nowrap | wrap | wrap-reverse;
}
它可能取三个值。
（1）
nowrap（默认）：不换行。
（2）
wrap：换行，第一行在上方。
（3）
wrap-reverse：换行，第一行在下方。
3.3 flex-flow
flex-flow属性是
flex-direction属性和
flex-wrap属性的简写形式，默认值为
row nowrap。
.box {
  flex-flow: <flex-direction> || <flex-wrap>;
}
下面是一个例子。
div {
	display: flex;
	flex-flow: row wrap;
}
3.4 justify-content属性
justify-content属性定义了项目在主轴上的对齐方式。
.box {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}
它可能取5个值，具体对齐方式与轴的方向有关。下面假设主轴为从左到右。
flex-start（默认值）：左对齐
flex-end：右对齐
center： 居中
space-between：两端对齐，项目之间的间隔都相等，项目与边框没有间隔。
space-around：每个项目两侧的间隔相等。所以，项目之间的间隔比项目与边框的间隔大一倍。
3.5 align-items属性
align-items属性定义项目在交叉轴上如何对齐。
.box {
  align-items: flex-start | flex-end | center | baseline | stretch;
}
它可能取5个值。具体的对齐方式与交叉轴的方向有关，下面假设交叉轴从上到下。
flex-start：交叉轴的起点对齐。
flex-end：交叉轴的终点对齐。
center：交叉轴的中点对齐。
baseline: 项目的第一行文字的基线对齐。
stretch（默认值）：如果项目未设置高度或设为auto，将占满整个容器的高度。
3.6 align-content属性
align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线，该属性不起作用。
.box {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
该属性可能取6个值。
flex-start：与交叉轴的起点对齐。
flex-end：与交叉轴的终点对齐。
center：与交叉轴的中点对齐。
space-between：与交叉轴两端对齐，轴线之间的间隔平均分布。
space-around：每根轴线两侧的间隔都相等。所以，轴线之间的间隔比轴线与边框的间隔大一倍。
stretch（默认值）：轴线占满整个交叉轴。
四、项目的属性
以下6个属性设置在项目上。
order
flex-grow
flex-shrink
flex-basis
flex
align-self
4.1 order属性
项目在主轴的排列顺序，默认是其出现的顺序。
order属性可以改变这一点，让后面出现的项目，排到前面去。
order属性定义项目的排列顺序。数值越小，排列越靠前，默认为
0。
.item {
  order: <integer>;
}
4.2 flex-grow 属性
flex-grow属性定义项目的放大比例，默认为0，即如果主轴存在剩余空间，也不放大。
.item {
  flex-grow: <number>; /* default 0 */
}
如果所有项目的
flex-grow属性都为1，则它们将等分剩余空间（如果有的话）。如果一个项目的
flex-grow属性为2，其他项目都为1，则前者占据的剩余空间将比其他项目多一倍。因此，
flex-grow也可以理解成放大的速率，
2的增长速率比
1快一倍。
flex-grow的值是一种比例关系，所有项目都设成
1，与都设成
2或
0.5，结果是一样的。
4.3 flex-shrink 属性
flex-shrink属性定义了项目的缩小比例，默认为1，即如果空间不足，该项目将缩小。
.item {
  flex-shrink: <number>; /* default 1 */
}
如果所有项目的
flex-shrink属性都为1，当空间不足时，都将等比例缩小，否则项目宽度大于容器宽度，会发生溢出。如果一个项目的
flex-shrink属性为0，其他项目都为1，则空间不足时，前者不缩小。
负值对该属性无效。
4.4 flex-basis 属性
flex-basis属性定义了在分配多余空间之前，项目占据的主轴空间（main size），即项目本身的尺寸。浏览器根据这个属性，计算主轴是否有剩余空间。它的默认值为
auto，即项目的本来大小。
.item {
  flex-basis: <length> | auto; /* default auto */
}
它可以设为跟
width或
height属性一样的值（比如350px、20%、5em等等），则项目将占据固定空间。
4.5 flex 属性
flex属性是
flex-grow, 
flex-shrink 和 
flex-basis的简写，默认值为
0 1 auto。后两个属性可选。
.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
该属性有两个快捷值：
auto (代表
1 1 auto) 和 none (代表
0 0 auto)。
4.6 align-self 属性
align-self属性允许单个项目有与其他项目不一样的对齐方式，可覆盖
align-items属性。默认值为
auto，表示继承父元素的
align-items属性，如果没有父元素，则等同于
stretch。
.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
该属性可能取6个值，除了
auto，其他都与
align-items属性完全一致。
（完）
Flex布局实例教程
上一篇文章，介绍了Flex布局的语法。
今天介绍，常见布局的Flex写法。你会看到，不管是什么布局，Flex往往都可以几行命令搞定。
下面的内容，我只列出代码，详细的语法解释请查阅《Flex布局语法教程》。
我主要参考了Landon Schropp的文章和Solved by Flexbox。
一、骰子的布局
如果不加说明，本节的HTML模板一律如下。
<div class="box">
  <span class="item"></span>
</div>
上面代码中，div元素是Flex容器，span元素是Flex项目。如果有多个项目，就要添加多个span元素，以此类推。
1.1 单项目：首行左对齐
Flex布局默认就是首行左对齐，所以一行代码就够了。
.box {
  display: flex;
}
1.2 单项目：首行居中对齐
.box {
  display: flex;
  justify-content: center;
}
1.3 单项目：首行右对齐
.box {
  display: flex;
  justify-content: flex-end;
}
1.4 单项目：中行左对齐
.box {
  display: flex;
  align-items: center;
}
1.5 单项目：垂直居中对齐
.box {
  display: flex;
  justify-content: center;
  align-items: center;
}
1.6 单项目：尾行居中对齐
.box {
  display: flex;
  justify-content: center;
  align-items: flex-end;
}
1.7 单项目：尾行右对齐
.box {
  display: flex;
  justify-content: flex-end;
  align-items: flex-end;
}
1.8 双项目：首行两端对齐
.box {
  display: flex;
  justify-content: space-between;
}
1.9 双项目：首列两端对齐
.box {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
1.10 双项目：中列两端对齐
.box {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
}
1.11 双项目：尾列两端对齐
.box {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-end;
}
1.12 双项目：首行左对齐，中行居中对齐
.box {
  display: flex;
}
.item:nth-child(2) {
  align-self: center;
}
1.13 双项目：首行左对齐，尾行右对齐
.box {
  display: flex;
  justify-content: space-between;
}
.item:nth-child(2) {
  align-self: flex-end;
}
1.14 三项目：对角线布局
.box {
  display: flex;
}
.item:nth-child(2) {
  align-self: center;
}
.item:nth-child(3) {
  align-self: flex-end;
}
1.15 四项目：首行排满，尾行右对齐
.box {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-content: space-between;
}
1.16 四项目：四角对齐
HTML代码如下。
<div class="box">
  <div class="column">
    <span class="item"></span>
    <span class="item"></span>
  </div>
  <div class="column">
    <span class="item"></span>
    <span class="item"></span>
  </div>
</div>
CSS代码如下。
.box {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
}
.column {
  flex-basis: 100%;
  display: flex;
  justify-content: space-between;
}
1.17 六项目：首行排满，尾行排满
.box {
  display: flex;
  flex-wrap: wrap;
  align-content: space-between;
}
1.18 六项目：首列排满，尾列排满
.box {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-content: space-between;
}
1.19 六项目：首行两端对齐，中行居中，尾行排满
HTML代码如下。
<div class="box">
  <div class="row">
    <span class="item"></span>
    <span class="item"></span>
    <span class="item"></span>
  </div>
  <div class="row">
    <span class="item"></span>
  </div>
  <div class="row">
     <span class="item"></span>
     <span class="item"></span>
  </div>
</div>
CSS代码如下。
.box {
  display: flex;
  flex-wrap: wrap;
}
.row{
  flex-basis: 100%;
  display:flex;
}
.row:nth-child(2){
  justify-content: center;
}
.row:nth-child(3){
  justify-content: space-between;
}
1.20 九项目
.box {
  display: flex;
  flex-wrap: wrap;
}
二、网格布局
2.1 基本网格布局
容器平均分配空间。
HTML代码如下。
<div class="Grid">
  <div class="Grid-cell">…</div>
  <div class="Grid-cell">…</div>
  <div class="Grid-cell">…</div>
</div>
CSS代码如下。
.Grid {
  display: flex;
}
.Grid-cell {
  flex: 1;
}
上面这样的设置，不管父容器之中有多少个项目，都会平分宽度。
遇到小屏幕时，可以使用 media query，让项目占满一行。
@media (max-width: 400px) {
  .flex-grid {
    display: block;
  }
}
网格之间的间隔，可以像下面这样设置。
.flex-grid-thirds {
  display: flex;
  justify-content: space-between;
}
.flex-grid-thirds .col {
  width: 32%;
}
2.2 百分比布局
某项目占据固定的百分比，其余项目平均分配空间。
HTML代码如下。
<div class="Grid">
  <div class="Grid-cell u-1of4">…</div>
  <div class="Grid-cell">…</div>
  <div class="Grid-cell u-1of3">…</div>
</div>
.Grid {
  display: flex;
}
.Grid-cell {
  flex: 1;
}
.Grid-cell.u-full {
  flex: 0 0 100%;
}
.Grid-cell.u-1of2 {
  flex: 0 0 50%;
}
.Grid-cell.u-1of3 {
  flex: 0 0 33.3333%;
}
.Grid-cell.u-1of4 {
  flex: 0 0 25%;
}
三、圣杯布局
圣杯布局（Holy Grail Layout）指的是一种最常见的网站布局。页面从上到下，分成三个部分：头部（header），躯干（body），尾部（footer）。其中躯干又水平分成三栏，从左到右为：导航、主栏、副栏。
HTML代码如下。
<body class="HolyGrail">
  <header>…</header>
  <div class="HolyGrail-body">
    <main class="HolyGrail-content">…</main>
    <nav class="HolyGrail-nav">…</nav>
    <aside class="HolyGrail-ads">…</aside>
  </div>
  <footer>…</footer>
</body>
CSS代码如下。
.HolyGrail {
  display: flex;
  min-height: 100vh;
  flex-direction: column;
}
header,
footer {
  flex: 1;
}
.HolyGrail-body {
  display: flex;
  flex: 1;
}
.HolyGrail-content {
  flex: 1;
}
.HolyGrail-nav, .HolyGrail-ads {
  /* 两个边栏的宽度设为12em */
  flex: 0 0 12em;
}
.HolyGrail-nav {
  /* 导航放到最左边 */
  order: -1;
}
如果是小屏幕，躯干的三栏改为垂直分布。
@media (max-width: 768px) {
  .HolyGrail-body {
    flex-direction: column;
    flex: 1;
  }
  .HolyGrail-nav,
  .HolyGrail-ads,
  .HolyGrail-content {
    flex: auto;
  }
}
四、输入框的布局
常常需要在输入框的前方添加提示，后方添加按钮。
HTML代码如下。
<div class="InputAddOn">
  <span class="InputAddOn-item">…</span>
  <input class="InputAddOn-field">
  <button class="InputAddOn-item">…</button>
</div>
CSS代码如下。
.InputAddOn {
  display: flex;
}
.InputAddOn-field {
  flex: 1;
}
五、悬挂式布局
有时，主栏的左侧或右侧，需要添加一个图片栏。
HTML代码如下。
<div class="Media">
  <img class="Media-figure" src="" alt="">
  <p class="Media-body">…</p>
</div>
CSS代码如下。
.Media {
  display: flex;
  align-items: flex-start;
}
.Media-figure {
  margin-right: 1em;
}
.Media-body {
  flex: 1;
}
六、固定的底栏
有时，页面内容太少，无法占满一屏的高度，底栏就会抬高到页面的中间。
这时可以采用Flex布局，让底栏总是出现在页面的底部。
HTML代码如下。
<body class="Site">
  <header>…</header>
  <main class="Site-content">…</main>
  <footer>…</footer>
</body>
CSS代码如下。
.Site {
  display: flex;
  min-height: 100vh;
  flex-direction: column;
}
.Site-content {
  flex: 1;
}
两栏式布局
对于简单的两栏式布局，Flexbox 布局相当简单。
/*
  HTML 代码如下
  <div class="wrapper">
    <section class="main-column" />
    <aside class="sidebar" />
  </div>
*/
.wrapper {
  display: flex;
}
.main-column {
  width: 70%;
  padding-right: 2rem;
}
.sidebar {
  width: 30%;
}
（完）
参考链接
Getting Dicey With Flexbox, by Landon Schropp
A Complete Guide to Flexbox
Dimitar Stojanov, A Visual Guide to CSS3 Flexbox Properties

float
简介
float属性指定某个元素定位在容器的左侧或右侧，文字和其他行内元素紧挨在它的旁边。
h4  {
  float: left;
}
如果对行内元素指定
float属性，就相当于将这个行内元素变成块级元素。
float属性可以取三个值。
left：定位在容器的左侧
right：定位在容器的右侧
none：不采用浮动定位（默认值）
清理浮动
设置
float属性以后，容器里面的行内元素（通常是文字）会紧贴浮动元素的边缘，进行布局。如果文字的长度小于浮动元素的高度，就会出现布局问题。
下面是一段 HTML 代码。
<div>
  <h2>标题一</h2>
  Hello World
</div>
<h3>标题二</h3>
其中的“标题一”是浮动的。
h2 {
  height: 200px;
  float: left;
}
由于
Hello World的高度小于“标题一”的高度，导致紧跟在后面的“标题二”，不是出现在“标题一”的下方，而是在“标题一”的右侧。这时就需要清理浮动。
h3 {
  clear: both;
}
clear属性可以取四个值。
left：左侧不能有浮动元素
right：右侧不能有浮动元素
both：两侧不能有浮动元素
none：默认值，不需要清理浮动
另一种情况是，容器内部的文本不希望紧贴浮动的元素，这时也可以使用
clear属性进行清理浮动。
对容器的影响
如果一个容器里面所有子元素都是浮动的，就会导致这个容器变成一个空容器，高度缩为
0。因为布局的时候，浮动的所有子元素是脱离父容器计算位置的，这导致渲染引擎认为这个容器是空元素。
解决这个问题，有三种方法。
（1）父容器也进行浮动。
.container-with-float{
    float: left;
    width: 100%;
}
（2）父容器添加
overflow: hidden
.container-with-overflow{
    overflow: hidden;
}
添加
overflow: hidden以后，容器计算高度的时候，就会自动将浮动的子元素考虑在内。
（3）CSS 生成内容
CSS 生成内容以后，就不会被渲染引擎当成是一个空元素。
.container-with-generated-content:after{
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}
还有另一种写法。
.grid:after {
  content: "";
  display: table;
  clear: both;
}

Grid 布局
一、概述
网格布局（Grid）是最强大的 CSS 布局方案。
它将网页划分成一个个网格，可以任意组合不同的网格，做出各种各样的布局。以前，只能通过复杂的 CSS 框架达到的效果，现在浏览器内置了。
上图这样的布局，就是 Grid 布局的拿手好戏。
Grid 布局与 Flex 布局有一定的相似性，都可以指定容器内部多个项目的位置。但是，它们也存在重大区别。
Flex 布局是轴线布局，只能指定“项目”针对轴线的位置，可以看作是一维布局。Grid 布局则是将容器划分成“行”和“列”，产生单元格，然后指定“项目所在”的单元格，可以看作是二维布局。Grid 布局远比 Flex 布局强大。
二、基本概念
学习 Grid 布局之前，需要了解一些基本概念。
2.1 容器和项目
采用网格布局的区域，称为“容器”（container）。容器内部采用网格定位的子元素，称为“项目”（item）。
<div>
  <div><p>1</p></div>
  <div><p>2</p></div>
  <div><p>3</p></div>
</div>
上面代码中，最外层的
<div>元素就是容器，内层的三个
<div>元素就是项目。
注意：项目只能是容器的顶层子元素，不包含项目的子元素，比如上面代码的
<p>元素就不是项目。Grid 布局只对项目生效。
2.2 行和列
容器里面的水平区域称为“行”（row），垂直区域称为“列”（column）。
上图中，水平的深色区域就是“行”，垂直的深色区域就是“列”。
2.3 单元格
行和列的交叉区域，称为“单元格”（cell）。
正常情况下，
n行和
m列会产生
n x m个单元格。比如，3行3列会产生9个单元格。
2.4 网格线
划分网格的线，称为“网格线”（grid line）。水平网格线划分出行，垂直网格线划分出列。
正常情况下，
n行有
n + 1根水平网格线，
m列有
m + 1根垂直网格线，比如三行就有四根水平网格线。
上图是一个 4 x 4 的网格，共有5根水平网格线和5根垂直网格线。
三、容器属性
Grid 布局的属性分成两类。一类定义在容器上面，称为容器属性；另一类定义在项目上面，称为项目属性。这部分先介绍容器属性。
3.1 display 属性
display: grid指定一个容器采用网格布局。
div {
  display: grid;
}
上图是
display: grid的效果。
默认情况下，容器元素都是块级元素，但也可以设成行内元素。
div {
  display: inline-grid;
}
上面代码指定
div是一个行内元素，该元素内部采用网格布局。
上图是
display: inline-grid的效果。
注意，设为网格布局以后，容器的
float、
display: inline-block、
display: table-cell、
vertical-align和
column-*等设置都将失效。
3.2 grid-template-columns 属性，grid-template-rows 属性
容器指定了网格布局以后，接着就要划分行和列。
grid-template-columns属性定义每一列的列宽，
grid-template-rows属性定义每一行的行高。
.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
}
上面代码指定了一个三行三列的网格，列宽和行高都是
100px。
除了使用绝对单位，也可以使用百分比。
.container {
  display: grid;
  grid-template-columns: 33.33% 33.33% 33.33%;
  grid-template-rows: 33.33% 33.33% 33.33%;
}
（1）repeat()
有时候，重复写同样的值非常麻烦，尤其网格很多时。这时，可以使用
repeat()函数，简化重复的值。上面的代码用
repeat()改写如下。
.container {
  display: grid;
  grid-template-columns: repeat(3, 33.33%);
  grid-template-rows: repeat(3, 33.33%);
}
repeat()接受两个参数，第一个参数是重复的次数（上例是3），第二个参数是所要重复的值。
repeat()重复某种模式也是可以的。
grid-template-columns: repeat(2, 100px 20px 80px);
上面代码定义了6列，第一列和第四列的宽度为
100px，第二列和第五列为
20px，第三列和第六列为
80px。
（2）auto-fill 关键字
有时，单元格的大小是固定的，但是容器的大小不确定。如果希望每一行（或每一列）容纳尽可能多的单元格，这时可以使用
auto-fill关键字表示自动填充。
.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
}
上面代码表示每列宽度
100px，然后自动填充，直到容器不能放置更多的列。
（3）fr 关键字
为了方便表示比例关系，网格布局提供了
fr关键字（fraction 的缩写，意为“片段”）。如果两列的宽度分别为
1fr和
2fr，就表示后者是前者的两倍。
.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
上面代码表示两个相同宽度的列。
fr可以与绝对长度的单位结合使用，这时会非常方便。
.container {
  display: grid;
  grid-template-columns: 150px 1fr 2fr;
}
上面代码表示，第一列的宽度为150像素，第二列的宽度是第三列的一半。
（4）minmax()
minmax()函数产生一个长度范围，表示长度就在这个范围之中。它接受两个参数，分别为最小值和最大值。
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
上面代码中，
minmax(100px, 1fr)表示列宽不小于
100px，不大于
1fr。
（5）auto 关键字
auto关键字表示由浏览器自己决定长度。
grid-template-columns: 100px auto 100px;
上面代码中，第二列的宽度，基本上等于该列单元格的最大宽度，除非单元格内容设置了
min-width，且这个值大于最大宽度。
（6）网格线的名称
grid-template-columns属性和
grid-template-rows属性里面，还可以使用方括号，指定每一根网格线的名字，方便以后的引用。
.container {
  display: grid;
  grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4];
  grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4];
}
上面代码指定网格布局为3行 x 3列，因此有4根垂直网格线和4根水平网格线。方括号里面依次是这八根线的名字。
网格布局允许同一根线有多个名字，比如
[fifth-line row-5]。
（7）布局实例
grid-template-columns属性对于网页布局非常有用。两栏式布局只需要一行代码。
.wrapper {
  display: grid;
  grid-template-columns: 70% 30%;
}
上面代码将左边栏设为70%，右边栏设为30%。
传统的十二网格布局，写起来也很容器。
grid-template-columns: repeat(12, 1fr);
3.3 grid-row-gap 属性，grid-column-gap 属性，grid-gap 属性
grid-row-gap属性设置行与行的间隔（行间距），
grid-column-gap属性设置列与列的间隔（列间距）。
.container {
  grid-row-gap: 20px;
  grid-column-gap: 20px;
}
上面代码中，
grid-row-gap用于设置行间距，
grid-column-gap用于设置列间距。
grid-gap属性是
grid-column-gap和
grid-row-gap的合并简写形式，语法如下。
grid-gap: <grid-row-gap> <grid-column-gap>;
因此，上面一段 CSS 代码等同于下面的代码。
.container {
  grid-gap: 20px 20px;
}
如果
grid-gap省略了第二个值，浏览器认为第二个值等于第一个值。
根据最新标准，上面三个属性名的
grid-前缀已经删除，
grid-column-gap和
grid-row-gap写成
column-gap和
row-gap，
grid-gap写成
gap。
3.4 grid-template-areas 属性
网格布局允许指定“区域”（area），一个区域由单个或多个单元格组成。
grid-template-areas属性用于定义区域。
.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
  grid-template-areas: 'a b c'
                       'd e f'
                       'g h i';
}
上面代码先划分出9个单元格，然后将其定名为
a到
i的九个区域，分别对应这九个单元格。
多个单元格合并成一个区域的写法如下。
grid-template-areas: 'a a a'
                     'b b b'
                     'c c c';
上面代码将9个单元格分成
a、
b、
c三个区域。
下面是一个布局实例。
grid-template-areas: "header header header"
                     "main main sidebar"
                     "footer footer footer";
上面代码中，顶部是页眉区域
header，底部是页脚区域
footer，中间部分则为
main和
sidebar。
如果某些区域不需要利用，则使用“点”（
.）表示。
grid-template-areas: 'a . c'
                     'd . f'
                     'g . i';
上面代码中，中间一列为点，表示没有用到该单元格，或者该单元格不属于任何区域。
注意，区域的命名会影响到网格线。每个区域的起始网格线，会自动命名为
区域名-start，终止网格线自动命名为
区域名-end。
比如，区域名为
header，则起始位置的水平网格线和垂直网格线叫做
header-start，终止位置的水平网格线和垂直网格线叫做
header-end。
3.5 grid-auto-flow 属性
划分网格以后，容器的子元素会按照顺序，自动放置在每一个网格。默认的放置顺序是“先行后列”，即先填满第一行，再开始放入第二行，即下图数字的顺序。
这个顺序由
grid-auto-flow属性决定，默认值是
row，即“先行后列”。也可以将它设成
column，变成“先列后行”。
grid-auto-flow: column;
上面代码设置了
column以后，放置顺序就变成了下图。
grid-auto-flow属性除了设置成
row和
column，还可以设成
row dense和
column dense。这两个值主要用于，某些项目指定位置以后，剩下的项目怎么自动放置。
下面的例子让1号项目和2号项目各占据两个单元格，然后在默认的
grid-auto-flow: row情况下，会产生下面这样的布局。
上图中，1号项目后面的位置是空的，这是因为3号项目默认跟着2号项目，所以会排在2号项目后面。
现在修改设置，设为
row dense，表示“先行后列”，并且尽可能紧密填满，尽量不出现空格。
grid-auto-flow: row dense;
上面代码的效果如下。
上图会先填满第一行，再填满第二行，所以3号项目就会紧跟在1号项目的后面。8号项目和9号项目就会排到第四行。
如果将设置改为
column dense，表示“先列后行”，并且尽量填满空格。
grid-auto-flow: column dense;
上面代码的效果如下。
上图会先填满第一列，再填满第2列，所以3号项目在第一列，4号项目在第二列。8号项目和9号项目被挤到了第四列。
3.6 justify-items 属性，align-items 属性，place-items 属性
justify-items属性设置单元格内容的水平位置（左中右），
align-items属性设置单元格内容的垂直位置（上中下）。
.container {
  justify-items: start | end | center | stretch;
  align-items: start | end | center | stretch;
}
这两个属性的写法完全相同，都可以取下面这些值。
start：对齐单元格的起始边缘。
end：对齐单元格的结束边缘。
center：单元格内部居中。
stretch：拉伸，占满单元格的整个宽度（默认值）。
.container {
  justify-items: start;
}
上面代码表示，单元格的内容左对齐，效果如下图。
.container {
  align-items: start;
}
上面代码表示，单元格的内容头部对齐，效果如下图。
place-items属性是
align-items属性和
justify-items属性的合并简写形式。
place-items: <align-items> <justify-items>;
下面是一个例子。
place-items: start end;
如果省略第二个值，则浏览器认为与第一个值相等。
3.7 justify-content 属性，align-content 属性，place-content 属性
justify-content属性是整个内容区域在容器里面的水平位置（左中右），
align-content属性是整个内容区域的垂直位置（上中下）。
.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}
这两个属性的写法完全相同，都可以取下面这些值。（下面的图都以
justify-content属性为例，
align-content属性的图完全一样，只是将水平方向改成垂直方向。）
start - 对齐容器的起始边框。
end - 对齐容器的结束边框。
center - 容器内部居中。
stretch - 项目大小没有指定时，拉伸占据整个网格容器。
space-around - 每个项目两侧的间隔相等。所以，项目之间的间隔比项目与容器边框的间隔大一倍。
space-between - 项目与项目的间隔相等，项目与容器边框之间没有间隔。
space-evenly - 项目与项目的间隔相等，项目与容器边框之间也是同样长度的间隔。
place-content属性是
align-content属性和
justify-content属性的合并简写形式。
place-content: <align-content> <justify-content>
下面是一个例子。
place-content: space-around space-evenly;
如果省略第二个值，浏览器就会假定第二个值等于第一个值。
3.8 grid-auto-columns 属性，grid-auto-rows 属性
有时候，一些项目的指定位置，在现有网格的外部。比如网格只有3列，但是某一个项目指定在第5行。这时，浏览器会自动生成多余的网格，以便放置项目。
grid-auto-columns属性和
grid-auto-rows属性用来设置，浏览器自动创建的多余网格的列宽和行高。它们的写法与
grid-template-columns和
grid-template-rows完全相同。如果不指定这两个属性，浏览器完全根据单元格内容的大小，决定新增网格的列宽和行高。
下面的例子里面，划分好的网格是3行 x 3列，但是，8号项目指定在第4行，9号项目指定在第5行。
.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
  grid-auto-rows: 50px; 
}
上面代码指定新增的行高统一为50px（原始的行高为100px）。
3.9 grid-template 属性，grid 属性
grid-template属性是
grid-template-columns、
grid-template-rows和
grid-template-areas这三个属性的合并简写形式。
grid属性是
grid-template-rows、
grid-template-columns、
grid-template-areas、  
grid-auto-rows、
grid-auto-columns、
grid-auto-flow这六个属性的合并简写形式。
从易读易写的角度考虑，还是建议不要合并属性，所以这里就不详细介绍这两个属性了。
四、项目属性
下面这些属性定义在项目上面。
4.1 grid-column-start 属性，grid-column-end 属性，grid-row-start 属性，grid-row-end 属性
项目的位置是可以指定的，具体方法就是指定项目的四个边框，分别定位在哪根网格线。
grid-column-start属性：左边框所在的垂直网格线
grid-column-end属性：右边框所在的垂直网格线
grid-row-start属性：上边框所在的水平网格线
grid-row-end属性：下边框所在的水平网格线
.item-1 {
  grid-column-start: 2;
  grid-column-end: 4;
}
上面代码指定，1号项目的左边框是第二根垂直网格线，右边框是第四根垂直网格线。
上图中，只指定了1号项目的左右边框，没有指定上下边框，所以会采用默认位置，即上边框是第一根水平网格线，下边框是第二根水平网格线。
除了1号项目以外，其他项目都没有指定位置，由浏览器自动布局，这时它们的位置由容器的
grid-auto-flow属性决定，这个属性的默认值是
row，因此会“先行后列”进行排列。读者可以把这个属性的值分别改成
column、
row dense和
column dense，看看其他项目的位置发生了怎样的变化。
下面的例子是指定四个边框位置的效果。
.item-1 {
  grid-column-start: 1;
  grid-column-end: 3;
  grid-row-start: 2;
  grid-row-end: 4;
}
这四个属性的值，除了指定为第几个网格线，还可以指定为网格线的名字。
.item-1 {
  grid-column-start: header-start;
  grid-column-end: header-end;
}
上面代码中，左边框和右边框的位置，都指定为网格线的名字。
这四个属性的值还可以使用
span关键字，表示“跨越”，即左右边框（上下边框）之间跨越多少个网格。
.item-1 {
  grid-column-start: span 2;
}
上面代码表示，1号项目的左边框距离右边框跨越2个网格。
这与下面的代码效果完全一样。
.item-1 {
  grid-column-end: span 2;
}
使用这四个属性，如果产生了项目的重叠，则使用
z-index属性指定项目的重叠顺序。
4.2 grid-column 属性，grid-row 属性
grid-column属性是
grid-column-start和
grid-column-end的合并简写形式，
grid-row属性是
grid-row-start属性和
grid-row-end的合并简写形式。
.item {
  grid-column: <start-line> / <end-line>;
  grid-row: <start-line> / <end-line>;
}
下面是一个例子。
.item-1 {
  grid-column: 1 / 3;
  grid-row: 1 / 2;
}
/* 等同于 */
.item-1 {
  grid-column-start: 1;
  grid-column-end: 3;
  grid-row-start: 1;
  grid-row-end: 2;
}
上面代码中，项目
item-1占据第一行，从第一根列线到第三根列线。
这两个属性之中，也可以使用
span关键字，表示跨越多少个网格。
.item-1 {
  background: #b03532;
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}
/* 等同于 */
.item-1 {
  background: #b03532;
  grid-column: 1 / span 2;
  grid-row: 1 / span 2;
}
上面代码中，项目
item-1占据的区域，包括第一行 + 第二行、第一列 + 第二列。
斜杠以及后面的部分可以省略，默认跨越一个网格。
.item-1 {
  grid-column: 1;
  grid-row: 1;
}
上面代码中，项目
item-1占据左上角第一个网格。
4.3 grid-area 属性
grid-area属性指定项目放在哪一个区域。
.item-1 {
  grid-area: e;
}
上面代码中，1号项目位于
e区域，效果如下图。
grid-area属性还可用作
grid-row-start、
grid-column-start、
grid-row-end、
grid-column-end的合并简写形式，直接指定项目的位置。
.item {
  grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
}
下面是一个例子。
.item-1 {
  grid-area: 1 / 1 / 3 / 3;
}
4.4 justify-self 属性，align-self 属性，place-self 属性
justify-self属性设置单元格内容的水平位置（左中右），跟
justify-items属性的用法完全一致，但只作用于单个项目。
align-self属性设置单元格内容的垂直位置（上中下），跟
align-items属性的用法完全一致，也是只作用于单个项目。
.item {
  justify-self: start | end | center | stretch;
  align-self: start | end | center | stretch;
}
这两个属性都可以取下面四个值。
start：对齐单元格的起始边缘。
end：对齐单元格的结束边缘。
center：单元格内部居中。
stretch：拉伸，占满单元格的整个宽度（默认值）。
下面是
justify-self: start的例子。
.item-1  {
  justify-self: start;
}
place-self属性是
align-self属性和
justify-self属性的合并简写形式。
place-self: <align-self> <justify-self>;
下面是一个例子。
place-self: center center;
如果省略第二个值，
place-self属性会认为这两个值相等。
五、参考链接
A Complete Guide to Grid, by Chris House
Understanding the CSS Grid Layout Module, by Ian Yates
How to Build an Off-Canvas Navigation With CSS Grid, Ian Yates
Introduction to the CSS Grid Layout With Examples, Dogacan Bilgili
Learn CSS Grid, Jonathan Suh
How I stopped using Bootstrap’s layout thanks to CSS Grid, Cédric Kui

Table 布局
CSS 可以让 HTML 元素像表格那样排列。
下面是表格的各个 HTML 标签，所对应的布局模式。
table    { display: table }
tr       { display: table-row }
thead    { display: table-header-group }
tbody    { display: table-row-group }
tfoot    { display: table-footer-group }
col      { display: table-column }
colgroup { display: table-column-group }
td, th   { display: table-cell }
caption  { display: table-caption }
表格布局可以很简单地做到垂直居中。
div {
  height: 200px;
  display:table-cell;
  vertical-align: middle;
}
这种写法相比下面的写法，更容易理解。
div {
  height: 200px;
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}
表格布局的另一个用途是，让页尾总是显示在浏览器的最低部，即使页面高度不足一页。
/*
  HTML 代码如下
  <body>
    <div class="main"></div>
    <div class="footer"></div>
  </body>
*/
body {
  display: table;
  width: 100%;
}
.main {
  min-height: 100%;
}
.footer {
  display: table-row;
  height:1px;
}
基于上面这种底部固定的技巧，可以使用表格布局，完成圣杯布局，即页面从上到下分成页首 + 内容 + 页尾三部分，其中内容部分又分成左边栏和右边栏。
/*
  HTML 代码如下
<div class="wrapper">
  <div class="header">HEADER</div>
  <div class="main">
    <div class="box sidebar">Left-sidebar</div>
    <div class="box content">Main Content</div>
    <div class="box sidebar">Right-sidebar</div>
  </div>
  <div class="footer">FOOTER</div>
</div>
*/
.wrapper {
  min-height: 100%;
  display: table;
  width: 100%;
  text-align: center;
}
.header {
  display: table-row;
  height: 1px;
}
.main {
  min-height: 100%;
  display: table;
  width: 100%;
}
.box {
  display: table-cell;
}
.sidebar {
  width: 100px;
}
.footer {
  display: table-row;
  height:1px;
}
利用表格的不同性质的行，可以调整行的显示位置。
display:table-caption使得该行显示在表格的最顶部。
display:table-header-group使得该行显示在表格的头部，但是位置低于
table-caption的行。
display:table-footer-group使得该行显示在表格的底部。
参考链接
Colin Toh, The Anti-hero of CSS Layout - "display:table"
Ian Devlin, CSS stacking with display:table
Ben Frain, CSS performance test: Flexbox v CSS Table

属性选择器
[attribute]	匹配指定属性，不论具体值是什么
[attribute="value"]	完全匹配指定属性值
[attribute~="value"]	属性值是以空格分隔的多个单词，其中有一个完全匹配指定值
[attribute|="value"]	属性值以value-打头
[attribute^="value"]	属性值以value开头，value为完整的单词或单词的一部分
[attribute$="value"]	属性值以value结尾，value为完整的单词或单词的一部分
[attribute*="value"]	属性值为指定值的子字符串
修饰符
属性修饰器支持
i修饰符，表示不区分大小写。
[class=foo i] {
  color: red;
}
上面代码中，属性名
foo后面的
i，表示不区分
foo的大小写，所以下面几个 class 都会匹配。
<div class="foo">...</div>
<div class="Foo">...</div>
<div class="fOo">...</div>
这个修饰符对于匹配用户的输入，非常有用。
/**
 * 匹配：
 * <input value="hello world">
 * <input value="hello World">
 * <input value="hElLo WoRlD">
 * ...
 */
[value="hello world" i] { /* ... */ }
参考链接
The CSS attribute selector has a case-insensitive mode

选择器
选择器决定了样式规则对哪些元素有效。
基本选择器
元素名称选择器，选中所有该标签的元素。
#elementId选中指定
id属性的元素。
.elementClass选中指定
class属性的元素。
应该尽量使用 class 选择器，而不是 ID 选择器。
ID 选择器的样式不能在其他元素上复用（记住，在一个页面中，一个id只能出现在一个元素上）。这会导致在其他元素上重复样式，而不是通过class共享样式。
ID 选择器的特殊性比class选择器要强得多。这意味着如果要覆盖使用id选择器定义的样式，就要编写特殊性更强的CSS规则。如果数量不多，可能还不难管理。如果处理规模较大的网站，其CSS就会变得比实际所需的更长、更复杂。
通配符选择器
通配符
*（星号）匹配任何元素。
因为匹配范围太广，会让浏览器加载页面变慢，因此应该谨慎使用通配符。实际适合使用通配符的情况比较少。
:matches()
:matches(A, B)选择器表示匹配A或B。
:matches(.foo, .bar) {
  background-color: green;
}
/* 等同于 */
.foo, .bar {
  background-color: green;
}
它可以简化一些选择器的写法。
.syntax-highlighted .css-keyword,
.syntax-highlighted .css-tag {
  color: rgb(170, 13, 145);
}
/* 等同于 */
.syntax-highlighted :matches(.css-keyword, .css-tag) {
  color: rgb(170, 13, 145);
}
:not()
:not()表示选中不匹配指定条件的元素。
a:not(.internal) {
  color: red;
}
:not()可以采用链式写法。
:not(i):not(em)
/* 等同于 */
:not(i, em)
BEM命名法
BEM是Block（区块）、Element（元素）、Modifier（修饰符）三者的简称。区块是顶级组件的抽象，元素是组件的组成部分，修饰符是组件或元素的状态。区块与元素之间用两个下划线连接，元素与修饰符之间用两个连词线连接。
/* Block component */
.btn {}
/* Element that depends upon the block */
.btn__price {}
/* Modifier that changes the style of the block */
.btn--orange {}
.btn--big {}
对应的HTML代码结构如下。
<a class="btn btn--big btn--orange" href="http://css-tricks.com">
  <span class="btn__price">$9.99</span>
  <span class="btn__text">Subscribe</span>
</a>
BEM的重要特点就是CSS是扁平式的，不存在元素嵌套。
target
target选择器用来匹配当前hash。
产生动画效果。
#further-resources:target {
  animation: highlight .8s ease-out;
}
@keyframes highlight {
  0% { background-color: #FFFF66; }
  100% { background-color: #FFFFFF; }
}
弹出效果。
#search-overlay {
  position: fixed;
  top: 1em;
  bottom: 1em;
  right: 1em;
  left: 1em;
  /* … */
  opacity: 0;
  transition: opacity .3s ease-in-out;
  pointer-events: none;
}
#search-overlay:target {
  opacity: 1;
  pointer-events: auto;
  transition: opacity .3s ease-in-out;
}
导航栏效果
.main-nav {
  position: fixed;
  top: 0;
  width: 0;
  height: 100%;
  background: #3B3B3B;
  overflow-y: auto;
  transition: width 0.3s ease;
}
#main-nav:target {
  width: 20%;
}
#main-nav:target + .page-wrap {
  width: 80%;
  .open-menu {
     display: none;
  }
  .close-menu {
     display: block;
  }
  .main-header {
    width: 80%;
    left: 20%;
  }
}
伪元素（Pseudo-element）
伪元素（::before或者::after）是每个元素额外多出来的DOM节点。
.pebble::before {
  ...
}
.pebble::after {
  ...
}
伪元素使用两个双引号标识，如果希望IE8支持，也可以使用单引号。
button::after {
  content: '';
  position: absolute;
  top: -50%;
  right: -50%;
  bottom: -50%;
  left: -50%;
  background: linear-gradient(to bottom, rgba(229, 172, 142, 0.1), rgba(255,255,255,0.5) 50%, rgba(229, 172, 142, 0.1));
  transform: rotateZ(60deg) translate(-5em, 7.5em);
}
button:hover::after {
  animation: sheen 1s forwards;
}
@keyframes sheen {
  100% {
    transform: rotateZ(60deg) translate(1em, -9em);
  }
}
参考链接
Donovan Hutchinson, Animating pseudo-elements
伪类
:empty：没有任何子元素
:in-range：针对有range属性的input
:out-of-range：针对有range属性的input
:optional：没有required属性的input元素
:required
:disabled
:fullscreen
:not()
优先级
一个网页元素，可以被多个选择器匹配。如果这些选择器都设置了同样的规则，就有一个”优先级“的问题：到底哪个选择器的优先级更高？
规则是针对性越强的选择器，优先级越高。浏览器会计算每条规则的优先级值，然后采用值最高的规则，计算方法如下。
!important后缀为 10000
行内样式为 1000
ID 为 100
class、伪类、属性选择器为 10
标签名、伪元素为 1
然后，累加得到的分数，哪条规则得分最高，就采用哪条规则。如果得分相同，就采用位置靠后的位置。
下面是一些例子。
<li style="color: red;">：行内样式，得分为1000。
ul#nav li.active a：一个 ID、一个 Class、三个标签名，得分为113。
body.ie7 .col_3 h2 ~ h3：两个 Class，三个标签名，得分为23。
#footer *:not(nav) li：一个 ID、两个标签名，得分为102。注意，
*没有分数，而且
:not不算伪类，只计算它括号里面的标签名。
ul > li ul li ol li:first-letter：七个标签名，得分为7。注意，
:first-letter算作伪元素。

伪类选择器
伪元素（pseudo-element）是 HTML 中并不存在的元素。例如，定义第一个字母或第一行文字时，并未在HTML中作相应的标记。
伪类（pseudo-class）是浏览器根据网页元素的状态，自动提供的 CSS 类，无需在 HTML 代码显式标记这些类。例如，使用:first-child可以选择某元素的第一个子元素，你就不用写成class="first-child"。更多关于伪类的内容。
伪元素有四个。
::first-line
::first-letter
::before
::after
伪类
:first-child
:link：新的、未访问的链接
:visited：访问过的链接
:focus：链接获得焦点（如通过Tab键）
:hover：当访问者将鼠标指针停留在链接上时
:active: 当访问者激活链接时
:empty：空选择器
新的、未访问的链接显示为红色；访问过的链接变为橙色；
概述
CSS 2.1非常有限，只提供了三个伪类。
:active
:focus
:hover
CSS Selector Level 3添加了更多与HTML表单相关的伪类：
:enabled
:disabled
:checked
:indeterminate
CSS Basic UI Level 3添加了许多伪类来描述窗口小部件的状态：
:default
:valid
:invalid
:in-range
:out-of-range
:required
:optional
:read-only
:read-write
:first-child，:last-child
:first-child表示一组元素的第一个元素，且该元素必须是父元素的第一个子元素。
li{
  color: blue;
}
li:first-child {
  color: green;
}
上面代码中，第一个
li的字体颜色为绿色，其他
li都为蓝色。
:last-child表示一组元素之中的最后一个，且该元素必须是父元素的最后一个子元素。
li:last-child {
  background-color: lime;
}
:first-of-type，:last-of-type
:first-of-type选中一组元素之中的第一个元素。
p:first-of-type {
  font-size: 1.25em;
}
上面代码中，
p:first-of-type只会选中第一个
p元素。
:first-of-type与
:first-child的区别是，后者必须父元素的第一个子元素。
<ul>
  <p>Hello World</p>
  <li>1</li>
  <li>2</li>
</ul>
上面这段 HTML 代码，如果想让第一个
<li>显示为绿色，必须使用
:first-of-type，而不能是
:first-child。
/* 正确 */
ul li:first-of-type {
  color: green;
}
/* 错误 */
ul li:first-child {
  color: green;
}
:last-of-type选中本类之中最后一个元素。
p:last-of-type {
  font-size: 0.75em;
}
上面代码中，
p:last-of-type只会选中最后一个
p元素。
:nth-child()，:nth-last-child()
:nth-child()选中指定位置的子元素。
:nth-last-child()选中指定的倒数位置的子元素。
p:nth-child(2) {
  color: red;
}
上面代码中，
:nth-child()选中所有第二个子元素位置的
p元素。
注意，如果元素名与
:nth-child()之间有没有空格，含义是不一样的。没有空格时，表示匹配该种子元素；有空格时，表示匹配该元素的子元素。
p :nth-child(2) {
  color: red;
}
上面代码表示，匹配
p元素内部的第二个子元素，而不是匹配
p元素本身。
:nth-child()和
:nth-last-child()可以使用通配符作为参数，参见
:nth-of-type()部分的说明。
ul li:nth-child(3n+3) {
  color: #ccc;
}
上面代码选中3、6、9等位置的
li元素，
n表示整数序列0、1、2、3……。
这里还有一个技巧，如果要选中前三个元素，可以在
n前面使用负数符号1
-。
ul li:nth-child(-n + 3) {
  color: #ccc;
}
上面代码只会选中前三个
li，因为当
n大于等于
3时，
-n + 3会小于等于0，而
li的序号是从
1开始的。
相应的，
:nth-last-child(-n + 3)就会选中最后三个元素，而
:nth-last-child(n + 4)会选中除了最后三个以外的其他元素。
除了使用
An + B这种形式的表达式指定位置，还可以使用
odd或
even关键字，分别表示奇数位置或偶数位置的元素。
ul li:nth-child(odd) {
  color: #ccc;
}
:nth-of-type()，:nth-last-of-type()
:nth-of-type()匹配指定类型和位置的元素，
:nth-last-of-type()匹配倒数位置的指定类型和位置的元素。
p:nth-of-type(2) {
  color: red;
}
上面代码中，
p:nth-of-type(2)匹配第二个
p元素。
下面是通配符用法。
li:nth-of-type(2n) {
  background: lightslategrey;
}
li:nth-of-type(3n+2) {
  background: blue;
}
:nth-of-type的参数可以是
an + b的形式。
“a”是一个整数
“n”作为英文字母，总是不变的，含义是“0, 1, 2, ....”
“+”作为一个运算符，可以是“+”，也可以是“-”
“b”是一个整数，如果提供了运算符，就必须提供“b”
:nth-of-type的参数还可以是
even或
odd。
li::nth-of-type(odd)  {
  background: lightslategrey;
}
空选择器
:empty是空选择器，匹配没有任何子节点的元素。
p:empty {
  color: red;
}
下面的 HTML 代码都匹配
:empty选择器。
<!-- 闭合标签之间没有空格 -->
<p></p>
<!-- 闭合标签之间只有注释 -->
<p><!-- comment --></p>
下面的 HTML 代码都不匹配
:empty选择器。
<!-- 闭合标签之间有空格 -->
<p></p>
<!-- 闭合标签之间有换行符 -->
<p>
<!-- comment -->
</p>
<!-- 闭合标签有子元素 -->
<p><span></span></p>
这个选择器的一个作用，就是使用脚本动态添加子元素后，将该元素显示出来。
<!-- No error message -->
<div class="error"></div>
<!-- Yes error message -->
<div class="error">Missing Email</div>
上面代码中，为
<div>标签添加文本内容后，使用下面的 CSS 代码将其显示出来。
.error:empty {
  display: none;
}
.error:before {
  color: red;
  content: "\0274c "; /* ❌ icon */
}
选中非空元素可以像下面这样写。
.alert:not(:empty) {
  background: pink;
  padding: 10px;
}
参考链接
CSS :empty Selector, Samantha Ming

text-decoration
文本可以附加装饰线（比如下划线），以下属性用来设置装饰线。
text-decoration
text-decoration设置文本采用哪一种装饰线，主要有下划线（underline）、上划线（overline）和删除线（line-through）等类型。
h3 {
  text-decoration: underline;
}
该属性可以取以下值。
none：没有任何修饰
underline：下划线，默认线宽
1px
overline：上划线，默认线宽
1px
line-through：删除线，默认线宽
1px
inherit：继承父元素的设置
多种装饰线可以同时存在。
.multiple {
  text-decoration: underline overline line-through;
}
默认情况下，装饰线的颜色与文本的
color属性一致。
text-decoration-color属性可以修改颜色。
text-decoration属性还可以用作
text-decoration-style和
text-decoration-color的简写形式。
.fancy-underline {
  text-decoration-line: underline;
  text-decoration-style: wavy;
  text-decoration-color: red;
  /* 等同于 */
  text-decoration: underline wavy red;
}
text-decoration-color
text-decoration-color设置文本的装饰线的颜色。
a {
  text-decoration-color: #E18728;
}
text-decoration-style
text-decoration-style设置文本的下划线（underline）、上划线（overline）和删除线（line-through）的样式。
a {
  text-decoration-style: solid;
}
该属性支持以下样式。
solid：单条直线
double：双条直线
dotted：多个点组成的直线
dashed：多个短划线组成的直线
wavy：波浪线
text-decoration-line
text-decoration-line设置文本采用何种装饰线，与
text-decoration单个值的写法相同。建议采用后者，因为浏览器的支持度更好。
p {
  text-decoration-line: underline;
}
它的取值参考
text-decoration。
text-decoration-skip
text-decoration-skip设置文本的装饰线应该在哪里中断，主要用于改善文本被装饰以后的可读性。
a {
  text-decoration-skip: ink;
}
上面代码中，下划线遇到英语字母
y和
p会中断，让它们较长的下划会更清晰地显示出来。
该属性可以取以下值。
objects：默认值，装饰线遇到图片或其他
inline-block对象时中断。
none：装饰线不会有任何中断，包括遇到行内对象。
spaces：装饰线在空格、断词处中断。
ink：装饰线遇到有笔画下降或上升的字母时中断。
edges：装饰线在内容开始后和结束前都收缩一点，主要用于多个连续的装饰线，可以看上去连成一条。
box-decoration：装饰线在继承的 margin、border 和 padding 处中断。
参考链接
text-decoration, by Sara Cope
text-decoration-skip, by Marie Mosley

文本
direction
direction属性设置块级元素内部的文本阅读方向。
它的默认值是
ltr（从左到右），适用于大部分语言。它还可以设成
rtl（从右到左）。
blockquote {
  direction: rtl;
}
一般采用 HTML 语言的
dir属性控制文本阅读方向，而不是使用这个属性。
text-align
text-align属性设置块级元素内部的文本对齐方式。
它可以取以下值。
left：默认值，文本向左对齐
right：右对齐
center：居中对齐
justify：两端对齐，除了最后一行是左对齐。
inherit：继承父元素的值
start：
direction属性为从左到右时，为左对齐；从右到左时，为右对齐
end：
direction属性为从左到右时，为右对齐；从右到左时，为左对齐
vertical-align
vertical-align设置一个元素与在同一条水平线上的其他元素如何对齐。这些元素需要都是
inline。它可以取以下值。
baseline：对齐父元素的基线，默认值
length: 升高或降低特定的长度，可使用负值
%：升高或降低
line-height的百分比，不允许负值
sub：设为下标
super：设为上标
top: 当前元素的顶部对齐最高元素的顶边
text-top：当前元素的顶部对齐父元素字体的顶部
middle：元素位于父元素的垂直中部
bottom：当前元素的底部对齐本行最低元素的底部
text-bottom：当前元素的底部，对齐父元素字体的底部
initial：设置为默认值
inherit：继承父元素的值
这个属性通常用于同一行的图标与文字的对齐。
vertical-align: middle;
这个命令对设为
display: table-cell的元素也有效，可以控制元素在单元格之中的垂直对齐方式。这时，一般使用
top、
middle和
bottom等值。
tab-size
tab-size属性设置 Tab 键的宽度，可以设置为整数（表示多少个空格），也可以设置为具体的长度单位。
/* 整数植 */
tab-size: 4;
tab-size: 0;
/* 长度单位 */
tab-size: 10px;
tab-size: 2em;
该属性常用于
<pre>标签之中。
pre {-moz-tab-size: 16;} /* Code for Firefox */
pre {-o-tab-size: 16;} /* Code for Opera 10.6-12.1 */
pre {tab-size: 16;}
word-wrap
word-wrap的正式名称是
overflow-wrap，用于规定是否可以在一个词内部断行，避免溢出容器。
它可以取两个值。
normal：只在可以断行的地方断行。
break-word：可以在任意点断行，避免某个词过长，发生溢出。
word-break
word-break用于规定是否可以在词内断行。
它可以取三个值。
normal：使用浏览器默认的断行规则
break-all：对于非 CJK 字符，可以任意字符之间断行。
keep-all：对于 CJK 字符不允许换行。非 CJK 字符与
normal相同。
hyphens
浏览器打开连字号功能，需要两个步骤。第一个步骤是设置文本的语言。这将告诉浏览器使用哪个连字词典，正确的自动连字需要一个适合文本语言的连字词典。如果浏览器不知道文本的语言，即使打开 CSS 设置也不会自动连词。
设置网页语言，应该使用
<html>标签的
lang属性。
<html lang="en">
CSS 里面使用自动连词，要开启
hyphens属性。
hyphens属性控制块级元素之中，文本是否显示连词线。
hyphens: auto;
hyphens属性可以取以下三个值。
（1） none
none表示一个词不会在断行处被拆开，即断行处不会有连词线。
（2）manual
manual表示只有在一个词内部的字符表示可以有连词线时，才会在断行处拆开。断行处，会有连词线。
两个字符可以表示此处可以断行，并显示连词线，一个是
-(U+2010)，表示此处可以有一个可见的断行，即使不在此处断行，这里也会有连词线显示；另一个是
U+00AD，表示不可见的断行，HTML 文档里面可以用
&shy;插入。
（3）auto
auto表示浏览器决定一个词是否可以在断行处拆开，以及是否会有连词线。
参考链接
All you need to know about hyphenation in CSS, Richard Rutter

空格
一、基本规则
HTML 代码的空格通常会被浏览器忽略。
<p>◡◡hello◡◡world◡◡</p>
上面是一行 HTML 代码，文字的前部、内部和后部各有两个空格。为了便于识别，这里使用半圆形符号
◡表示空格。
浏览器的输出结果如下。
hello world
可以看到，文字的前部和后部的空格都会忽略，内部的连续空格只会算作一个。这就是浏览器处理空格的基本规则。
如果希望空格原样输出，可以使用
<pre>标签。
<pre>◡◡hello◡◡world◡◡</pre>
另一种方法是，改用 HTML 实体
&nbsp;表示空格。
<p>&nbsp;&nbsp;hello&nbsp;&nbsp;world&nbsp;&nbsp;</p>
二、空格字符
HTML 处理空格的规则，适用于多种字符。除了普通的空格键，还包括制表符（
\t）和换行符（
\r和
\n）。
浏览器会自动把这些符号转成普通的空格键。
<p>hello
world</p>
上面代码中，文本内部包含了一个换行符，浏览器视同为空格，输出结果如下。
hello world
所以，文本内部的换行是无效的（除非文本放在
<pre>标签内）。
<p>hello<br>world</p>
上面代码使用
<br>标签显式表示换行。
三、CSS 的 white-space 属性
HTML 语言的空格处理，基本上就是直接过滤。这样的处理过于粗糙，完全忽视了原始文本内部的空格可能是有意义的。
CSS 提供了一个 white-space 属性，可以提供更精确一点的空格处理方式。该属性共有六个值，除了一个通用的
inherit（继承父元素），下面依次介绍剩下的五个值。
3.1 white-space: normal
white-space属性的默认值为
normal，表示浏览器以正常方式处理空格。
<p>◡◡hellohellohello◡hello
world
</p>
上面代码中，文本前部有两个空格，内部有一个长单词和一个换行符。
然后，容器
<p>指定一个比较小的宽度。为了便于识别，背景色设为红色。
p {
  width: 100px;
  background: red;
}
显示效果如下图。
可以看到，文首的空格被忽略。由于容器太窄，第一个单词溢出容器，然后在后面一个空格处换行。文本内部的换行符自动转成了空格。
3.2 white-space: nowrap
white-space属性为
nowrap时，不会因为超出容器宽度而发生换行。
p {
  white-space: nowrap;
}
显示效果如下图。
所有文本显示为一行，不会换行。
3.3 white-space: pre
white-space属性为
pre时，就按照
<pre>标签的方式处理。
p {
  white-space: pre;
}
显示效果如下图。
上面结果与原始文本完全一致，所有空格和换行符都保留了。
3.4 white-space: pre-wrap
white-space属性为
pre-wrap时，基本还是按照
<pre>标签的方式处理，唯一区别是超出容器宽度时，会发生换行。
p {
  white-space: pre-wrap;
}
显示效果如下图。
文首的空格、内部的空格和换行符都保留了，超出容器的地方发生了折行。
3.5 white-space: pre-line
white-space属性为
pre-line时，意为保留换行符。除了换行符会原样输出，其他都与
white-space:normal规则一致。
p {
  white-space: pre-line;
}
显示效果如下图。
除了文本内部的换行符没有转成空格，其他都与
normal的处理规则一致。这对于诗歌类型的文本很有用。
四、参考链接
When does white space matter in HTML?，by Patrick Brosset
white-space，by Sara Cope