Giter Club home page Giter Club logo

blog's Introduction

blog's People

Contributors

xiongshj avatar

blog's Issues

CSS 世界 - 术语和概念

CSS 世界 - 术语和概念

这是学习《CSS 世界》第 2 章的笔记。

  • inherit 称作“泛关键字”,就是“所有 CSS 属性都可以使用的关键字”的意思。
  • currentColor 变量。
  • 长度单位可以分为相对长度单位和绝对长度单位。
    • 相对长度单位。相对长度单位又分为相对字体长度单位和相对视区长度单位。
      • 相对字体长度单位,如 em 和 ex,还有 CSS3 中的 rem 和 ch(字符 0 的宽度)。
      • 相对视区长度单位,如 vh、vw、vmin 和 vmax。
    • 绝对长度单位:最常见的就是 px,还有 pt、cm、mm、pc 等了解一下就可以(实用性近乎零)。
  • 属性名加上属性值就是声明,例如color: transparent
  • @规则指的是以@字符开始的一些规则,像@media@font-face@page 或者 @support,诸如此类。
  • 规范顾及不到的细枝末节的实现,称为“未定义行为”。

小结

加油。

过渡

过渡

这是学习《CSS 权威指南》第 17 章的笔记。

CSS 过渡

CSS 过渡能控制一段时间内属性的值如何变成另一个值。

如果浏览器不支持 CSS 过渡相关的属性,变化立即完成,而不逐渐过渡,对最终结果完全没有影响。同样,如果属性或提供给属性的值不支持动画,变化也立即完成,而不逐渐过渡。

定义过渡的属性

在 CSS 中,过渡使用四个属性定义:transition-property、transition-duration、transition-timing-function 和 transition-delay。此外,还有个简写属性 transition,可一次声明全部四个属性。

transition-property 属性

transition-property 属性指定想应用过渡效果的 CSS 属性名称。这样便可以限定只在特定的属性上应用过渡效果,而其他属性值的变化则瞬间完成。

transition-property 属性的值是以逗号分隔的属性列表;或者是 none,表示不过渡任何属性;还可以是默认值 all,即“过渡所有支持动画的属性”。以逗号分隔的属性列表中也可以包含关键字 all。

如果只有关键字 all,或者默认为 all,那么所有支持动画的属性将一起过渡。

默认情况下没有过渡效果,然后如果设置了过渡,而后又想在特定的情况下撤销过渡效果,可以使用 transition-property: none' 覆盖整个过渡声明,禁用所有属性的过渡效果。

none 关键字只能作为该属性的唯一一个值,不能放在以逗号分隔的一组值中。

过渡结束后都会触发 transitionend 事件。

transition-duration 属性

设置过渡持续时间使用 transition-duration 属性,这个属性的值是以逗号分隔的时间长度列表,单位为秒(s)或毫秒(ms)。默认为 0s。

如果两个状态声明的 transition-duration 值不一样,过渡的持续时间为目标状态声明的 transition-duration 值。

transition-duration 属性的值是正数,规范要求必须带时间单位,就算设为零秒,也要写成 0s。

如果声明的属性数量与持续时间的数量不一致,根据各浏览器制定的规则处理。如果持续时间的数量比属性多,忽略多出的持续时间。如果属性的数量比持续时间多,重复使用前面的持续时间。

如果恰好声明两个持续时间,奇数位上的属性使用第一个持续时间,偶数位上的属性使用第二个持续时间。

一般来说,持续时间在 100 到 200 毫秒之间的过渡效果最好,用户能看到动画过程,而且不至于分散注意力。

transition-timing-function 属性

transition-timing-function 属性用于控制过渡的步调,初始值是 ease。

transition-timing-function 属性可以取的值有 ease、linear、ease-in、ease-out、ease-in-out、step-start、step-end、steps(n, start)(n 是步进的次数)、steps(n, end) 和 cubic-bezier(x1, y1, x2, y2)。

transition-delay 属性

transition-delay 属性在元素上发生触发过渡的变化与开始过渡之间引入一定的延迟。

把 transition-delay 设为 0s(默认值),过渡立即开始,即一旦元素的状态发生变化就开始过渡。

有趣的是,transition-delay 属性的值可以是负数。此时,如果 transition-delay 的绝对值比 transition-duration 的值小,从中间某个位置立即开始过渡;如果 transition-delay 的绝对值大于或等于 transition-duration 的值,属性的值瞬间变化,就像没有应用 transition 属性一样,因此也就不触发 transitionend 事件。

transition 简写属性

transition 属性是 transition-property、transition-duration、transition-timing-function 和 transition-delay 四个属性的合并简写形式。初始值是 all 0s ease 0s。

transition 属性中唯有 transition-duration 部分是真正必须的,其他部分省略的话都取默认值。持续时间必须在延迟时间之前。

小结

浏览器对过渡的支持极好。

过渡算是一种渐进增强。

加油呀。

流的破坏与保护

流的破坏与保护

这是学习《CSS 世界》第 6 章的笔记。

魔鬼属性 float

text-align 和 vertical-align 对块级元素无效。

float 会把元素块状化。

float 的天然克星 clear

clear 属性只有块级元素才有效。

CSS 世界的结界——BFC

BFC 全称为 block formatting context,中文为“块级格式化上下文”。相对应的还有 IFC,也就是 inline formatting context,中文为“内联格式化上下文”。

如果一个元素具有 BFC,内部子元素不会影响到外部的元素。所以,BFC 元素是不可能发生 margin 重叠的,因为 margin 重叠是会影响外面的元素的;BFC 元素也可以用来清除浮动的影响,因为如果不清除,子元素浮动则父元素高度塌陷,必然会影响后面元素布局和定位,这显然有违 BFC 元素的子元素不会影响外部元素的设定。

常见触发 BFC 的情况:

  • 根元素;
  • float 的值不为 none;
  • overflow 的值为 auto、scroll 或 hidden;
  • display 的值为 table-cell、table-caption 和 inline-block 中的任何一个;
  • position 的值不为 relative 和 static。

换言之,只要元素符合上面任意一个条件,就无须使用 clear: both 属性去清除浮动的影响了。

BFC 的表现原则,具有 BFC 特性的元素的子元素不会受外部元素的影响,也不会影响外部元素。

BFC 声明家族能担任自适应布局重任的:

  • overflow: auto/hidden,适用于 IE7 及以上版本浏览器;
  • display: inline-block,适用于 IE6 和 IE7;
  • display: table-cell,适用于 IE8 及以上版本浏览器。

最后,我们可以提炼出两套 IE7 及以上版本浏览器适配的自适应解决方案。

  • 借助 overflow 属性,如下:
.lbf-content {
  overflow: hidden;
}
  • 融合 display: table-cell 和 display: inline-block,如下:
.lbf-content {
  display: tabel-cell;
  width: 9999px;
  /* 如果不需要兼容 IE7,下面样式可以省略 */
  display: inline-block;
  width: auto;
}

最佳结界 overflow

要想彻底清除浮动的影响,最适合的属性不是 clear 而是 overflow。一般使用 overflow: hidden,利用 BFC 的“结界”特性彻底解决浮动对外部或兄弟元素的影响。

overflow 支持的属性值:

  • visible:默认值。
  • hidden:剪裁。
  • scroll:滚动条区域一直在。
  • auto:不足以滚动时没有滚动条,可以滚动时滚动条出现。

如果 overflow-x 和 overflow-y 属性中的一个值设置为 visible 而另外一个设置为 scroll、auto 或 hidden,则 visible 的样式表现会如同 auto。但是,scroll、auto 和 hidden 这 3 个属性值是可以共存的。

在 PC 端,无论是什么浏览器,默认滚动条均来自 <html>,而不是 <body> 标签。所以,如果我们想要去除页面默认滚动条,只需要 html { overflow: hidden; }。这个规则只对 PC 端有效,对于移动端并不一定适用。例如,在 PC 端,对 <html> 标签设置 overflow: hidden 可以隐藏滚动条禁止滚动,但是在移动端基本上无效。在 PC 端,窗体滚动高度可以使用 document.documentElement.scrollTop 获取,但是在移动端,可能就要使用 document.body.scrollTop 获取。

滚动条会占用容器的可用宽度或高度。

单行文字溢出点点点效果:

.ell {
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}

对 -webkit- 私有前缀支持良好的浏览器还可以实现多行文字打点效果,但是却无须依赖 overflow: hidden。比如,最多显示 2 行内容,再多就打点的核心 CSS 代码如下:

.ell-rows-2 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

实现返回顶部效果:

<a href="#">返回顶部</a>

overflow: hidden 元素依然可以滚动。

float 的兄弟 position: absolute

<span> 元素默认是 inline 水平,但是一旦设置 position: absolute,其 display 计算值就变成了 block

“包含块” 计算规则,具体如下(不常用的未列出):

  1. 根元素(很多场景下可以看成是<html>)被称为“初始包含块”,其尺寸等同于浏览器可视窗口大小。
  2. 对于其他元素,如果该元素的 positionrelative 或者 static,则“包含块”由其最近的块容器祖先盒的 content box 边界形成。
  3. 如果元素 positin: fixed,则“包含块”是“初始包含块”。
  4. 如果元素 position: absolute,则“包含块”由最近的 position 不为 static 的祖先元素建立,具体方式如下:如果该祖先元素是纯 inline 元素,则规则略复杂:
  • 假设给内联元素的前后各生成一个宽度为 0 的内联盒子(inline box),则这两个内联盒子的 padding box 外面的包围盒就是内联元素的“包含块”;
  • 如果该内联元素被跨行分割了,那么“包含块”是未定义的,也就是 CSS2.1 规范并没有明确定义,浏览器自行发挥。

否则,“包含块”由该祖先的 padding box 边界形成。

如果没有符合条件的祖先元素,则 “包含块”是“初始包含块”。

可以看到,和常规元素相比,absolute 绝对定位元素的“包含块”有以下 3 个明显差异:

  1. 内联元素也可以作为“包含块”所在的元素;
  2. “包含块”所在的元素不是父级元素,而是最近的 position 不为 static 的祖先元素或根元素;
  3. 边界是 padding box 而不是 content box。

具有相对特性的无依赖 absolute 绝对定位

即使写了很多年 CSS 代码的人也可能会错误地回答下面这个问题:一个绝对定位元素,没有任何 left/top/right/bottom 属性设置,并且其祖先元素全部都是非定位元素,其位置在哪里?

很多人都认为是在浏览器窗口左上方。实际上,还是当前位置,不是在浏览器左上方。

这是关于 absolute 绝对定位最典型的错误认知。正是这种错误认知导致凡是使用 absolute 绝对定位的地方,一定父容器 position: relative,同时 left/top 等属性定位,甚至必同时使用 z-index 属性设置层级。

这是非常严重的认知和使用错误!

请牢记下面这句话:absolute 是非常独立的 CSS 属性值,其样式和行为表现不依赖其他任何 CSS 属性就可以完成。

实现在文字右上方增加小图标:

.icon-hot {
  position: absolute;
  margin: -6px 0 0 2px;
  width: 28px;
  height: 11px;
  background: url(hot.gif);
}

一个简简单单的 position: absolute,然后通过 margin 属性进行定位,效果即达成,包括 IE6 在内的浏览器都是兼容良好的。

同样是 position: absolute,通过简单的 margin 偏移实现。此方法兼容性很好,与 inline-block 对齐相比的好处在于,inline-block 对齐最终行框高度并不是 20px,因为中文下沉,图标居中,要想视觉上水平,图标 vertical-align 对齐要比实际低一点儿,这就会导致最终整个行框的高度并不是预期的 20px,而是 21px 或者更大。但是,如果使用“无依赖绝对定位”实现,则完全不必要担心这一问题,因为绝对定位元素不会改变正常流的尺寸空间,就算我们的图标有 30px 大小,行框高度依然是纯文本所在的 20px 高度。

absolute 的流体特性

<div> 之类的普通块级元素拥有流体特性。实际上,绝对定位元素也具有类似的流体特性,当然,不是默认就有的,而是在一定条件下才具有,这个条件就是“对立方向同时发生定位的时候”。

left/top/right/bottom 是具有定位特性元素专用的 CSS 属性,其中 left 和 right 属于水平对立定位方向,而 top 和 bottom 属于垂直对立定位方向。

当一个绝对定位元素,其对立定位方向属性同时有具体定位数值的时候,流体特性就发生了。例如:

.box {
  position: absolute;
  left: 0;
  right: 0;
}

如果只有 left 属性或者只有 right 属性,则由于包裹性,此时 .box 宽度是 0。但是在本例中,由于 left 和 right 同时存在,所以宽度就不是 0,而是表现为“格式化宽度”,宽度大小自适应于 .box 包含块的 padding box,也就是说,如果包含块 padding box 宽度发生变化,.box 的宽度也会跟着一起变。

position: relative

relative 的定位有两大特性:一是相对自身;二是无侵入。

“无侵入”的意思是,当 relative 进行偏移定位的时候,一般情况下不会影响周围元素的布局。

relative 的定位还有另外两点值得一提:相对定位元素的 left/top/right/bottom 的百分比值是相对于包含块计算的,而不是自身。注意,虽然定位位移是相对自身,但是百分比值的计算不是。

当相对定位元素同时应用对立方向定位值得时候,也就是 top/bottom 和 left/right 同时使用的时候,只有一个方向的定位属性会起作用(哪个方向生效与文档流的顺序有关,默认的是 top 和 left 生效)。

position: fixed 固定定位

position: fixed 固定定位元素的“包含块”是根元素,我们可以将其近似看成 <html> 元素。

蒙层弹窗是网页中常见的交互,其中黑色半透明全屏覆盖的蒙层基本上都是使用 position: fixed 定位实现的。

小结

昨天是世界读书日,买了一本书,叫《牧羊少年奇幻之旅》,上面有句话“当你想要某种东西时,整个宇宙会合力助你实现愿望”。

所以,加油吧。

CSS 世界 - 概述

CSS 世界 - 概述

这是学习《CSS 世界》第 1 章的笔记。

在 CSS 这个世界中,CSS 并不是一个机械枯燥的语言,所有属性都是有血有肉、有着不同个性和身世的个体。不同的个体可以碰撞出不同的火花,激荡出异彩纷呈的故事。

  • 在 CSS 世界中,HTML 是魔法石,选择器就是选择法器,CSS 属性就是魔法师,CSS 各种属性值就是魔法师的魔法技能,浏览器就是他们所在的“王国”。
  • CSS 世界的诞生就是为图文信息展示服务的。
  • 流(文档流),就是 CSS 世界中引导元素排列和定位的一条看不见的“水流”。
  • “流”的特性对<table>并不适用。

小结

人得自个儿成全自个儿。--《霸王别姬》

浮动及其形状

浮动及其形状

这是学习《CSS 权威指南》第 10 章的笔记。

浮动

在 CSS 中,浮动通过 float 属性实现。

float 取值有三:left、right 和 none(初始值)。

float 属性不继承。

浮动的元素

元素浮动后,其他内容将围绕它流动。

浮动元素四周的外边距不折叠。

如果浮动的是非置换元素,要为元素设定宽度。否则,根据 CSS 规范,元素的宽度趋近于零。

float: none 的作用是彻底禁止元素浮动。

浮动详解

浮动元素的容纳块是最近的块级祖辈元素。

不管元素是什么类型,浮动后得到的都是块级框。

浮动元素与内容重叠

行内框与浮动元素重叠时,其边框、背景和内容都在浮动元素“之上”渲染。

块级框与浮动元素重叠时,其边框和背景在浮动元素“背后”渲染,而内容在浮动元素“之上”渲染。

清除浮动

清除浮动使用 clear 属性,可以取的值有四个:

h3 {
  clear: left; /* 清除左边,右边不受影响 */
}

h3 {
  clear: both; /* 目标元素的两边都不与浮动的元素共存 */
}

h3 {
  clear: right; /* 清除右边,左边不受影响 */
}

h3 {
  clear: none; /* 初始值,不清除浮动 */
}

在 CSS1 和 CSS2 中,clear 起作用的方式是增加元素的上外边距,把元素移到浮动的元素下方。因此,为元素声明的上外边距其实会被忽略。

然而,CSS 2.1 引入了间距(clearance)这个概念。间距是为了把元素向下移动,确保显示在浮动元素的下方而在元素上外边距上方增加的额外空白。这意味着,清楚了浮动的元素,其上外边距不再受到影响。现在,元素下移是因为有这一块间距。

浮动形状

定义形状

若想规定浮动元素周围的内容按什么形状流动,首先要定义一个形状。shape-outside 属性就是这个作用。

(1)shape-outside 初始值为 none,这个时候,除了浮动元素自身的外边距框,没有形状,与常规情况下一样。

(2)使用图像定义浮动形状,内容将流入与之“直接接触”那一侧的透明部分。

img.lunar {
  float: left;
  shape-outside: url("moon.png");
}
<img class="lunar" src="moon.png">

也就是说,上述代码的结果,内容不会同时流入图像的左右两边,而是只流入右边。因为这个图像是向左浮动的,所以与内容直接接触的是右边。

注意,图像必须有透明区域才能定义浮动形状。如果图像格式为 JPEG,或者是没有 alpha 通道的 GIF 或 PNG,得到的形状将是矩形,这与 shape-outside: none 的效果没有任何区别。

(3) 基本形状:

  • inset() 内凹形状
  • circle() 圆形
  • ellipse() 椭圆形
  • polygon() 多边形

形状框:

  • margin-box
  • border-box
  • padding-box
  • content-box

这些形状框指明形状最外边的界限,可以单独使用。

默认使用外边距框,没有定义形状时浮动框就以外边距为界限。

此外,还可以把形状框与基本形状结合在一起使用。例如,可以这么声明:

shape-outside: inset(10px) border-box;

定义内凹形状时,设定的是从形状框各边向内偏移的距离,可以使用一个到四个长度或百分数值,以及一个可选的圆角值。

例如,下述声明把形状框内缩 2.5em:

shape-outside: inset(2.5em);

这里,形状框的四个内边界都向内偏移 2.5em。此时,型状框是外边界框(默认)。假如想从内边距框向内偏移,要把值改成这样:

shape-outside: inset(2.5em) padding-box;

内凹形状计算向内偏移时可以为形状定义圆角(与 border-radius 类似)。

shape-outside: inset(7% round 5px);

或者圆角是椭圆形的:shape-outside: inset(7% round .5em/5px);,这里宽为 0.5em,高为 5px。

圆形和椭圆形浮动形状的句法十分接近,两种情况下都要定义半径(椭圆需要两个半径)和中心点的位置。

.hello {
  shape-outside: circle(25px);
  shape-outside: circle(25px at center);
  shape-outside: circle(25px at 50% 50%);

  shape-outside: circle(3em at top left);
  shape-outside: circle(50% at top left);

  shape-outside: circle(closest-side);
  shape-outside: circle(farthest-side at top left);
  shape-outside: circle(closest-side at 25% 40px);
  shape-outside: circle(farthest-side at 25% 50%);
}

椭圆形,除了换成 ellipse()之外,椭圆与圆之间在句法上的区别是要定义两个半径。第一个横轴,第二个纵轴。

.world {
  shape-outside: ellipse(25% 50% at center);
  shape-outside: ellipse(25% 50% at 25% 25%);
  shape-outside: ellipse(67% 33% at center);
  shape-outside: ellipse(100% 33% at center left);

  shape-outside: ellipse(closest-side);
  shape-outside: ellipse(farthest-side at top left);
  shape-outside: ellipse(closest-side at 25% 40px);
  shape-outside: ellipse(farthest-side at 25% 40px);
}

多边形形状的句法较复杂,但是却更好理解一些。多边形形状由一系列逗号分隔的 x-y 坐标定义,值可以使用长度或百分数,相对形状框的左上角计算。一对 x-y 坐标指定多边形的一个顶点。

.hi {
  shape-outside: polygon(25px 0, 50px 25px, 25px 50px, 0 25px);
  shape-outside: polygon(50% 0, 100% 50%, 50% 100%, 0 50px);
}

跟之前一样,形状绝不会超出形状框,而是会被形状框裁剪。

多边形还有一个独特之处,即可以调整填充规则。默认的填充规则是 nonzero(完全填充),此外还可以使用 evenodd(部分填充)。

.go {
  shape-outside: polygon(nonzero, 51% 0%, 83% 100%, 0 38%, 100% 38%, 20% 100%);
  shape-outside: polygon(evenodd, 51% 0%, 83% 100%, 0 38%, 100% 38%, 20% 100%);
}

使用透明图像定义形状

前面说过,可以使用有透明区域的图像定义浮动形状。图像中任何不完全透明的部分都是形状的一部分,这是默认行为,不过可以使用 shape-image-threshold 属性修改。

这个属性用于指定透明度为多少时允许内容流入。反过来说则是,不透明度为多少时算在浮动形状内。

shape-image-threshold: 0.5; 来说,图像中透明度超过 50% 的部分将允许内容流入,而透明度小于 50% 的部分则构成浮动形状。

为形状添加外边距

定义好浮动形状之后,可以使用 shape-margin 属性为形状添加“外边距”。

img {
  float: left;
  margin: 0;
  shape-outside: url("star.svg");
  border: 1px solid hsla(0, 100%, 50%, .25);
  shape-margin: 0; /* 0 是初始值 */
}

小结

原来浮动还能这么好玩。

栅格布局

栅格布局

这是学习《CSS 权威指南》第 13 章的笔记。

创建栅格容器

栅格有两种:常规栅格和行内栅格。这两种栅格使用 display 属性的特殊值创建:grid 和 inline-grid。前者生成块级框,后者生成行内框。

栅格容器的子元素是栅格元素。子元素的子元素不是栅格元素。

栅格容器的外边距不与其后代的外边距折叠。

有些 CSS 属性和功能不能用在栅格容器和栅格元素上,如下:

(1)栅格容器上的所有 column 属性(例如 column-count、columns 等)都被忽略。

(2)栅格容器没有 ::first-line 和 ::first-letter 伪元素,如果使用,将被忽略。

(3)栅格元素(而非栅格容器)上的 float 和 clear 属性将被忽略。

(4)vertical-align 属性对栅格元素不起作用。

如果为栅格容器声明的 display 值是 inline-grid,而目标元素是浮动的或绝对定位的,那么 display 的计算值将变为 grid(取代 inline-grid)。

基本的栅格术语

栅格元素是在栅格格式化上下文中参与栅格布局的东西。这通常是栅格容器的子元素,但也可以是元素内容中的匿名文本(即不在元素中的文本)。

栅格轨道(grid track)指两条相邻的栅格线之间夹住的整个区域,从栅格容器的一边延伸到对边,即栅格列或栅格行。栅格轨道的尺寸由栅格线的位置决定。

栅格单元(grid cell)指四条栅格线限定的区域,内部没有其他栅格线贯穿,类似于单元格。这是栅格布局中区域的最小单位。栅格单元不能直接使用 CSS 栅格属性处理,即没有属性能把一个栅格元素放在指定的栅格单元里。

栅格区域(grid area)指任何四条栅格线限定的矩形区域,由一个或多个栅格单元构成。最小的栅格单元区域是一个栅格单元,最大的栅格区域是栅格中所有的栅格单元。栅格区域能使用 CSS 属性直接处理,定义好栅格区域后即可在其中放置栅格元素。

上述栅格术语演示图

栅格容器属性

grid-template-rows 和 grid-template-columns 属性

grid-template-rows,grid-template-columns 使用这两个属性可以大致定义栅格模板(grid template,CSS 规范称之为 explicit grid,显式栅格)中的栅格线。栅格中的一切都依赖栅格线。这两个属性的初始值是 none,适用于栅格容器。

(1)定义三个宽度固定的栅格列:

#grid {
  display: grid;
  grid-template-columns: 200px 50% 100px; 
}

(2)为栅格线命名:

#grid {
  display: grid;
  grid-template-columns: [start col-a] 200px [col-b] 50% [col-c] 100px [stop end last];
  grid-template-rows: [start masthead] 3em [content] 80% [footer] 2em [stop end];
}

(3)minmax(a, b) 函数设定一个长度范围,表示长度就在这个范围之中。

#grid {
  display: grid;
  grid-template-rows: [start masthead] 3em [content] minmax(3em, 100%) [footer] 2em [stop end];
}

minmax() 表达式的最小值部分不允许使用 fr 单位。

如果最小值比最大值大,那么整个值将替换为最小值。因此,minmax(500px, 200px) 将视为只有 500px 一个值。

(4)轨道的高度(或宽度)还可以使用 calc() 计算。

#grid {
  display: grid;
  grid-template-rows: [start masthead] 3em [content] calc(100% - 5em) [footer] 2em [stop end];
}

(5)份数单位:如果想把余下的空间分成一定份数,分配给各栏,可以使用 fr 单位。

#grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
}

(6)min-content 意思是“尽量少占据空间,够显示内容即可”。max-content 意思是“占据内容所需的最大空间”。auto 关键字表示由浏览器自行决定长度。

(7)fit-content

fit-content() 函数的参数为一个长度或一个百分数。

fit-content(argument) => min(max-content, max(min-content, argument))

这个公式的意思是:先确定 min-content 和指定的参数哪个大,然后拿较大的那个值与 max-concont 相比,找出较小的。

(8)repeat() 简化重复的值

#grid {
  display: grid;
  grid-template-columns: repeat(10, 5em);
  grid-template-columns: repeat(3, 2em 1fr 1fr);
  grid-template-columns: repeat(3, 2em 1fr 1fr) 2em;
  grid-template-columns: repeat(4, 10px [col-start] 250px [col-end] 10px);
}

(9)auto-fill 关键字

#grid {
  display: grid;
  grid-template-rows: repeat(auto-fill, [top] 5em [bottom]);
}

上述代码会每隔 5em 放置一条栅格线,直到没有空间为止。

自动重复的局限是,只能有一个可选的栅格线名称、一个尺寸固定的轨道和另一个可选的栅格线名称。

(10)如果使用 auto-fit,没有栅格元素的轨道将被剔除。除此之外,auto-fit 的行为与 auto-fill 一样。

grid-template-columns: repeat(auto-fit, 20em);

grid-template-areas 属性

栅格区域可以使用 grid-template-areas 指定,这个属性的初始值是 none,适用于栅格容器。

#grid {
  display: grid;
  grid-template-areas: "h h h h"
                       "l c c r"
                       "l f f f";
}

每个字符串(放在一对双引号中)定义栅格的一行。

浏览器把名称相同的相邻单元合并为一个区域,不过得到的形状必须是矩形。

定义好栅格区域之后,接下来要使用 grid-template-columns 和 grid-template-rows 定义栅格轨道的尺寸。例如:

#grid {
  display: grid;
  grid-template-areas: "header header header header"
                       "left   ...    ...    right"
                       "footer footer footer footer";
  grid-template-columns: 1fr 20em 20em 1fr;
  grid-template-rows: 40px 10em 3em;
}

grid-auto-flow 属性

栅格流主要分为两种模式,即行优先和列优先。栅格流通过 grid-auto-flow 属性设置。这个属性的初始值是 row,适用于栅格容器。

#grid {
  display: grid;
  width: 45em;
  height: 8em;
  grid-auto-flow: row;
}

如果想让栅格元素尽量紧靠,而不管顺序会受到什么影响,只需要在 grid-auto-flow 的值里面加上关键字 dense。

grid-auto-flow: dense column;

grid-auto-rows 和 grid-auto-columns 属性

默认情况下,自动增加的行是所需的最小尺寸。如果想指定新增的行的大小,可以使用 grid-auto-rows 和 grid-auto-columns 这两个属性,它们的初始值是 auto,适用于栅格容器。

.grid {
  display: grid;
  grid-template-rows: 80px 80px;
  grid-template-columns: 80px 80px;
}

#g1 {
  grid-auto-rows: 80px;
}

上面代码的效果演示图

grid 简写属性

grid 属性是 grid-template-rows、grid-template-columns、grid-template-areas、grid-auto-flow、grid-auto-rows、grid-auto-columns 这六个属性的合并简写形式。适用于栅格容器。

grid 属性的作用是以简洁的语法定义栅格模板,或者设定栅格流,并为自动增加到轨道设定尺寸。但是二者不能同时设置。

未定义的值都重置为默认值,这与其他简写属性是一致的。

#grid {
  display: grid;
  grid: "header header header header" 3em
        ". content sidebar ." 1fr
        "footer footer footer footer" 5em / 
        2em 3fr minmax(10em, 1fr) 2em;

  /* 下面的规则与上面的 grid 声明是等效的 */
  grid-template-areas: "header header header header"
                       ". content sidebar ."
                       "footer footer footer footer";
  grid-template-rows: 3em 1fr 5em;
  grid-template-columns: 2em 3fr minmax(10em, 1fr) 2em;

  /* 把字符串去掉 */
  grid: 3em 1fr 5em / 2em 3fr minmax(10em, 1fr) 2em;
}

grid 属性的另一个用法是融合 grid-auto-flow、grid-auto-rows 和 grid-auto-columns。下面两个规则是等效的:

#layout {
  grid-auto-flow: dense rows;
  grid-auto-rows: 2em;
  grid-auto-columns: minmax(1em, 3em);
}

#layout {
  grid: dense rows 2em / minmax(1em, 3em);
}

grid-row-gap 和 grid-column-gap 属性

栏距是两个栅格轨道之间的间隔。这两个属性的初始值是 0,适用于栅格容器。

grid-row-gap: 15px;
grid-column-gap: 1em;

这两个属性现已改名为 row-gap 和 column-gap。

grid-gap 属性

grid-gap 属性把行和列的栏距合在一起设定。初始值是 0 0,适用于栅格容器。

grid-gap: 12px 2em;

这个属性现已改名为 gap。

justify-items 和 align-items 属性

justify-items 和 align-items 属性用来横向对齐或纵向对齐全部元素,适用于栅格容器。

#grid {
  display: grid;
  align-items: center;
  justify-items: center;
}

上面的代码让栅格中的所有栅格元素在各自的栅格区域里居中对齐:效果演示图

justify-content 和 align-content 属性

使用 justify-content 和 align-content 属性以一定的方式分布栅格元素,抑或横向对齐或纵向对齐整个栅格。

链接中第 65-68 个图是这两个属性的可选值(部分)演示。

栅格元素属性

grid-row-start、grid-row-end、grid-column-start 和 grid-column-end 属性

栅格元素的位置是可以指定的,具体方法是指定栅格元素的四个边框,分别定位在哪根栅格线上。

这四个属性的初始值都是 auto,适用于栅格元素和绝对定位元素(前提是容纳块为栅格容器)。

.grid {
  display: grid;
  width: 50em;
  grid-template-rows: repeat(5, 5em);
  grid-template-columns: repeat(10, 5em);
}

.one {
  grid-row-start: 2;
  grid-row-end: 4;
  grid-column-start: 2;
  grid-column-end: 4;
}

.two {
  grid-row-start: 1;
  grid-row-end: 3;
  grid-column-start: 5;
  grid-column-end: 10;
}

.three {
  grid-row-start: 4;
  grid-column-start: 6;
}

上面代码的效果演示图

如果省略结束栅格线,那么结束栅格线使用序列中的下一条栅格线。

此外,还可以使用另一种方式:把结束值改为 span 1,或者只使用 span。

.three {
  grid-row-start: 4;
  grid-row-end: span 1;
  grid-column-start: 6;
  grid-column-end: span;
}

如果 span 后面有数字,意思是“跨指定数目的栅格轨道”。如果 span 后面没有数字,默认为 1。

对结束线来说,auto 通常指跨一个栅格单元后的栅格线。

grid-row 和 grid-column 属性

grid-row 属性是 grid-row-start 和 grid-row-end 的合并简写形式,grid-column 属性是 grid-column-start 和 grid-column-end 属性的合并简写形式。

.one {
  grid-row: R 3 / 7;
  grid-column: col-B / span 2;
}

在以斜线分隔的两部分中,前一部分定义的是开始栅格线,后一部分定义的是结束栅格线。

如果值中没有斜线,那么定义的是开始栅格线,结束栅格线取决于开始栅格线的值。如果开始栅格线是用名称引用的,那么结束栅格线也使用那个名称引用。因此,下面两个声明是等效的:

grid-column: col-B;
grid-column: col-B / col-B;

如果只提供一个数字,那么第二个数字(即结束线的编号)被设为 auto。因此,下面两个声明式等效的:

grid-row: 2;
grid-row: 2 / auto;

grid-area 属性

通过行线和列线附加元素是不错,但是我们可以只使用一个属性引用栅格区域,那就是 grid-area 属性。

这个属性适用于栅格元素和绝对定位的元素(前提是容纳块为栅格容器)。

grid-area 较为简单的用法:把元素指定给定义好的栅格区域。

#grid {
  display: grid;
  grid-template-areas: "header   header  header  header"
                       "leftside content contnet rightside"
                       "leftside footer  footer  footer";
}

#masthead {
  grid-area: header;
}

#sidebar {
  grid-area: leftside;
}

#main {
  grid-area: contnet;
}

#navbar {
  grid-area: rightside;
}

#footer {
  grid-area: footer;
}
<div id="grid">
  <div id="masthead">...</div>
  <div id="main">...</div>
  <div id="navbar">...</div>
  <div id="sidebar">...</div>
  <div id="footer">...</div>
</div>

上面代码的效果演示图

就是这么简单:先设置一些具名栅格区域,定义布局,然后通过 grid-area 把栅格元素放入指定区域。

此外,还可以使用 grid-area 引用栅格线。

.box03 {
  grid-area: 1 / 1 / 2 / 2;
}

栅格线值的顺序:row-start、column-start、row-end、column-end,这些值是按逆时针排列的。

justify-self 和 align-self 属性

justify-self 和 align-self 两个属性适用于栅格元素,分别在横向和纵向上对齐单个元素。

可选值(部分)演示图

分层和排序

如果栅格元素之间发生了重叠的情况,可以使用 z-index 属性指定栅格元素的重叠顺序。

小结

栅格布局复杂而强大,需要花些时间才能掌握。

没有吃透也不要灰心,在艰辛而曲折的学习过程中,耐心和毅力总会有回报。

定位

定位

这是学习《CSS 权威指南》第 11 章的笔记。

基本概念

定位的类型

定位类型使用 position 属性指定,有五种类型:

(1)static(初始值)。正常生成元素框。块级元素生成矩形框,位于文档流中;行内元素生成一个或多个行框,随父元素流动。

(2)relative。元素偏移一定的距离。元素的形状与未定位时一样,而且元素所占的空间也与正常情况下相同。

(3)absolute。元素框完全从文档流中移除,相对容纳块定位。此时,容纳块可能是文档中的另一个元素,也可能是初始容纳块。正常情况下元素在文档流中占据的空间不复存在,好似元素没有出现过一样。不管元素在常规的文档流中生成什么类型的框体,定位后生成的都是块级框。

(4)fixed。元素框的行为类似于 absolute,不过容纳块是视区自身。

(5)元素一开始留在常规的文档流中,达到触发粘滞的条件时,从常规的文档流中移除,不过在常规文档流中占据的空间得以保留。此时,相当于相对容纳块绝对定位。触发粘滞的条件失效后,元素回到常规文档流中最初的位置。

容纳块

对非根元素来说,如果 position 属性的值是 relative 或 static,其容纳块由最近的块级、单元格或行内块级祖辈元素框体的内容边界划定。

对非根元素来说,如果 position 属性的值是 absolute,其容纳块是 position 属性的值不是 static 的最近的祖辈元素(任何类型)。具体规则如下:

  • 如果祖辈元素是块级元素,容纳块是那个元素的内边距边界,即由边框限定的区域。
  • 如果祖辈元素是行内元素,容纳块是祖辈元素的内容边界。
  • 如果没有祖辈元素,元素的容纳块是初始容纳块。

对粘滞定位的元素来说,容纳块的边界由粘滞限定矩形确定。

偏移属性

定位使用四个属性指定定位元素的各边相对容纳块的偏移,这四个属性称为偏移属性。

偏移属性:top、right、bottom 和 left。

内容溢出

溢出使用 overflow 属性,可以取的值有四个:visible、hidden、scroll 和 auto。这个属性适用于块级元素和置换元素,默认值是 visible。

(1)visible 的意思是,超出元素框的内容是可见的。通常,这会导致内容超出所在的元素框,但是对元素框的形状没有影响。

(2)把 overflow 的值设为 scroll 时,元素的内容将在元素框的边界处裁剪(即隐藏),但是被裁剪的内容依然有方法呈现给用户。

设为 scroll 时,平移机制(例如滚动条)应该始终渲染。

(3)把 overflow 的值设为 hidden 时,元素的内容将在元素框的边界处裁剪,而且超出裁剪区的内容无法通过滚动条等页面元素查看。此时,用户看不到被裁剪的内容。

(4)overflow: auto; 这个值让用户代理自己决定使用哪种行为。

元素的可见性

控制整个元素的可见性:visibility。

visibility 可以取的值有:visible、hidden 和 collapse。

初始值是 visible,适用于所有元素,可继承。

visibility: visible; 元素是可见的。

visibility: hidden; 元素不可见,但依然像可见时那样影响文档的布局。也就是说,元素还在那里,只是看不见,就像声明 opacity: 0; 一样。

display: none; 元素不显示,完全从文档中移除。

visibility: collapse; 在渲染表格时使用。根据规范,collapse 与用在非表格元素上的 hidden 具有相同作用。

绝对定位

position: absolute;

绝对定位元素的容纳块

绝对定位的元素完全从文档流中移除,其位置相对容纳块确定,外边距的边界使用偏移属性(top、left 等)划定。

绝对定位元素的容纳块石 position 属性的值不是 static 的最近的祖辈元素。通常,创作人员选定用作绝对定位元素的容纳块的元素后,会把 position 的值设为 relative,而且不设置偏移。

绝对定位的元素是其后代元素的容纳块。

Z 轴上的位置

z-index 用于调整元素之间重叠的方式。

z-index 的值越大,元素离读者的距离越近。因此,值大的元素可能会遮盖其他元素。叠放的优先级称为堆叠次序。

z-index 的值可以设为任何整数,包括负数。

z-index 的值无需连续,想使用多大的整数都可以。

所有后代元素的堆叠次序都相对祖辈元素而言。

z-index: auto; 可以视作 z-index: 0;

固定定位

position: fixed;

固定定位与绝对定位类似,只不过固定定位元素的容纳块是视区。固定定位的元素完全从文档流中移除,其位置与文档中的任何一部分都没关系。

利用固定定位可以在界面中放一个始终可见的元素,例如一个小的链接列表。我们可以像下面这样创建一个始终可见的页脚,显示版权等信息。

footer {
  position: fixed;
  bottom: 0;
  width: 100%;
  height: auto;
}

相对定位

position: relative;

img {
  position: relative;
  top: -20px;
  left: -20px;
}

CSS 2.1 规定,如果相对定位出现过约束,把其中一个值设为另一个值的相反数。因此,bottom 始终等于 -top。

strong {
  position: relative;
  top: 10px;
  bottom: 20px;
}

上例将被视作:

strong {
  position: relative;
  top: 10px;
  bottom: -10px;
}

粘滞定位

position: sticky;

偏移属性(top、left 等)用于定义相对容纳块的粘滞定位矩形。

#scrollbox {
  overflow: scroll;
  width: 15em;
  height: 18em;
}

#scrollbox h2 {
  position: sticky;
  top: 2em;
  bottom: auto;
  left: auto;
  right: auto;
}

小结

只需要一些时间,看似复杂的知识点,其实都是纸老虎,会被你一捅就破。

CSS 和文档

CSS 和文档

这是学习《CSS 权威指南》第 1 章的笔记。

元素

对 CSS 来说,元素通常有两种形式:置换元素和非置换元素。

置换元素指用来置换元素内容的部分不由文档内容直接表示。例如:img 和 input。

HTML 元素大部分是非置换元素,即元素的内容由用户代理(通常是浏览器)在元素自身生成的框中显示。

把 CSS 应用到 HTML 上

link 标签

link 标签必须放在 head 元素中,不能放在其他元素中。

候选样式表,定义方式为把 rel 属性的值设为 alternate stylesheet。仅当用户自己选择,文档才会使用候选样式表渲染。

style 元素

开始和结束 style 标签之间的样式表称为文档样式表或嵌入式样式表。

style 元素可以直接包含应用到文档上的样式,也可以通过 @import 指令引入外部样式表。

@import 指令

@import 指令也可以显示导入的样式表应用于何种媒体,方法是在样式表的 URL 后面提供媒体描述符:

@import url(sheet2.css) all;
@import url(blueworld.css) screen;
@import url(zany.css) projection, print;

CSS 要求样式表中的 @import 指令必须在所有样式规则前面。遵守规范的用户代理会忽略放在样式规则(例如 body {color: red;})后面的 @import 指令。

HTTP 链接

为文档关联 CSS 还有一种鲜为人知的方式:使用 HTTP 首部。

截至2017年年末,广泛支持 HTTP 链接样式表的浏览器有 Firefox 和 Opera。

样式表中的内容

一些常用的厂商前缀

前缀 厂商
-epub- 国际数字出版论坛制定的 ePub 格式
-moz- 基于 Mozilla 的浏览器(如 Firefox)
-ms- 微软 Internet Explorer
-o- 基于 Opera 的浏览器
-webkit- 基于 WebKit 的浏览器(如 Safari 和 Chrome)

在 CSS 中,注释只能使用 /* */ 编写。

媒体查询

媒体类型

媒体查询最基本的形式媒体类型,由 CSS2 引入。媒体类型就是指明不同媒体的标注。

为媒体类型加上特性描述符(例如,描述指定媒体的分辨率或色深)之后事情就变得有趣了。

媒体描述符

一个媒体描述符包含一个媒体类型和一个或多个媒体特性列表,其中特性描述符要放在圆括号中。如果没有媒体类型,那就应用到所有媒体上,因此下面两个示例是等效的:

@media all and (min-resolution: 960dpi) { ... }
@media (min-resolution: 960dpi) { ... }

一般情况下,媒体特性描述符的格式类似于 CSS 中的一对属性和值。二者最大的区别是,特性描述符可以不指定值。

多个特性描述符使用逻辑关键字 and 连接。

not:对整个查询取反。假如所有条件为真,那样式表不会应用到文档上。not 关键字只能在媒体查询的开头使用。

only:在不支持媒体查询的旧浏览器中隐藏样式表。only 关键字只能用在媒体查询的开头。

特性查询

根据用户代理是否支持特性的 CSS 属性及其值来应用一段样式,这个功能称为特性查询(feature query)。

@support (color: balck) {
  body {
    color: black;
  }
  
  h1 {
    color: purple;
  }

  h2 {
    color: navy;
  }
}

特性查询是渐进增强样式的完美方式。

特性查询在结构上与媒体查询很像,可以与媒体查询互相嵌套。

小结

逃避虽然可耻,但是有用。

逃避虽然有用,但是可耻。

值和单位

值和单位

这是学习《CSS 权威指南》第 4 章的笔记。

关键字、字符串和其他文本值

有时,值用一个词表示,这叫关键字。none 是一个十分常见的关键字,它与 0(零)不同。

CSS3 定义了几个“全局”关键字,规范中的每个属性都能使用:inherit、initial 和 unset。

  • inherit 关键字把元素某个属性的值设为与父元素同一属性的值一样。
  • initial 关键字把属性的值设为预定义的初始值,相当于“重设”值。
  • unset 关键字是 inherit 和 initial 的通用替身。对继承的属性来说,unset 的作用与 inherit 一样;对不继承的属性来说,unset 的作用与 initial 一样。

有个特殊的属性只接受这几个全局关键字:all。

all 表示除 direction 和 unicode-bidi 之外的所有属性。

距离

长度单位分为两种:绝对长度单位和相对长度单位。

绝对长度单位

绝对长度单位有七个:英寸(in)、厘米(cm)、毫米(mm)、四分之一毫米(q)、点(pt)、派卡(pc)和像素(px)。

1 英寸等于 2.54 厘米,1 厘米等于 0.394英寸。  
1 厘米等于 10 毫米。  
1 英寸有 72 点。  
1 派卡等于 12 点。

分辨率单位

随着媒体查询和响应式设计的出现,为了描述显示器的分辨率,出现了三个新单位。

点每英寸(dpi):在长为 1 英寸的范围内能显示的点数。

点每厘米(dpcm):与 dpi 类似,不过测量的范围是 1 厘米,而不是 1 英寸。

点每像素单位(dppx):CSS 中每个 px 单位显示的点数。从 CSS3 起,1dppx = 96dpi。

截至 2017 年年末,这些单位只能在媒体查询中使用。

相对长度单位

相对长度单位中的“相对”是指其长度是相对其他东西而言的。

(1)em 和 ex 单位

按 CSS 的定义,1em 等于元素的 font-size 属性值。如果元素的 font-size 为 14 像素,那么对那个元素来说,1em 就等于 14 像素。ex 指所用字体中小写字母 x 的高度。字体不同,ex 就不同(即使字号相同)。

(2)rem 单位

与 em 单位类似,rem 也基于声明的字号。二者之间的区别是(很微小),em 相对当前元素的字号计算,而 rem 始终相对根元素计算。

在 HTML 中,根元素是 html。因此,font-size: 1rem; 声明把元素的字号设为与文档根元素的字号一样大。

rem 的实际作用相当于重设字号:不管祖辈元素把字号设为多大,font-size: 1rem; 都会把字号还原成根元素设定的大小。

(3)ch 单位

CSS3 新增了一个有趣的单位:ch。这个单位基本上可以理解为“一个字符”。

CSS3 规范是这样定义的:等于渲染时所用字体中“0”字形的进距。

CSS 把 ch 单位定义为所用字体中一个零的进宽。

(4)视区相关的单位

视区宽度单位(vw):这个单位根据视区的宽度计算,然后除以 100。因此,如果视区的宽度是 937 像素,那么 1vw = 9.37 px。

视区高度单位(vh):这个单位根据视区的高度计算,然后除以 100。

视区尺寸最小值单位(vmin):这个单位等于视区宽度或高度的 1/100,始终取宽度和高度中较小的那个。

视区尺寸最大值单位(vmax):这个单位等于视区宽度或高度的 1/100,始终取宽度和高度中较大值的那个。

颜色

RGBa 颜色,这里的 a 指 alpha 通道,用于衡量不透明度。

如果想让颜色完全透明,把 alpha 值设为 0;如果想完全不透明,应该设为 1。

HSL 和 HSLa 颜色,CSS3 新增了 HSL 表示法。

有两个特殊的关键字可以在任何允许使用颜色值的地方使用:transparent 和 currentColor。

transparent 表示完全透明的颜色。

currentColor 表示当前元素 color 属性计算得到的值。

角度

角度单位有四个,deg(度数)、grad(百分度)、rad(弧度)、turn(圈数)。

自定义值

自定义属性,例如:

html {
  --base-color: #639;
  --highlight-color: #aea;
}

h1 {
  color: var(--base-color);
}

h2 {
  color: var(--highlight-color);
}

自定义标识符以两个连字符开头(--)。

调用的方法是使用 var() 值类型。

小结

理解距离一节中各个单位以及它们之间的区别。

内联元素与流

内联元素与流

这是学习《CSS 世界》第 5 章的笔记。

字母 x ———— CSS 世界中隐匿的举足轻重的角色

在各种内联相关模型中,凡是涉及垂直方向的排版或者对齐的,都离不开最基本的基线(baseline)。

line-height 行高的定义就是两基线的间距。

字母 x 的下边缘(线)就是我们的基线。

CSS 中有一个概念叫做 x-height,指的是字母 x 的高度。通俗地讲,x-height 指的就是小写字母 x 的高度,术语描述就是基线和等分线(mean line,也称作中线,midline)之间的距离。

vertical-align: middle 并不是绝对的垂直居中对齐,我们平常看到的 middle 效果只是一种近似效果。

ex 是 CSS 中的一个相对单位,指的是小写字母 x 的高度,就是指 x-height。

利用默认的 baseline 基线对齐实现图标和文字中间位置对齐(链接):

.icon-arrow {
  display: inline-block;
  width: 20px;
  height: 1ex;
  background: url(arrow.png) no-repeat center;
}

内联元素的基石 line-height

div 高度是由行高决定的,而非文字。

对于非替换元素的纯内联元素,其可视高度完全由 line-height 决定。

对于文本这样的纯内联元素,line-height 就是高度计算的基石,用专业说法就是指定了用来计算行框盒子高度的基础高度。比方说,line-height 设为 16px,则一行文字高度是 16px,两行就是 32px,三行就是 48px,所有浏览器渲染解析都是这个值。

在 CSS 中,“行距”分散在当前文字的上方和下方,也就是即使是第一行文字,其上方也是有“行距”的,只不过这个“行距”的高度仅仅是完整“行距”高度的一半,因此,也被称为“半行距”。

业界的共识是:行距 = 行高 - em-box。也就是:行距 = line-height - font-size。其中 em-box 是 CSS 是世界中比较虚的一个概念,说“虚”并不是胡编乱造的意思,而是我们无法有效感知这个盒子具体的位置在哪里,但是有一点可以明确,就是其高度正好就是 1em。

line-height 不可以影响替换元素的高度。

对于块级元素,line-height 对其本身是没有任何作用的,我们平时改变 line-height,块级元素的高度跟着变化实际上是通过改变块级元素里面内联级别元素占据的高度实现的。

要让单行文字(多行也可以,需要 vertical-align 属性一起)垂直居中,只需要 line-height 这一个属性就可以,与 height 无关。这里 line-height 设置的只是近似垂直居中。

line-height 的好朋友 vertical-align

vertical-align 只能应用于内联元素及 display 值为 table-cell 的元素。

小结

未完待续。

流、元素与基本尺寸

流、元素与基本尺寸

这是学习《CSS 世界》第 3 章的笔记。

HTML 标签种类繁多,但通常我们就把它们分为两类:块级元素(block-level element) 和内联元素(inline element)。

块级元素

常见的块级元素有<div>、<li>和<table>等。需要注意的是,“块级元素”和"display 为 block 的元素”不是一个概念。例如,<li>元素默认的 display 值是 list-item,<table>元素默认的 display 值是 table,但是它们均是“块级元素”,因为它们都符合块级元素的基本特征,也就是一个水平流上只能单独显示一个元素,多个块级元素则换行显示

width/height 作用的具体细节

对于普通文档流中的元素,百分比高度值想要起作用,其父级必须有一个可以生效的高度。

让元素支持 height: 100% 效果:

  • 设定显示的高度值
  • 使用绝对定位。例如:
div {
  position: absolute;
  height: 100%;
}

需要注意的是,绝对定位元素的百分比计算和非绝对定位元素的百分比计算是有区别的,区别在于绝对定位的宽高百分比计算是相对于 padding box 的,也就是说会把 padding 大小值计算在内,但是,非绝对定位元素则是相对于 content box 计算的。

CSS min-width/max-width 和 min-height/max-height 二三事

min-width/min-height 的初始值是 auto,max-width/max-height 的初始值是 none。

max-width 会覆盖 width(即使设置了 !important); min-width 和 max-width 冲突的时候 min-width 有效。

内联盒模型-内容区域、内联盒子、行框盒子和包含盒子。

小结

加油鸭!

颜色、背景和渐变

颜色、背景和渐变

这是学习《CSS 权威指南》第 9 章的笔记。

颜色

CSS 可以为任何元素设置前景色和背景色。

一般来说,前景指元素的文本,不过也包括元素四周的边框。

设置元素前景色最简单的方法是使用 color 属性,这个属性会被继承。

元素的 currentColor 值始终为 color 属性的计算值。

一般建议同时设定前景色和背景色。

背景

默认情况下,背景区域从前景背后的空间一直延伸到边框的外边界。因此,内容框和内边距都在元素的背景中,而边框在背景之上绘制(可以使用 CSS 改变这种行为)。

通过 CSS 可以把元素的背景设为纯色,也可以设为一个或多个图像,甚至还可以设为线性渐变或径向渐变。

背景色

元素背景的颜色使用 background-color 属性声明,值为任何有效的颜色值。

background-color 属性的值不继承。这个属性的默认值为 transparent。

裁剪背景

有个 CSS 属性能控制背景延伸到何处,这个属性名为 background-clip,取值有 border-box | padding-box content-box | text。

  • 默认值(border-box)是以前一直采用的行为,即背景绘制区域延伸到边框的外边界。背景始终绘制到边框的可见部分背后。
  • 如果设为 padding-box,背景只延伸到内边距区域的外边界(即边框的内边界)。因此,边框背后不绘制背景。
  • content-box 值把背景限制在元素的内容区内。
  • text 把背景裁剪到元素的文本线条。意即,文本将使用背景“填充”,文本线条之外的背景是透明的。不过要注意,若想看到效果,要删除元素的前景色。否则,前景色将遮盖背景。

background-clip 对根元素没有效果,这和根元素背景的绘制方式有关。

背景绘制区域由 background-clip 裁剪后,如果有圆角,再由圆角进一步裁剪。

截至 2017 年年末,只有 Firefox 支持 background-clip: text 这种确切形式。不过,几乎每个浏览器,包括 Firefox,都支持 -webkit-background-clip: text

背景图

首先,要使用 background-image 属性把图像放到背景中。

与 background-color 一样,background-image 也不继承。其实,背景相关的属性都不继承。

使用背景图时最好同时指定背景色,这样至少能保证文本是可见的。

p.starry {
  background-image: url("http://www.site.web/pix/stars.gif");
  background-color: black;
  color: white;
}

背景定位

在元素的背景中放好图像之后,能不能指定图像的具体位置呢?当然没问题,使用 background-position 属性。

background-position 十分简单,这个属性的值有很多种指定方式。首先是关键字:top、bottom、left、right 和 center。通常,关键字成对出现,但也不尽然。其次是长度值,例如 50px 或 2cm。最后是百分数值,例如 43%。这几种值对背景图位置的影响稍有不同。

位置关键字的顺序随意,只要不超过两个:一个指定横向位置;一个指定纵向位置。如果使用两个横向位置关键字(right right)或两个纵向位置关键字(top top),整个值将被忽略。

如果只有一个关键字,另一个假定为 center。因此,如果想把背景图放在各个段落的上部居中位置,只需这样声明:

p {
  background-image: url("yinyang-sm.png");
  background-repeat: no-repeat;
  background-position: top;
}

如果只提供一个百分数值,那个值将做横向偏移,而纵向偏移假定为 50%。

background-position 的默认值是 0% 0%,其作用与 top left 一样。正是因为这样,在没有指定其他位置时,背景图始终从元素背景的左上角开始平铺。

关键字和长度值及百分数值可以混用。

关键字以外的值对轴的顺序有要求。也就是说,如果使用长度值或百分数,横向值必须写在首位,纵向值必须写在末位。

默认的,偏移始终相对背景区域的左上角。不过可以使用关键字实现特殊的功能:指定相对哪边计算偏移。

p {
  background-position: 33% 30px;
  background-position: left 33% top 30px;
  background-position: right 33% bottom 30px;
}

改变偏移边,基本的句法是:一个边界关键字、一个偏移距离、一个边界关键字和一个偏移距离。横向和纵向的顺序随意。如果某一个方向的偏移量为零,可以将其省略。

p {
  background-position: bottom 30px right 25%;
  background-position: right 25% bottom 30px;
  background-position: right bottom 30%;
  background-position: right 25% bottom;
}

改变定位框

background-origin 属性确定计算源图像的位置时以什么的边界为基准,定义的是 背景定位区域 (background-clip 定义的是 背景绘制区域 ),取值有 border-box | padding-box(默认值) | content-box。

背景重复方式(或不重复)

background-repeat 属性,取值有 repeat | no-repeat | space | round | repeat-x | repeat-y。

如果提供两个值,第一个值应用于横向,第二个值应用于纵向。如果只有一个值,同时应用于横向和纵向,repeat-x 和 repeat-y 例外。

repeat 关键字的效果是沿所有方向无限平铺图像。repeat-x 和 repeat-y 分别在横向和纵向上重复图像,而 no-repeat 则禁止图像沿指定的轴平铺。

space 确定沿某一轴能完全重复多少次,然后从背景区域的一边倒对边均匀排列图像。如果图像太大,在某个方向放不下,那就只出现一次,位置则由 background-position 的值确定。反过来,如果在某个方向上要重复多次,那个方向上的 background-position 值将被忽略。

相比之下,round 值在重复背景图的过程中很有可能会缩放图像,而且(奇怪的是)不覆盖 background-position 的值。如果从背景区域的一边到对边之间无法重复整数次,那么图像将被放大或缩小,恰好重复整数次。此外,图像沿各轴的缩放程度可以不同。

使用 round 时,如果不想让平铺的图像被裁剪,必须从四个角中的某一个开始平铺(而且要保证背景定位区域和背景绘制区域是相同的)。

background-clip 能改变背景的绘制区域,而 background-origin 确定源图像的位置。这两个值不同的话,使用 space 和 round 时会出现部分裁剪情况。这是因为 space 和 round 是相对背景定位区域计算的,而不是背景绘制区域。可以选择把这两个值设为一样的。

背景粘附

background-attachment 属性,取值有 fixed | local | scroll。

  • fixed 把源图像声明为固定在视区内,从而免受滚动的影响。
  • 与 fixed 的作用基本相反的是 local,即背景图随内容一起滚动。
  • 默认值 scroll,设为这个值时,在 Web 浏览器滚动文档时,背景图随之一起滚动。(这个有些不一样,用到的时候多查查文档看看)

控制背景图的尺寸

background-size 属性用来改变背景图片尺寸。

为 background-size 提供两个值时,第一个值是横向尺寸,第二个值是纵向尺寸。

声明的百分数值相对背景定位区域计算,即由 background-origin 定义的区域。

假如想让图像完全覆盖元素的背景,而且不在乎有部分图像超出背景绘制区域。此时,可以使用 cover。与之相比,contain 会将图像缩放为正好放在背景定位区域中的尺寸,允许有部分区域不被图像覆盖。

写为一个属性

背景相关的属性可以集中在一起,使用一个简写属性声明:background。

background-size 值要紧跟在 background-position 值后面,而且二者之间要以一条斜线(/)隔开。

如果同时为 background-origin 和 background-clip 提供值,前一个分配给前者,后一个分配给后者。如果只提供一个值,同时为这两个属性设定为这个值。

background 不要求必须设定任何值,只要有一个值,其他都可以省略。使用简写属性可以只设定背景颜色,而且这是很常见的做法:

body {
  background: white;
}

渐变

有两种新的图像类型完全由 CSS 实现:线性渐变和径向渐变。这两种渐变又各分为二:循环渐变和不循环渐变。

渐变指从一个颜色到另一个颜色的平滑过渡。

渐变的平缓或骤变程度取决于渐变的作用空间。

在探讨渐变的过程中请谨记一点:渐变是图像。尽管渐变是通过 CSS 实现的,但每一点都与 SVG、PNG、GIF 等图像一样。

线性渐变

线性渐变指沿线行向量填充得到的渐变。这个向量称为梯度线。梯度线始终经过渐变图像的中心点。

#ex01 {
  background-image: linear-gradient(purple, gold);
}

#ex02 {
  background-image: linear-gradient(90deg, purple, gold);
}

#ex03 {
  background-image: linear-gradient(to left, purple, gold);
}

渐变的默认方向是 to bottom,这与 180deg 和其他等量值(例如 0.5turn)的作用是一样的。

基本的格式:开头是一个可选的方向,然后列出一系列色标和(或)中色点,结尾又是一个色标。

在每个颜色值之后可以(但不强求)提供一个位置值。

色标位置的长度值不限于像素值,任何长度值都可以,em、英寸等都能用。此外,在同一个渐变中甚至可以混用不同的单位,但是一般不推荐这么做。

百分数值相对梯度线的总长度计算。位于 50% 处的色标在梯度线的中点。

如果把两个色标放在同一个点上,会由前一种颜色直接变成后一种颜色,跨度为零。这种“急变”效果可用于实现条纹:

.stripes {
  background-image: linear-gradient(90deg,
  gray 0%, gray 25%,
  transparent 25%, transparent 50%,
  gray 50%, gray 75%,
  transparent 75%, transparent 100);
}

设置中色点

#ex01 {
  background-image: linear-gradient(to right, #000 25%, rgb(90%, 90%, 90%) 75%);
}

#ex02 {
  background-image: linear-gradient(to right, #000 25%, 33%, rgb(90%, 90%, 90%) 75%);
}

#ex03 {
  background-image: linear-gradient(to right, #000 25%, 67%, rgb(90%, 90%, 90%) 75%);
}

径向渐变

径向渐变的句法与线性渐变类似,不过也有一些区别:简单来说,可以声明形状尺寸(可选),可以声明渐变的中心点在何处(可选),然后声明两个或多个色标,色标之间还可以指定中色点(可选)。

径向渐变只有两种可用的形状值(因此也就只能有两种形状),即 circle(圆形) 和 ellipse(椭圆形)。径向渐变的形状可以显式声明,也可以由渐变图像的尺寸推导出来。

指定径向渐变的尺寸时可以只提供一个非负长度值(得到的是圆形),也可以提供两个非负长度值(得到的是椭圆形)。

尺寸也可以使用百分数值,不过只能用于设定椭圆形。圆形不能用百分数指定尺寸,因为无法确定百分数相对哪一轴计算。

当然,长度值和百分数值不是设定径向渐变尺寸的唯一方式。除此之外,还可以使用四个关键字:closest-side、farthest-side、closest-corner 和 farthest-corner(默认值)。

径向渐变的中心默认放在 center,也可以使用对 background-position 属性来说任何有效的位置值。

#ex01 {
  background-image: radial-gradient(30px at bottom left, purple, gold);
}

#ex02 {
  background-image: radial-gradient(30px 15px at center right, purple, gold);
}

#ex03 {
  background-image: radial-gradient(50% 15% at 30px 30px, purple, gold);
}

#ex04 {
  background-image: radial-gradient(farthest-side at 25% 66%, purple, gold);
}

#ex05 {
  background-image: radial-gradient(farthest-corner at 30px 66%, purple, gold);
}

处理渐变图像

使用渐变有三点优势:

  • 基本可以肯定的是,CSS 所占的字节比 PNG 图像小。
  • 更为重要的是,PNG 图像要额外请求服务器。这会拖慢页面的加载时间,降低服务器的性能。CSS 渐变就在样式表中,无需额外请求服务器。
  • 修改渐变简单得多,因此你可以不断试验,直到找出合适的尺寸、形状和明暗程度。

循环渐变

循环渐变,repeating-linear-gradient 或 repeating-radial-gradient。

盒子投影

为元素所在的框体创建投影,即 box-shadow。

投影只在元素边框的外边界以外才看得到。

定义盒子投影设定的长度值,第一个定义横向偏移,第二个定义纵向偏移。如果提供第三个值,定义的是模糊距离,即指定给模糊留出多少空间。第四个值定义展开距离,这会改变投影的尺寸。正值在模糊之前延伸投影,负值使投影变小。

还有一点,即 inset 关键字。如果在 box-shadow 属性的值中加上 inset,投影在框体内部渲染,(从视觉上来讲)不再浮动在画布上,而像是向内凹陷的。

注意,inset 关键字可以在其他值前面,也可以在后面,但不能在长度和颜色之间。

最后,与文本投影一样,一个元素可以应用任意多个盒子投影,各投影之间以逗号分隔。而且,部分投影可以是内凹的,部分可以是外凸的。例如:

#shadowbox {
  background: #eee;
  box-shadow: inset 1ch 1ch 0.25ch rgba(0, 0, 0, 0.25), 1.5ch 1.5ch 0.4ch rgba(0, 0, 0, 0.33); 
}

#wacky {
  box-shadow: inset 10px 2vh 0.77em 1ch red,
  1cm 1in 0 -1px cyan inset,
  2ch 3ch 0.5ch hsla(117, 100%, 50%, 0.343),
  -2ch -3ch 0.5ch hsla(297, 100%, 50%, 0.23);
}

小结

可能否。

弹性盒布局

弹性盒布局

这是学习《CSS 权威指南》第 12 章的笔记。

弹性盒基础

弹性盒依赖父子关系。在元素上声明 display: flex;display: inline-flex; 便激活弹性盒布局,而这个元素随之成为弹性容器(flex container),负责在所占的空间内布置子元素,控制子元素的布局。弹性容器的子元素称为弹性元素(flex item)。

使用 display: flex; 声明得到的是块级框,弹性元素在其中布局;使用 display: inline-flex; 声明得到的是行内块级框,弹性元素在其中布局。

把一个元素设为弹性容器之后,只有直接子元素使用弹性盒布局,其他后代元素不受影响。

弹性容器

弹性容器,也叫容器框。display: flex;display: inline-flex; 声明的目标元素变成弹性容器,为其子元素生成弹性格式化上下文。这些子元素不论是 DOM 节点、文本节点,还是生成的内容,都称为弹性元素。

flex-direction 属性

使用 flex-direction 属性控制排布弹性元素的主轴,可以取的值有四个:row、row-reverse、column 和 column-reverse。这个属性适用于弹性容器,初始值是 row。

flex-direction 属性指定在弹性容器中如何摆放弹性元素,即定义弹性容器的主轴,弹性元素就沿这个轴排布。

如果是其他的书写方向,可能会有一些变化。不过不用担心,用到了再查阅。

flex-wrap 属性

如果弹性元素在弹性容器的主轴上放不下,默认情况下弹性元素不会换行,也不会自行调整尺寸。如果通过 flex 属性设定允许弹性元素缩减尺寸,那就缩减尺寸,否则,弹性元素将从容器框的边界溢出。

我们可以在容器上设置 flex-wrap 属性,允许弹性元素换行,变成多行或多列,而不让弹性元素从容器中溢出,或者缩减尺寸,挤在同一行。

flex-wrap 可以取的值有三个:nowrap、wrap 和 wrap-reverse。这个属性适用于弹性容器,初始值是 nowrap。

设为 wrap 或 wrap-reverse 时,如果弹性元素超出了弹性容器的边界,将换行显示放不下的弹性元素。

wrap 是正常的换行,wrap-reverse 是把换的行放到上面(即从下往上)。

flex-flow 属性

flex-flow 属性用于定义主轴和垂轴的方向,以及是否允许弹性元素换行。

flex-flow 属性是 flex-direction 和 flex-wrap 两个属性的简写形式,用于定义弹性容器的换行方式及主轴和垂轴的方向。

.hello {
  flex-flow: column-reverse wrap;
  flex-flow: wrap column-reverse;
}

垂轴:块级元素沿此轴堆叠。在弹性盒中,指放置新弹性元素行的方向(前提是允许换行)。

wrap-reverse 值反转垂轴的方向,把新行添加到前一行的上方或左侧。

flex-direction 和 flex-wrap 对布局有很大的影响,而且二者之间也有不小的影响。如果想设置其中某一个属性,最好两个都设置,此时可以使用规范强烈推荐的 flex-flow 属性。

justify-content 属性

justify-content 属性指明在弹性容器的主轴上如何分布各行里的弹性元素。这个属性应用于弹性容器上,不能用到单个弹性元素上。

这个属性可以取的值有六个:flex-start、flex-end、center、space-between、space-around 和 space-evenly。初始值是 flex-start。

justify-content 属性六个可选值的效果图

(1)设为默认值 flex-start 时,弹性元素紧靠主轴起边。

(2)设为 flex-end 时,弹性元素紧靠主轴终边。

(3)center 把弹性元素作为一个整体,居中显示在主轴尺寸的中点。

(4)space-between 值把每一行里的第一个弹性元素放在主轴起边,把每一行里最后一个弹性元素放在主轴终边,然后在余下的每一对相邻的弹性元素之间放置等量的空白。

(5)space-around 把余下的空间拆开,把各部分的一半分配给每个弹性元素,看起来就像每个元素四周都有等量的不折叠外边距。注意,这意味着任何两个弹性元素之间的距离是第一个弹性元素与主轴起边之间以及最后一个弹性元素与主轴终边之间距离的两倍。

(6)space-evenly 也把余下的空间拆分开,不过每个间距的长度是相等的。这意味着,到主轴起边和终边之间的距离,与弹性元素之间的距离是一样的。

align-items 属性

align-items 属性定义的是弹性元素在垂轴方向上的对齐方式。align-items 应用在弹性容器上,而不能应用到单个弹性元素上。

这个属性有五个可选值,包括 flex-start、flex-end、center、baseline 和 默认的 stretch。

横排演示

竖排演示

弹性元素可以向垂轴起边或终边靠拢,也可以居中,或者经过拉伸,同时靠拢起边和终边。不过 baseline 有点特殊。此时,弹性元素向基线对齐,基线与垂轴起边那一侧的边之间的距离最远的弹性元素将与弹性元素行垂轴起边那一侧的边对齐。

align-content 属性

align-content 属性定义弹性容器有额外的空间时在垂轴方向上如何对齐各弹性元素行,以及空间不足以放下所有弹性元素行时从哪个方向溢出。

align-content 可选的值有七个,包括 flex-start、flex-end、center、space-between、space-around、space-evenly 和 默认的 stretch。

align-content 属性的各个值对额外空间的分配情况

align-content 属性的各个值弹性元素行的溢出方向

align-content 属性指定弹性容器中垂轴方向上的额外空间如何分配到弹性元素行之间和周围。align-content 属性只适用于分为多行显示的弹性容器,对禁止换行及只有一行的弹性容器没有影响。

弹性元素

弹性容器的子代称为弹性元素,不管是子元素,还是元素之间非空的文本节点,或是生成的内容。

文本节点会被放在一个匿名弹性元素中,其行为与其他同辈弹性元素一样,但是不能直接使用 CSS 装饰。

弹性元素的外边距不折叠。float 和 cleat 属性对弹性元素不起作用。vertical-align 对弹性元素没有影响,只用于设定弹性元素中文本的对齐方式。

align-self 属性

align-items 设置的是弹性容器中全部弹性元素的对齐方式,而 align-self 属性能重设单个弹性元素的对齐方式。

align-self有六个可选值,包括 flex-start、flex-end、center、baseline、stretch 和 默认的 auto。

对所有 align-self 属性为默认值 auto 的弹性元素来说,其对齐方式继承自容器的 align-items 属性。其他五个可选值与 align-items 属性的值一样。

flex-grow 属性

flex-grow 属性定义弹性元素的放大比例,默认值是 0,即如果存在剩余空间,也不放大。

flex-shrink 属性

flex-shrink 属性定义弹性元素的缩小比例,默认为 1,即如果空间不足,该弹性元素将缩小。

flex-basis 属性

flex-basis 属性定义弹性元素的初始或默认尺寸,即根据增长因子和缩减因子分配多余或缺少的空间之前,弹性元素的大小。它的默认值是 auto,这时 flex-basis 等于 width(或 height),如果 width(或 height)也是 auto,那么弹性基准回落为 content。

如果既设定了 flex-basis,又设定了 width(或主轴为纵向时的 height),弹性基准的优先级比宽度(或高度)高。

flex-basis 的百分数是相对弹性容器的主轴尺寸计算。

flex 属性

flex 属性是 flex-grow、flex-shrink 和 flex-basis 的简写形式,默认值为 0 1 auto。后两个属性可选。

该属性有四个常见的弹性值:

(1)initial(0 1 auto)。

(2)auto(1 1 auto)。

(3)none(0 0 auto)。

(4)数字值。如果 flex 属性只有一个值,而且是正数,那个值将用作增长因子,而缩减因子默认为 0,基准也默认为 0。flex: 3;flex: 3 0 0; 是等效的。

虽然三个子属性可以单独使用,但是强烈建议始终使用简写的 flex 属性。

order 属性

order 属性用于修改单个弹性元素的显示顺序。数值越小,排列越靠前,默认为 0。

小结

加油吧!

选择符

选择符

这是学习《CSS 权威指南》第 2 章的笔记。

元素选择符、群组选择符、通用选择符、类选择符、ID 选择符、属性选择符、后代选择符、伪类选择符和伪元素选择符。

样式的基本规则

元素选择符

p {
  color: black;
}

声明和关键字

CSS 关键字通常以空格分隔。

不过也有一些使用斜线或逗号分隔的。

群组

群组选择符

h2, p {
  color: gray;
}

通用选择符

通用选择符:星号(*)。

* {
  color: red;
}

使用 ID 选择符、类选择符、属性选择符、伪类选择符或伪元素选择符时,如果没有依附元素选择符,隐式蕴含通用选择符。

类选择符和 ID 选择符

类选择符

p.warning {
  font-weight: bold;
}

这个选择符现在匹配 class 属性的值中包含 warning 的 p 元素,其他任何元素,不管有没有这个类,都不匹配。

多个类

把两个类选择符串在一起,选择的是同时具有两个类名的元素,而且对类名的顺序没有要求。

.warning.urgent {
  background: silver;
}

ID 选择符

ID 选择符的开头不是点号,而是个散列字元(#),也叫井号、哈希符号、哈希记号或三联棋棋盘。

*#lead-para {
  font-weight: bold;
}

与类选择符一样,ID 选择符中的通用选择符也可以省略。前面的示例还可以写成这样:

#lead-para {
  font-weight: bold;
}

这样写与之前的效果一样。

属性选择符

CSS2 引入了属性选择符,根据属性及其值选择元素。属性选择符大致可以分为四类:简单属性选择符、精准属性值选择符、部分匹配属性值选择符和起始值属性选择符。

简单属性选择符

如果想选择具有某个属性的元素,而不管属性的值是什么,可以使用简单属性选择符。

h1[class] {
  color: silver;

}

*[title] {
  font-weight: bold;
}

基于多个属性选择,要把多个属性选择符串在一起。

a[href][title] {
  font-weight: bold;
}

根据精准的属性值选择

此外,还可以进一步缩小范围,只选择属性为特定值的元素。这个形式要求属性的值与指定的值完全一致。

<p class="urgent warning">Hello CSS!</p>

若想使用精确的属性值选择这个元素,要写成:

p[class="urgent warning"] {
  font-weight: bold;
}

根据部分属性值选择

根据属性值的一部分选择元素,而不是完整的值,CSS 为这种情况提供了多种选择,以不同的方式匹配属性值的子串。

形式 说明
[foo|="bar"] 选择的元素有 foo 属性,且其值以 bar 和一个英文破折号(U+002D)开头,或者值就是 bar 本身
[foo~="bar"] 选择的元素有 foo 属性,且其值是包含 bar 这个词的一组词
[foo*="bar"] 选择的元素有 foo 属性,且其值包含子串 bar
[foo^="bar"] 选择的元素有 foo 属性,且其值以 bar 开头
[foo$="bar"] 选择的元素有 foo 属性,且其值以 bar 结尾

不区分大小写的标识符

CSS Selectors Level 4 为属性选择符引入了一个不区分大小写的选项。在结束方括号前加上 i,属性选择符便不管文档语言的要求,匹配属性值时不区分大小写。

a[href$=".PDF" i] 这个选择符能匹配 href 属性的值以 .pdf 结尾的任何 a 元素,而不管 P、D 和 F 三个字母的大小写。

根据文档结构选择

后代选择符

后代选择符也叫上下文选择符。

在后代选择符中,规则中的选择符由两个或多个空格分隔的选择符构成。选择符之间的空格是一种连接符。

h1 em {
  color: gray;
}

后代选择符中不止可以使用两个单独的选择符。

ul ol ul em {
  color: gray;
}

人们经常忽略后代选择符的一点是,两个元素之间的层级间隔可以是无限的。比如说,ul em 选择的是作为 ul 元素后代的任何 em 元素,不管 em 嵌套的有多深。

选择子元素

选择子元素,使用子代连结符,即大于号(>)。

h1 > strong {
  color: red;
}

选择作为 h1 元素的子元素的 strong 元素(而不是层级更深的后代)。

选择紧邻同胞元素

若想选择同一个父元素中紧跟在另一个元素后面的一个元素,要使用紧邻同胞连结符,即一个加号(+)。

若想把紧跟在 h1 元素后面的段落的上外边距去掉,这样写:

h1 + p {
  margin-top: 0;
}

这个选择符的意思是,“选择的 p 元素紧跟在 h1 元素后面,而且二者同属一个父元素”。

选择后续同胞

Selectors Level 3 引入一个新的同胞连结符,名为一般同胞连结符。这个连结符用波浪号(~)表示,选择一个元素后面同属一个父元素的另一个元素(不一定只有1个)。

h2 ~ ol {
  font-style: italic;
}

伪类选择符

所有伪类无一例外都是一个冒号(:)后面跟着一个词,而且可以出现在任何选择符的的任何位置。

深入讨论之前,对伪类要明确一点:伪类始终指代所依附的元素。

拼接伪类

CSS 允许把伪类拼接(串联)在一起。

结构伪类

(1):root 伪类选择文档的根元素。

(2):empty 伪类选择没有任何子代的元素,甚至连文本节点都没有(包括文本和空白)。

(3):only-child 伪类选择的元素是另一个元素的唯一子元素。

在后代选择符上使用 :only-child 伪类时,列出的元素不一定是父子关系。

(4):only-of-type 匹配同胞中唯一的那种元素,而 :only-child 只匹配完全没有同胞的元素。

(5):first-child 伪类选择一个元素的第一个子元素。

与 :first-child 对应的是 :last-child。

有趣的是,这两个伪类结合在一起的效果相当于 :only-child。

p:only-child {
  color: red;
}

p:first-child:last-child {
  background-color: red;
}

(6):fitst-of-type 与 :last-of-type 选择一个元素中某种元素的第一个或最后一个。

我们可以把这两个伪类连在一起,达到与 :only-of-type 的效果。

table:only-of-type {
  color: red;
}

table:first-of-type:last-of-type {
  background: red;
}

(7):nth-child() 伪类,我们可以在括号中填上整数,甚至是简单的代数式,选择任何想选择的子元素。

:nth-child(2n) 选择的是偶数位的子代,:nth-child(2n + 1) 或 :nth-child(2n - 1) 选择的是奇数位的子代。也可以使用两个特殊的关键字:even 和 odd。

还有一个与之对应的伪类 :nth-last-child()。

(8)选择每第 n 个某种元素

:nth-of-type() 和 :nth-last-of-type()。

动态伪类

动态伪类可应用于任何元素,也就是说可用于链接之外的元素。

(1)超链接伪类 => :link(未访问)和 :visited(已访问)。

(2)用户操作伪类

伪类 说明
:focus 指代当前获得输入焦点的元素,即可以接受键盘输入或以某种方式激活
:hover 指代鼠标指针放置其上的元素,例如鼠标指针悬停在超链接上
:active 指代由用户输入激活的元素,例如用户单击超链接时按下鼠标按键的那段时间

UI 状态伪类

伪类 说明
:enabled 指代启用的用户界面元素(例如表单元素),即接受输入的元素
:disabled 指代禁用的用户界面元素(例如表单元素),即不接受输入的元素
:checked 指代由用户或文档默认选中的单选按钮或复选框
:indeterminate 指代既未选中也没有未选中的单选按钮或复选框;这个状态只能由 DOM 脚本设定,不能由用户设定
:default 指代默认选中的单选按钮、复选框或选项
:valid 指代满足所有数据有效性语义的输入框
:invalid 指代不满足所有数据有效性语义的输入框
:in-range 指代输入的值在最小值和最大值之间的输入框
:out-of-range 指代输入的值小于控件允许的最小值或大于控件允许的最大值的输入框
:required 指代必须输入值的输入框
:optional 指代无需一定输入值的输入框
:read-write 指代可由用户编辑的输入框
:read-only 指代不能由用户编辑的输入框

:target 伪类

URL 片段标识符指向的目标元素可以使用 :target 伪类特别装饰。

URL 中的片段标识符由 # 符号标记。

:lang 伪类

如果想根据文本使用的语言选择元素,可以使用 :lang 伪类。

*:lang(fr) {
  font-style: italic;
}

否定伪类

Selectors Level 3 引入了否定伪类 :not()。

:not() 伪类依附在元素上,括号中是简单的选择符。

根据 W3C 的定义,简单的选择符指:一个类型选择符、通用选择符、属性选择符、类选择符、ID 选择符或伪类。基本上,简单选择符是指没有祖辈-后代关系的选择符。

/* 选择 li 标签但没有 .moreinfo 的 */
li:not(.moreinfo) {
  font-style: italic;
}
/* 选择有 .moreinfo 但不是 li 标签的 */
.moreinfo:not(li) {
  font-style: italic;
}

否定伪类不能嵌套,不过可以串在一起,作用相当于“也不是”。例如,想选择 class 为 link,但既不是列表项目也不是段落的元素。

*.link:not(li):not(p) {
  font-style: italic;
}

伪元素选择符

为了区分,伪类使用一个冒号,伪元素使用一对冒号(在 CSS2 中,这两种选择符都使用一个冒号)。

选择符中的最后一个元素是主词。

所有伪元素只能出现在选择符的最后。

一个选择符中只能有一个伪元素。

装饰首字母

::first-letter 伪元素用于装饰任何非行内元素的首字母,或者开头的标点符号和首字母(如果文本以标点符号开头)。

p::first-letter {
  color: red;
}

装饰首行

::first-line 用于装饰元素的首行文本。

p::first-line {
  font-size: 150%;
  color: purple;
}

对 ::first-letter 和 ::first-line 的限制

目前,::first-letter 和 ::first-line 伪元素只能应用到块级元素上,不能应用到行内元素上。

::first-line 和 ::first-letter 样式中可以使用的 CSS 属性也有限制。

装饰(或创建)前置和后置内容元素

::before 这个伪元素用于插入并装饰生成的内容。

若想把内容放在元素的后面,使用 ::after 伪元素。

/* 在 h2 元素前面插入内容 ]] */
h2::before {
  content: "]]";
  color: silver;
}
/* 在文档结尾加上结束语 */
body::after {
  content: "The End.";
}

小结

心里有光,哪儿都美。

盒尺寸四大家族

盒尺寸四大家族

这是学习《CSS 世界》第 4 章的笔记。

深入理解 content

根据“外在盒子”是内联还是块级我们可以把元素分为内联元素和块级元素,而根据是否具有可替换内容,我们也可以把元素分为替换元素和非替换元素。

替换元素,内容可以被替换。例如 <img>

<img> 和其他一些替换元素的替换内容的适配方式可以通过 object-fit 属性修改了。

<span> 标签设置 width 和 height 是无效的。

在 Chrome 浏览器下,所有的元素都支持 content 属性,而其他浏览器仅在 ::before/::after 伪元素中才有支持。

在 CSS 世界中,我们把 content 属性生成的对象称为“匿名替换元素“。

content 属性生成的内容和普通元素内容会有很多不同的特性表现:使用 content 生成的文本是无法选中、无法复制的,好像设置了 user-select: none 声明一般,但是普通元素的文本却可以被轻松选中,同时 content 生成的文本无法被屏幕阅读设备读取,也无法被搜索引擎抓取;不能左右 :empty 伪类等。

在实际项目中,content 属性几乎都是用在 ::before/::after 这两个伪元素中,因此,“content 内容生成技术”有时候也称为“::before/::after 伪元素技术”。

IE8 浏览器仅支持单冒号的伪元素。

温和的 padding 属性

一个错误的认知:内联元素的 padding 只会影响水平方向,不会影响垂直方向。

内联元素 padding 对视觉层和布局层具有双重影响,所有类似“垂直方向 padding 对内联元素没有作用”的说法显然是不正确的。

利用内联元素的 padding 实现高度可控的分隔线(链接):

<a href="">登录</a><a href="">注册</a>
a + a:before {
  content: "",
  font-size: 0;
  padding: 10px 3px 1px;
  margin-left: 6px;
  border-left: 1px solid gray;
}

网页可以通过地址栏的 hash 值和页面 HTML 中 id 值一样的元素发生锚点定位。

padding 属性是不支持负值的。

padding 支持百分比值,padding 百分比值无论是水平方向还是垂直方向均是相对于宽度计算的。

/* 实现一个正方形 */
div {
  padding: 50%;
}

/* 实现一个宽高比为 2:1 的矩形 */
div {
  padding: 25% 50%;
}

/* 实现一个宽高比为 5:1 的比例固定的头图效果 */
.box {
  position: relative;
  padding: 10% 50%;
}

.box > img {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}

CSS 实现“三道杠”图标效果:

<i class="icon-menu"></i>
.icon-menu {
  display: inline-block;
  width: 14px;
  height: 1px;
  padding: 3.5px 0;
  border-top: 1px solid;
  border-bottom: 1px solid;
  background-color: red;
  background-clip: content-box;
}

激进的 margin 属性

左侧定宽,右边自适应的两栏布局效果:

.box {
  overflow: hidden;
}

.box > img {
  float: left;
}

.box > p {
  margin-left: 140px;
}
<div class="box">
  <img src="1.jpg">
  <p>文字内容...</p>
</div>

利用 margin 外部尺寸实现等高布局(块状元素):

.column-box {
  overflow: hidden;
}

.column-left,
.column-right {
  margin-bottom: -9999px;
  padding-bottom: 9999px; // 可以使用 border-bottom: 9999px solid transparent 代替
}

内联元素垂直方向的 margin 是没有任何影响的,既不会影响外部尺寸,也不会影响内部尺寸。

和 padding 属性一样,margin 的百分比值无论是水平方向还是垂直方向都是相对于宽度计算的。

块级元素的上外边距与下外边距有时会合并为单个外边距,这样的现象称为“margin 合并”。

margin 合并的3种场景:

  • 相邻兄弟元素 margin 合并。
  • 父级和第一个/最后一个子元素。
  • 空块级元素的 margin 合并。

margin: auto 的填充规则如下:

  • 如果一侧定值,一侧 auto,则 auto 为剩余空间大小。
  • 如果两侧均是 auto,则平分剩余空间。

margin 默认值是 0。

如果想让某个块状元素右对齐,脑子里不要就一个 float: right,很多时候,margin-left: auto 才是最佳的实践,浮动毕竟是个“小魔鬼”。

绝对定位元素的 margin: auto 居中:

.father {
  position: relative;
  width: 300px;
  height: 150px;
}

.son {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 200px;
  height: 100px;
  margin: 0;
}

功勋卓越的 border 属性

CSS 世界中很多大受欢迎的属性之所以受欢迎,并不是因为其本职工作做得很好,而是衍生出来的特性可以用来解决很多棘手的问题。border 属性就是典型代表之一。

虽然同属于盒模型基本成员,但是 border-width 却不支持百分比。

我们平常使用 border-width 几乎全是固定的数值,如 border-width: 1px 之类,但是,可能有些人并不知道 border-width还支持若干关键字,包括 thin、medium(默认值) 和 thick,对应的尺寸大小具体如下:

  • thin:薄薄的,等同于 1px。
  • medium(默认值):薄厚均匀,等同于 3px。
  • thick:厚厚的,等同于 4px。

为什么 border 属性的默认宽度大小是 medium,也就是 3px,明明 thin(1px) 宽度更常用吧?为什么呢?因为 border-style: double 至少 3px 才有效果。

各种 border-style 类型:

  • border-style 的默认值是 none。
  • border-style: solid 实线边框。
  • border-style: dashed 虚线边框。
  • border-style: dotted 虚点边框。在 Chrome 以及 Firefox 浏览器下虚点实际上是个小方点,而 IE 浏览器下则是小圆点。
  • border-style: double 双线边框,顾名思义,即两根线且为实线。
  • 其他 border-style 类型:inset(内凹)、outset(外凸)、groove(沟槽)、ridge(山脊),兼容性不好,基本不使用。

border-color 默认颜色就是 color 色值,就是当没有指定 border-color 颜色值的时候,会使用当前元素的 color 计算值作为边框色。具有类似特性的 CSS 属性还有 outline、box-shadow 和 text-shadow 等。

上传图片带有加号的框框按钮 链接

使用透明 border 增加点击区域:

.icon-clear {
  width: 16px;
  height: 16px;
  border: 11px solid transparent;
}

使用 border 属性绘制三角形:

div {
  width: 0;
  border: 10px solid;
  border-color: #f30 transparent transparent;
}

border 等高布局技术 链接

小结

脚踏实地,仰望星空。

内边距、边框、轮廓和外边距

内边距、边框、轮廓和外边距

这是学习《CSS 权威指南》第 8 章的笔记。

基本元素框

文档中的每个元素都会生成一个矩形框,我们称之为元素框。

width 和 height 这两个属性无法应用到行内非置换元素上。

内边距

元素默认没有内边距。

如果为元素添加了边框,通常最好再加一些内边距。

padding: top right bottom left; 这个顺序不难记住:从上边开始,顺时针转动(上右下左)。

CSS 考虑到了少于四个值的情况,为此定义了几个规则:

  • 如果没有针对左边的值,使用针对右边的值。
  • 如果没有针对底边的值,使用针对顶边的值。
  • 如果没有针对右边的值,使用针对顶边的值。

元素的内边距可以用百分数值设定。百分数值相对父元素内容区的宽度计算(这一点不仅针对左右内边距,也针对上下内边距),因此,如果出于什么原因,父元素的宽度变了,内边距也会变。

div p {
  padding-top: 10%;
}
<div style="width: 500px;">
  <p>This is a paragraph.</p>
</div>

对上述代码来说,段落的上内边距为 50px。

百分数值可以与长度值混用,例如:

h2 {
  padding: 0.5em 10%;
}

边框

元素的内边距之外是边框。边框是元素的内容和内边距周围的一到多条线段。默认情况下,元素的背景在边框的外边界处终止,不会延伸到外边距区域。边框在外边距内侧。

边框有三个要素:宽度(厚度),式样(外观),颜色。

  • 宽度的默认值为 medium。
  • 默认的边框式样为 none,即不存在(所以一般见不到边框)。
  • 默认的边框颜色是元素自身的前景色。

边框的式样

式样是边框最重要的要素,因为倘若没有式样,根本看不到边框。

一个边框可以有多个式样。例如:

p.aside {
  border-style: solid dashed dotted solid;
}

这个属性与 padding 一样,值的顺序为上右下左。值少于四个时的复制规则也与 padding 属性一样。

单边式样:border-top-style ……如此。

边框宽度

使用 border-width 属性来设定边框宽度,类似的有 border-top-width 等属性设定各边的边框宽度。

边框颜色

使用 border-color 属性来设定边框颜色,类似的有 border-top-color 等属性设定各边的边框颜色。

有时会想创建有宽度但不可见的边框,要把边框的颜色设为 transparent。透明边框在某种程度上相当于内边距,不过透明边框有个额外好处,需要时可以让边框可见。

简写的边框属性

简写的边框属性:border-top, border-right, border-bottom, border-left。

h1 {
  border-bottom: thick solid rgb(50%, 40%, 70%);
}

整个边框

还有一个最简单的简写属性:border。

h1 {
  border: thick silver solid;
}

圆角边框

元素边框的角是直的,可以使用 border-radius 属性定义一个(或两个)圆角半径,把圆角变得圆滑一些。

#example {
  border-raidus: 2em;
}

#example {
  border-radius: 33%; /* 百分数相对边框框的尺寸计算 */
}

#example {
  border-radius: 1em 2em 3em 4em;
  /* 左上角 - 右上角 - 右下角 - 左下角 */
}

如果缺少某个值,填充的方式与 padding 等属性一样。

下面讨论提供两个值的情况,在两个值之间插入一个斜线:

#example {
  border-radius: 3ch / 1ch;
}
/* 等价于: */
#example {
  border-radius: 3ch 3ch 3ch 3ch / 1ch 1ch 1ch 1ch;
}

在这种句法中,斜线前是横轴的值,斜线后是纵轴的值。

单独的圆角属性,各属性设定对应各角的曲线形状,与之前不同的是,如果提供两个值,一个用作横向半径,另一个用作纵向半径,无需在两个值之间插入斜线:

  • border-top-left-radius
  • border-top-right-radius
  • border-bottom-right-radius
  • border-bottom-left-radius

单独的圆角属性最常用于修改某一角,例如先设定通用的圆角,然后覆盖其中一个:

.tabs {
  border-radius: 2em;
  border-bottom-left-radius: 0;
}

图像边框

使用图像绘制边框,要使用 border-image-source 属性。

p.hello {
  border: 25px solid;
  border-image-source: url(i/circle.png); 
}

注意,如果没有 border: 25px solid 声明,根本不会显示边框。因此,为了让边框图像显示出来,必须把 border-style 设为 none 以外的值,不一定非得是 solid。

其次,border-width 的值决定边框图像的宽度。如未声明这个值,默认为 medium,差不多是 3 像素(具体的值可能有所不同)。

裁剪边框图像,使用 border-image-slice 属性。

调整图像的宽度,使用 border-image-width 属性。

外推边框,使用 border-image-outset 属性。

使用 border-image-repeat 属性可以改变各边上边框图像的处理方式,取值有 stretch | repeat | round | space。

边框图像的简写属性:border-image。

这个属性的值排列方式很独特:必须按指定的顺序列出,先是裁剪,后跟宽度,最后是偏移(这几个值中间要加上斜线)。这三组词的顺序定好之后,图像来源和重复方式可以写在任何位置。

比如:source slice / width / outset repeat。

如果省略了某个部分,那一部分将使用默认值。

轮廓

CSS 定义了一种特殊的装饰方式,名为轮廓(outline)。

根据规范,轮廓与边框的区别体现在三个方面:

  1. 轮廓不占空间。
  2. 轮廓可以不是矩形。
  3. 用户代理通常在元素处于 :focus 状态时渲染轮廓。
    不过,还要加上一点:
  4. 轮廓更极端,无法单独为一边设置独特的轮廓。

轮廓式样:outline-style。

轮廓宽度:outline-width。

轮廓颜色:outline-color。

唯一的轮廓简写属性:outline。与 border 类似,这个属性能一次性设置轮廓的式样、宽度和颜色。

轮廓与边框之间的第一个重要区别是,轮廓对布局完全没有影响。任何影响都没有。轮廓只是视觉上的效果。

轮廓不一定是矩形的,也不一定是连续的。

外边距

常规流动模式下,元素之间有间隔的原因是元素有外边距(margin)。外边距在元素周围添加额外的空白。空白一般指其他元素不能共存的区域,而且在这片区域中,父元素的背景是可见的。

外边距的默认值是 0(零)。因此,如果未声明值,默认没有外边距。

不过,浏览器通常会为很多元素提供预设样式,这其中就包含外边距。例如,在启用 CSS 的浏览器中,通常会在段落上下添加一个“空行”。因此,如果没有为 p 元素设定外边距的话,浏览器会自行添加。只要声明了,默认的样式就会被覆盖。

不同类型的长度值还可以混用。一个规则中并不一定非要使用同一种长度值,例如:

h2 {
  margin: 14px 5em 0.1in 3ex; /* 不同类型的长度值 */
}

元素的外边距可以使用百分数值设定。与内边距一样,百分数外边距值相对父元素的内容区宽度计算,因此外边距的具体值将随父元素的宽度而变。

单边外边距属性:margin-top, margin-right, margin-bottom, margin-left。

块级框的上下外边距有个有趣的行为,而这个行为往往被人忽略:上下外边距会折叠。相邻的两个(或多个)上下外边距会折叠为其中最大的那个外边距。

段落之间的空白是最经典的例子。一般来说,段落之间的间隔使用类似下面的规则实现:

p {
  margin: 1em 0;
}

这个规则把每个段落的上下外边距都设为 1em。如果外边距不折叠,相邻的两个段落之间就会出现 2em 的间隔。而事实上,段落之间只有 1em 的间隔,因为两个外边距折叠了。

在父元素上设定内边距或边框等可以阻止外边距折叠。

元素的外边距可以设为负值。这可能会使元素框从父元素中冒出来,或者与其他元素重叠。

小结

图像边框不是那么好理解,概念有点抽象。除此,其他都是很好理解的。

动画

动画

这是学习《CSS 权威指南》第 18 章的笔记。

@keyframes 规则

使用 @keyframes 规则定义可复用的 CSS 关键帧动画,并为动画起个名称。然后,通过这个名称把对应的动画效果应用到元素或伪元素上。

一个 @keyframes 规则有一个动画标识符(即动画的名称),以及一个到多个关键帧块。每个关键帧块有一个到多个关键帧选择符,声明属性及其值。整个 @keyframes 规则设置一个动画效果的完整迭代过程。

关键帧选择符可以是以逗号分隔的一组百分数,也可以是关键字 from 或 to。关键字 from 等于 0%,to 等于 100%。

@keyframes fadeout {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

@keyframes color-pop {
  0% {
    color: black;
    background-color: white;
  }
  33% {
    color: gray;
    background-color: yellow;
  }
  100% {
    color: white;
    background-color: orange;
  }
}

把动画应用到元素上

定义好关键帧动画便可以把动画应用到元素和伪元素上。为了把动画附加到元素上,并控制动画的播放过程,CSS 提供了多个相关的属性。若想保证动画效果能显示出来,至少要指明动画的名称,以及持续时间(不然动画瞬间就结束了)。

animation-name 属性

animation-name 属性的值为一个逗号分隔的列表,指定想应用的关键帧动画的名称。这里所说的名称是指使用 @keyframes 规则定义动画时设定的无引号标识符或有引号的字符串。

animation-name 属性默认值为 none,表示没有动画效果。如果想应用动画,把值设为 @keyframes 的标识符,即动画的名称。

div {
  animation-name: fadeout;
}

这个规则把 fadeout 动画应用到所有 div 元素上。

如果想应用多个动画,以逗号分开多个 @keyframes 标识符。

div {
  animation-name: fadeout, color-pop;
}

如果指定的一系列关键帧标识符中有一个不存在,不会导致所有动画都无法应用,只是那个不存在的动画被忽略,其他有效的动画仍将应用。

animation-duration 属性

animation-duration 属性定义动画迭代一次用时多久,单位为秒(s)或毫秒(ms),初始值是 0s。

如果不声明 animation-duration,动画仍将播放,只不过持续时间为 0s,看不到实际效果,而且 animationstart 和 animationend 事件也会触发。这个属性的值不能为负数。

如果一组以逗号分隔的持续时间中有无效的值,整个声明都失效。

animation-iteration-count 属性

只声明必须的 animation-name 属性,动画将播放一次,而且只播放一次。如果希望迭代的次数不是默认的一次,使用 animation-iteration-count 属性设定。

animation-iteration-count 属性不允许设为负值,如果提供的值无效,将重置为默认值 1,只迭代一次。

有趣的是,0 是 animation-iteration-count 属性的有效值。设为 0 时,动画依然播放,只不过迭代零次。与 animation-duration: 0s; 类似,这也会触发 animationstart 和 animationend 事件。这个属性的值也可以不是整数。

animation-direction 属性

使用 animation-direction 属性可以控制动画是从 0% 关键帧向 100% 关键帧播放,还是从 100% 关键帧向 0% 关键帧播放。可以让所有迭代都按照相同的方向播放,也可以隔一个循环变换一次方向。

animation-direction 属性定义按什么方向播放动画的关键帧。可取的值有四个:

(1)animation-direction: normal;

设为 normal 时(或者省略,默认为 normal),动画的每次迭代都会从 0% 关键帧向 100% 关键帧播放。

(2)animation-direction: reverse;

reverse 值逆序播放各次迭代,即从 100% 关键帧向 0% 关键帧播放。逆转动画的方向也就逆转了 animation-timing-function。

(3)animation-direction: alternate;

alternate 值的意思是第一次迭代(以及后续各奇数次迭代)从 0% 向 100% 播放,第二次迭代(以及后续各偶数次迭代)方向相反,从 100% 向 0% 播放。

(4)animation-direction: alternate-reverse;

alternate-reverse 值与 alternate 值类似,只不过是反过来的。第一次迭代(以及后续各奇数次迭代)从 100% 向 0% 播放,第二次迭代(以及后续各偶数次迭代)方向相反,从 0% 向 100% 播放。

animation-delay 属性

animation-delay 属性设定把动画附加到元素上之后隔多久开始播放动画,单位为秒(s)或毫秒(ms),初始值是 0s。

如果设为负值,动画立即开始播放,不过是从动画的中途开始。

利用 animation-delay 属性把多个动画串在一起,让下一个动画在前一个动画结束后立即开始:

.rainbow {
  animation-name: red, orange, yellow, blue, green;
  animation-duration: 1s, 3s, 5s, 7s, 11s;
  animation-delay: 3s, 4s, 7s, 12s, 19s;
}

后续各动画都在前一个动画结束后开始。我们称这样的效果为 CSS 动画链。

animation-timing-function 属性

animation-timing-function 属性指明动画在一次循环(或迭代)中如何演进,初始值是 ease。

可以取的值有 ease、ease-in、ease-out、ease-in-out、linear 等。

animation-play-state 属性

使用 animation-play-state 属性定义动画是播放还是暂停的。

设为默认值 running 时,动画正常播放。设为 paused 时,动画暂停。

animation-fill-mode 属性

animation-fill-mode 属性定义动画播放结束后是否应用原来的属性值。

这个属性可以取的值有四个:none、forwards、backwards 和 both,初始值是 none。

animation 简写属性

使用 animation 简写属性,无需分别定义 8 个属性,在一行声明中就能为元素定义全部动画属性。

初始值是 0s ease 0s 1 normal none running none。

在 animation 简写属性中,无需声明所有值;未声明的值将被设为默认值(初始值)。

各单独属性的初始值(默认值)如下:

#animation {
  animation-name: none;
  animation-duration: 0s;
  animation-timing-function: ease;
  animation-delay: 0s;
  animation-iteration-count: 1;
  animation-fill-mode: none;
  animation-direction: normal;
  animation-play-state: running;
}

简写属性中有些值的顺序是重要的。其一,有两个时间相关的属性,如果列出两个时间值,第一个始终为持续时间,第二个是延迟时间。其二,建议把 animation-name 属性的值放在最后。

其他

与动画有关的三个事件:animationstart、animationend 和 animationiteration。

2017 年年末,浏览器新增了一个媒体查询:prefers-reduced-motion。创作人员可以通过这个媒体查询为浏览器或其他设备中设置了“减少运动效果”或类似偏好设置的用户定义样式。强烈建议像下面这样做:

@media (prefers-reduced-motion) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

这个规则禁用全部动画和过渡。反过来,我们可以把所有动画和过渡单独放在一处,针对没有启用“减少运动效果”的用户:

@media not (prefers-reduced-motion) {
  /* 所有动画和过渡 */
}

小结

心里有光,哪儿都美。

视觉格式化基础

视觉格式化基础

这是学习《CSS 权威指南》第 7 章的笔记。

元素框基础

不管是什么元素,CSS 都假定每个元素都生成一个或多个矩形框,我们称之为元素框。

各元素框的中心是内容区域,四周有可选的内边距、边框、轮廓和外边距。之所以说这些区域是可选的,是因为它们的宽度都可以设为零,即把它们从元素框上删除。

内边距不能为负值,但是外边距可以。

重要概念概览:

  • 常规流动:即渲染西方语言时从左至右、从上到下的顺序,以及传统的 HTML 文档采用的文本布局方式。
  • 非置换元素:内容包含在文档中的元素。
  • 置换元素:为其他内容占位的元素。
  • 块级框:段落、标题或 div 等元素生成的框。在常规流动模式下,块级框在框体前后都“换行”,因此块级框式纵向堆叠的。display: block 声明能把任何元素生成的框体变成块级框。
  • 行内框:strong 或 span 等元素生成的框体。行内框前后不“换行”。display: inline 声明能把任何元素生成的框体变成行内框。
  • 行内块级框:内部特征像块级框,外部特征像行内框。行内块级框的行为与置换元素相似,但不完全相同。
  • 容纳块:在使用常规流动方式渲染的西文文本中,容纳块由离元素最近的那个生成列表项目或块级框的祖辈元素的边界构成。
<body>
  <div>
    <p>This is a paragraph.</p>
  </div>
</body>

在这里,p 元素的块级框的容纳块是 div 元素的块级框,div 元素的容纳块是 body 元素的框体。html 元素对应的是初始容纳块。

调整元素的显示方式

改变的是元素的显示方式,而不是元素的本性。也就是说,把段落生成的框体变成行内框并不会把段落变成行内元素。

display 属性的名称就表明,它是影响元素显示方式的,而不能改变元素的种类。

默认情况下,块级框的宽度(width)等于左内边界到右边界的距离,高度(height)等于上内边界到下内边界的距离。

box-sizing 属性的取值有 content-box | padding-box | border-box。

  • 初始值 content-box。
  • 适用于能设定 width 或 height 的所有元素。

这个属性用于改变 width 和 height 值的具体意义。如果声明 width: 400px,而且不为 box-sizing 设值,那么元素的内容框将为 400 像素宽,内边距和边框等都在此基础上增加。如果声明 box-sizing: border-box,那么元素框从左边框的外边界到右边框的外边界相距 400 像素,边框或内边距都在这个尺寸之内计算,即内容区的宽度相应减少。

横向格式化属性有七个,分别为 margin-left、border-left、padding-left、width、padding-right、border-right 和 margin-right。这七个属性的值加在一起要等于元素容纳块的宽度,而这一宽度通常为块级元素的父元素的 width 值。

在这七个属性中,只有三个属性的值能设为 auto:元素内容区宽度、左外边距和右外边距。余下的几个属性,要么设为具体的值,要么使用默认值(零)。

在 width、margin-left 和 margin-right 三个属性中,如果把其中一个设为 auto,另两个设为具体的值,那么设为 auto 的那个属性的具体长度要能满足元素框的宽度等于父元素的宽度。从某种意义上说,auto 可用于补全总和所缺的尺寸。

如果把这三个属性都设为 auto 之外的值,用 CSS 术语来说就是过于约束了,那么 margin-right 将被强制设为 auto。

多个 auto:

  • 如果两侧的外边距都设为 auto,那么外边距的长度相等,元素在父元素内居中显示。
  • 如果把某一边的外边距和 width 设为 auto。此时,设为 auto 的那个外边距等于零。
  • 如果这三个属性都设为 auto,两侧的外边距被设为零,而 width 则要多宽有多宽。这跟默认情况是一样的,即两侧的外边距和宽度都不明确声明值;此时,外边距默认为零,而 width 默认为 auto。

纵向格式化属性有七个:margin-top、border-top、padding-top、height、padding-bottom、border-bottom 和 margin-bottom。

在常规流动模式下,如果把块级框的高度设为百分数,百分数是相对框体的容纳块的高度而言的。例如,对下述标记来说,段落的高度将是 3em:

<div style="height: 6em;">
  <p style="height: 50%;">Half as tall</p>
</div>

纵向格式化的另一个重要特征是,相邻的纵向外边距会折叠。较小的外边距被较大的外边距消去了。

行内元素

匿名文本:不在任何行内元素中的字符串。

行距 = line-height - font-size。

小结

块级元素相对容易理解一些,不用费什么力气就能控制它们的布局。而行内元素有时却让人捉摸不透,因为要考虑的因素太多,不是区分置换元素和非置换元素就能解决的。

遇到问题时再解决,不要杞人忧天。

字体

字体

这是学习《CSS 权威指南》第 5 章的笔记。

字体族

为了覆盖所有情况,CSS 定义了五种通用字体族:

  • 衬线字体(serif)
  • 无衬线字体(sans-serif)
  • 等宽字体(monospace)
  • 草书字体(cursive)
  • 奇幻字体

字体族使用 font-family 属性声明。

使用 @font-face

@font-face 的作用是让你在设计中使用自定义的字体。

@font-face 是惰性加载字型的。

定义字体的全部参数都在 @font-face { } 结构中编写。这些参数称为描述符,与属性十分相似,格式为 descriptor: value;

描述符中有两个是必需的:font-family 和 src。

@font-face {
  font-family: "SwitzeraADF";
  src: url("SwitzeraADF-Regular.otf");
}

h1 {
  font-family: SwitzeraADF, Helvetica, sans-serif;
}

src 描述符中以逗号分隔的列表用于提供后背字体文件。

@font-face {
  font-family: "SwitzeraADF";
  src: url("SwitzeraADF-Regular.otf"),
       url("/fonts/SwitzeraADF-Regular.otf");
}

如果想告诉用户代理所用的字体是什么格式,可以使用可选的 format():

@font-face {
  font-family: "SwitzeraADF";
  src: url("SwitzeraADF-Regular.otf") format("opentype");
}

这么做的好处是,让用户代理跳过不支持的字体格式,从而减少带宽用量,提升加载速度。

可用的格式值见表。

格式
embedded-opentype EOT(Embedded OpenType)
opentype OTF(OpenType)
svg SVG(Scalable Vector Graphics)
truetype TTF(TrueType)
woff WOFF(Web Open Font Format)

除了使用 url() 和 format() 组合之外,还可以使用 local() 指定已经安装在用户设备中的字体族名称(可以是多个)。

@font-face {
  font-family: "SwitzeraADF";
  src: local("Switzera-Regular"),
       local("SwitzeraADF-Regular"),
       url("SwitzeraADF-Regular.otf") format("opentype"),
       url("SwitzeraADF-Regular.true") format("truetype");
}

借助这个功能可以为本地安装的字体自定义名称。

@font-face {
  font-family: "H";
  src: local("Helvetica"), local("Helvetica Neue");
}

h1, h2, h3 {
  font-family: H, sans-serif;
}

字体描述符

描述符 默认值 说明
font-style normal 区分常规、斜体和倾斜字型
font-weight normal 区分不同的字重(例如加粗)
font-stretch normal 区分不同的字符宽度(例如紧缩和加宽)
font-variant normal 区分众多字形变体(例如小号大写字母),在很多方面与 CSS 中的 font-feature-settings 很像
font-feature-settings normal 直接访问 OpenType 的低层特性(例如启用连字)
unicode-range U+0-10FFFF 定义指定字体中可用的字符范围

字重

CSS 中的 font-weight 属性可以精确控制字重。

font-weight 取值有 normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900。

增大字重:如果把一个元素的字重设为 bolder,用户代理首先要确定从父元素继承的 font-weight 值什么,然后选择比继承的字重高一级的最小数字。

减小字重:lighter 的工作方式类似,只不过是让用户代理向下减小字重。

使用 font-weight 描述符可以为字型指定 font-weight 属性支持的字重等级。

@font-face {
  font-family: "SwitzeraADF";
  font-weight: normal;
  src: url("f/SwitzeraADF-Regular.otf") format("opentype");
}

@font-face {
  font-family: "SwitzeraADF";
  font-weight: 300;
  src: url("f/SwitzeraADF-Light.otf") format("opentype");
}

h1, h4 {
  font: 225% SwitzeraADF, Helvetica, sans-serif;
}

h4 {
  font-size: 125%;
  font-weight: 300;
}

字号

字号 font-size 的取值有 xx-small | x-small | small | medium | large | x-large | xx-large | smaller | larger | <length> | <percentage>

font-size 支持的绝对大小值有七个:xx-small、x-small、small、medium、large、x-large 和 xx-large。这几个关键字没有固定的大小,而是相对而言的。

百分数始终根据继承自父元素的字号计算。

CSS 还把长度单位 em 定义为等效于百分数,对字号而言,1em 与 100% 的效果相同。

字号关键字和继承会导致实际大小缩水,这在某些浏览器渲染等宽文本时尤为明显。有个方法能绕开这个问题,而且对已知的浏览器都有效,具体方法如下:

p {
  font-size: medium; /* 默认值 */
  span {
    font-family: monospace, serif;
    font-size: 1em;
  }
}

其实这里就是在 font-family 中多加了个 serif。

有两个因素影响字体是否清晰易辨:字号和 x 高度。x 高度除以字号得到的结果称为高度比值。随着字号的减小,高度比值越高,字体越清晰易辨;相反,高度比值较低的字体,很容易变得模糊难辨。CSS 提供的 font-size-adjust 属性用于改变字体族之间的高度比值。

font-size-adjust 的取值有 <number> | none | auto。

默认值是 none,声明将禁止调整字号。

字形

font-style 属性的作用十分简单:在 normal(常规)、italic(斜体)和 oblique(倾斜体)之间做出选择。

字体拉伸

font-stretch 属性的取值有 normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded。

仅当使用的字体族中有宽体和窄体时,这个属性才起作用。

仅当使用的字体族中有加宽变体时,font-stretch: expanded 声明才起作用;如果没有加宽变体,什么也不会发生,即仍使用原来的字型。

截至 2017 年年末,macOS 和 iOS 中的 Safari 都不支持 font-stretch,Opera Mini 也不支持。

字距调整

有些字体定义了字符之间相对位置的数据,即字距。

字距可以使用 font-kerning 属性呼出或禁止。

font-kerning 的取值有 auto | normal | none。

none 的意思十分简单:让用户代理忽略字体中的字距信息。 normal 的意思是让用户代理正常处理字距,即是用字体中的字距数据。auto 则把决定权交给用户代理,让用户代理选择最合理的处理方式,当然具体怎么做由所用的字体决定。

字体变形

font-variant 描述符在 @font-face 规则中指明允许使用的变形能轻易覆盖属性中指定的字体变形。

字体特性

font-feature-settings 属性从低层控制 OpenType 字体的哪些特性可以使用(因此,不能用在 .woff 文件上)。

font-variant 描述符几乎涵盖 font-feature-settings 的一切功能,外加一些其他作用。CSS 规范明确建议创作人员使用 font-variant,只在想要的字体特性不在 font-variant 的取值范围内时才使用 font-feature-settings。

字体合成

font-synthesis 属性,取值有 none | weight || style。

初始值 weight style。

截至 2017 年年末,只有 Firefox 支持 font-synthesis 属性。

font 属性

font 属性必须的两个值是 font-size 和 font-family,而且必须以这样的顺序编写,其他值都是可选的。

font 属性还能设定 line-height 属性的值,尽管 line-height 是文本属性,而不是字体属性。设定的方法算是在 font-size 中增加一个值,以正斜线(/)分隔:

body {
  font-size: 12px;
}

h2 {
  font: bold italic 200%/1.2 Verdana, Helvetica, Arial, sans-serif;
}

小结

加油。

CSS 世界的层叠规则

CSS 世界的层叠规则

这是学习《CSS 世界》第 7 章的笔记。

在 CSS 世界中,z-index 属性只有和定位元素(position 不为 static 的元素)在一起的时候才有作用,可以是正数也可以是负数。

在 CSS3 中,z-index 已经并非只对定位元素有效,flex 盒子的子元素也可以设置 z-index 属性。

网页中绝大部分元素是非定位元素,并且影响层叠顺序的属性远不止 z-index 一个,因此大家千万不要以为 z-index 属性就可以代表 CSS 世界的层叠规则。

不要把层叠水平和 CSS 中的 z-index 属性混为一谈。尽管某些情况下 z-index 确实可以影响层叠水平,但是只限于定位元素以及 flex 盒子的子元素;而层叠水平所有的元素都存在。

对于非浮层元素,避免设置 z-index 值,z-index 值没有任何道理需要超过 2。

如果 DOM 元素顺序确实无法调整,不得不使用 z-index 值,请记住,z-index 不要超过2,不是不能,而是没有必要。如果你的定位发现必须 z-index: 3 或者以上才能满足效果,建议你检查自己的代码。

很重要的一点,以上说到的不超过 2 的准则,并不包括那些在页面上飘来飘去的元素定位,弹框、出错提示、一些下拉效果等都不受这一准则限制。

浮层元素使用 z-index“层级计数器”,一般设为 9。

小结

学一点是一点,不要追求完美。

列表和生成的内容

列表和生成的内容

这是学习《CSS 权威指南》第 15 章的笔记。

列表

调整列表样式最简单的(也是支持最广泛的)方式是改变记号类型。

list-style-type 属性

若想改变列表项目所用的记号类型,使用 list-style-type 属性。

这个属性的初始值是 disc,适用于 display 属性的值为 list-item 的元素,继承性:是。

列表样式类型示例

如果不想显示记号,应该使用的值是 none。none 的作用是禁止在本该显示记号的位置上出现任何内容,不过却不阻断有序列表的计数。

ol li {
  list-style-type: decimal;
}

li.off {
  list-style-type: none;
}
<ol>
  <li>Item the first</li>
  <li class="off">Item the second</li>
  <li>Item the third</li>
  <li class="off">Item the fourth</li>
  <li>Item the fifth</li>
</ol>

上面代码的效果演示

list-style-type 的值是继承的,因此如果希望嵌套的列表使用不同的记号,要分别定义。

CSS 还允许指定字符串值为列表的记号。这样,只要能从键盘上打出来的字符都能用作记号。例如:

.list01 {
  list-style-type: "%";
  list-style-type: "Hi! ";
}

目前只有 Firefox 族浏览器支持字符串记号。

list-style-image 属性

若想使用图像设定记号,可以使用 list-style-image 属性实现。

这个属性的初始值是 none,适用于 display 属性的值为 list-item 的元素,继承性:是。

ul li {
  list-style-image: url("ohio.gif");
}

一般来说,最好提供一个后备记号类型,以防图像无法加载。具体方法是,为列表再声明一个 list-style-type 属性。

ul li {
  list-style-image: url("ohio.png");
  list-style-type: square;
}

使用 list-style-image 时还可以把值设为默认的 none。这是个好习惯,因为 list-style-image 是继承的,因此嵌套列表也将使用指定的图像作为记号,除非明确设定不这么做:

ul {
  list-style-image: url("ohio.gif");
  list-style-type: square;
}

ul ul {
  list-style-image: none;
}

list-style-image 的值可以是任何图像值,包括渐变图像(不过很少浏览器支持使用渐变图像值作为列表记号)。

list-style-position 属性

使用 CSS 还可以影响列表项目的一个外观:在列表项目内容的外部还是内部显示记号。记号的位置使用 list-style-position 属性设定。

这个属性的可选值有三个,包括:inside、outside 和 inherit,初始值是 outside。这个属性适用于 display 属性的值为 list-item 的元素,继承性:是。

li.first {
  list-style-position: inside;
}

li.second {
  list-style-position: outside;
}

list-style 属性

list-style 属性是 list-style-type、list-style-image 和 list-style-position 三个属性的合并简写形式。

list-style 的值可以按任何顺序列出,而且任何一个值都可以省略。只要有一个值,其余的值都将使用默认值。

li.norm {
  list-style: url("img42.gif");
  list-style: url("imag42.gif") disc outside; /* 作用相同 */
}

生成的内容

插入生成的内容

生成的内容使用 ::before 和 ::after 伪元素插入文档。这两个伪元素把 content 属性指定的内容插入元素的内容之前或之后。

生成的内容与元素的内容之间没有空格。

生成的内容位于元素框的内部。从 CSS 2.1 开始,除了列表记号,无法把生成的内容放在元素框的外部。

CSS2 和 CSS 2.1 明确禁止浮动或定位 ::before 和 ::after。此外,还有下述限制:

(1)如果 ::before 或 ::after 选择符的目标是块级元素,那么 display 属性的值只能为 none、inline、block 或 marker。其他值都当作 block。

(2)如果 ::before 或 ::after 选择符的目标是行内元素,那么 display 属性的值只能为 none 或 inline。其他值都当作 inline。

生成的内容比较特别的一点是,它会从依附的元素上继承属性值。

当然,只有能被继承的属性才会继承。

h1 {
  border-top: 3px solid black;
  padding-top: 0.25em;
}

h1::before {
  content: "New Section";
  display: block;
  color: gray;
  border-bottom: 1px dotted black;
  margin-bottom: 0.5em;
}

由于生成的内容放在 h1 的元素框内部,因此生成的文本将出现在元素的上边框下方。此外,生成的文本也在内边距内测,如图所示。元素的内容将向下移动 0.5em,因为给生成的内容(设为了块级)设定了下外边距。

指定内容

生成的内容使用 content 属性指定,这个属性适用于 ::before 和 ::after 伪元素。

(1)字符串显示为字面量,即使其中包含某种标记也是如此。因此,下述规则将把字符串原封不动地插入文档:如图所示

h2::before {
  content: "<em>&para;</em> ";
  color: gray;
}

这意味着,如果想在生成的内容中换行,不能使用 <br>。正确的做法是使用字符串 \A,这是 CSS 表示换行符的方式。相反,如果一个较长的字符串值分为多行编写,要使用 \ 字符转义换行符。

(2)插入属性值

任何属性的值都可以作为生成的内容插入文档。

a[href]::after {
  content: " [" attr(href) "]";
}

(3)生成引号

引号是一种特殊形式的生成的内容。引号使用 quotes 属性和 open-quote 等值生成。

quotes 属性除了关键字 none 和 inherit 之外,唯一有效的值是一对或多对字符串。字符串对中的第一个字符串定义开始引号,第二个字符串定义结束引号。

open-quote 和 close-quote 两个值的作用是在恰当的位置插入正确的引号。插入的引号来自 quotes 属性的值。

<quotation>
  <quote>I hate quotations.</quote>
  <quotee>Ralph Waldo Emerson</quotee>
</quotation>
quotation {
  display: block;
}

quote {
  quotes: '"' '"';
}

quote::before {
  content: open-quote;
}

quote::after {
  content: close-quote;
}

quotee::before {
  content: " (";
}

quotee::after {
  contnet: ")";
}

上面代码的效果演示

此外,还有 no-close-quote 和 no-open-quote 两个关键字。

(4)计数器

创建计数器的基本过程就是先设置计数器的起点,然后增加一定的量。前者使用 counter-reset 属性设置,后者使用 counter-increment 属性设置。

通过重置创建 chapter 计数器:

h1 {
  counter-reset: chapter;
}

默认情况下,计数器重置为零。如果想重置为其他数,在标识符后声明:

h1#ch4 {
  counter-reset: Chapter 4;
}

使用多个标识符和整数对还可以一次性重置多个标识符。如果缺少整数,默认为零:

h1 {
  counter-reset: Chapter 4 section -1 subsec figure 1;
}

使用 counter-increment 属性指明通过哪个元素递增计数器。

与 counter-reset 一样,counter-increment 的值为标识符和整数对,而且整数部分可以是 0、负数或正数。两个属性的不同之处是,在 counter-increment 中省略的整数部分默认为 1,而不是 0。

ol {
  counter-reset: ordered; /* 默认为 0 */
  counter-increment: ordered; /* 默认为 1 */
}

为了真正显示计数器,需要使用 content 属性及与计数器有关的值。

list[type="ordered"] {
  counter-reset: ordered; /* 默认为 0 */
}

list[type="ordered"] item {
  display: block;
}

list[type="ordered"] item::before {
  counter-increment: ordered;
  content: counter(ordered) ". ";
  margin: 0.25em 0;
}

计数器在元素上重置。

增量可以在元素上设置,也可以在伪元素上设置。

在 counter() 中还可以为每个计数器定义不同的格式。方法是,在计数器的标识符后面添加一个 list-style-type 关键字,之间以逗号隔开。

注意,display 属性的值为 none 的元素不递增计数器。相比之下,visibility 属性的值为 hidden 的元素依然递增计数器。

嵌套计数器:counters()。

跳过了 @counter-style 相关内容的学习,因为浏览器对此欠缺支持。

小结

加油!

强大的文本处理能力

强大的文本处理能力

这是学习《CSS 世界》第 8 章的笔记。

line-height 的另一个朋友 font-size

在 CSS 中,1em 的计算值等同于当前元素所在的 font-size 计算值,可以将其想象成当前元素中(如果有)汉字的高度。

rem,即 root em,顾名思义,就是根元素 em 大小。em 相对于当前元素,rem 相对于根元素。

font-size 支持长度值,也支持百分比值,还支持关键字属性值(仅考虑使用 medium)。

字体属性家族的大家长 font-family

font-family 支持两类属性值,一类是“字体名”,一类是“字体族”。

”字体名”很好理解,就是使用的对应字体的名称。“字体族”分为很多类,包括衬线字体、无衬线字体和等宽字体等(其他不常用)。

小结

你不必事事做得完美。

特指度和层叠

特指度和层叠

这是学习《CSS 权威指南》第 3 章的笔记。

继承(inheritance)是指把一个元素的某些属性值传给其后代的机制。确定应该把哪些值应用到元素上时,用户代理不仅要考虑继承,还要考虑声明的特指度(specificity),以及声明的来源。这个过程称为层叠。

不管怎样,无论问题看上去多抽象、多难懂,都要不断努力!努力终有回报。

特指度

选择符的特指度由选择符本身的组成部分决定。一个特指度值由四部分构成,例如 0,0,0,0。选择符的特指度通过下述规则确定:

  • 选择符中的每个 ID 属性值加 0,1,0,0。
  • 选择符中的每个类属性值、属性选择或伪类加 0,0,1,0。
  • 选择符中的每个元素和伪元素加 0,0,0,1。
  • 连结符和通用选择符不增加特指度。

特指度值是从左向右比较的。特指度 1,0,0,0 比所有以 0 开头的特指度都大,不管后面的数有多大。

行内声明的特指度为 1,0,0,0。

有时某个声明可能非常重要,超过其他所有声明。CSS 称之为重要声明(important declaration)。这种重要声明末尾的分号之前插入 !important。

p.dark {
  color: #333 !important;
  background: white;
}

如果想把两个声明都标记为重要的,每个声明中都要插入 !important。

p.dark {
  color: #333 !important;
  background: white !important;
}

带有 !important 的声明对特指度没有影响,但是会与不重要的声明分开处理。

继承

继承指某些样式不仅应用到所指的元素上,还应用到元素的后代上。

继承的值没有特指度,连零都没有。

零特指度战胜无特指度。

层叠

先按权重和来源排序,再按特指度排序,最后是按前后位置排序。

正是因为前后位置有影响,所以通常才推荐按照一定的顺序编写链接的样式。链接样式的推荐顺序是“link-visited-focus-hover-active”(LVFHA),如下所示:

a:link {color: blue;}
a:visited {color: purple;}
a:focus {color: green;}
a:hover {color: red;}
a:active {color: orange;}

小结

本章内容简单易懂。

CSS 中的表格布局

CSS 中的表格布局

这是学习《CSS 权威指南》第 14 章的笔记。

表格格式化

设定显示方式的值

简要说明与表格有关的 display 值:

(1)table 把元素定义为块级表格。即,定义一个生成块级框的矩形框。显然,对应的 HTML 元素是 table。

(2)inline-table 把元素定义为行内表格。即,定义一个生成行内框的矩形框。在与表格无关的值中,与之最接近的是 inline-block。最接近的 HTML 元素是 table,然而 HTML 中的表格默认不是行内元素。

(3)table-row 把元素定义为单元格构成的行。对应的 HTML 元素是 tr。

(4)table-row-group 把元素定义为由一行或多行构成的行组。对应的 HTML 元素是 tbody。

(5)table-header-group 与 table-row-group 十分相似,不过在视觉上,表头行组始终显示在其他行和行组前面,并且显示在上表题后面。表头行组可以包含多行。对应的 HTML 元素是 thead。

(6)table-footer-group 与 table-header-group 十分相似,不过表脚行组始终显示在其他行和行组后面,并且显示在下表题前面。对应的 HTML 元素是 tfoot。

(7)table-column 把元素声明为由单元格构成的列。在 CSS 中,把元素的 display 属性设为这个值没有任何视觉效果,好似设为 none 一样。这个值的作用基本上是定义列中单元格的表现。对应的 HTML 元素是 col。

(8)table-column-group 把元素声明为由一列或多列构成的列组。与 table-column 元素一样,table-column-group 元素也不渲染,而是用于定义列组中元素的表现。对应的 HTML 元素是 colgroup。

(9)table-cell 把元素定义为表格中的一个单元格。HTML 中的 th 和 td 都是应用 table-cell 的元素。

(10)table-caption 定义表题。

匿名表格对象:CSS 定义了一种插入机制,以匿名对象的形式插入“缺少的”表格组件。

caption-side 属性

使用 caption-side 属性,可以把表题放在表格上方或下方,而不管表题在表格的结构中位于何处(在 HTML5 中,caption 元素只能作为 table 元素的第一个子元素)。

caption-side 属性可以取的值有两个:top 和 bottom,初始值是 top,适用于 display 属性的值为 table-caption 的元素。

CSS 规范指出,表题就像一个放在表格框之前(或之后)的块级框一样,只是,表题还从表格继承样式。可见表格元素是表题的容纳块。

单元格的边框

在 CSS 中有两种完全不同的边框模型。分离边框模型(separated border model)在单元格的布局之间有间隔时起作用。另一个选项是折叠边框模型(collapsed border model),此时单元格之间在视觉上没有间隔,单元格之间的边框将合并或折叠在一起。

border-collapse 属性

我们可以使用 border-collapse 属性定义为分离边框模型或折叠边框模型。

这个属性的可选值包括三个,分别是:collapse、separate 和 inherit。初始值是 separate,适用于 display 属性的值为 table 或 table-inline 的元素。

border-spacing 属性

把单元格的边框区分开以后,还可以使用 border-spacing 属性让边框相隔一定的距离。

border-spacing 属性的初始值是 0,适用于 display 属性的值为 table 或 table-inline 的元素。如果 border-collapse 属性的值不是 separate,会忽略 border-spacing 属性。

这个属性的值可以是一个或两个长度。如果提供两个值,第一个值始终是横向间隔,第二个值始终是纵向间隔。

empty-cells 属性

empty-cells 属性用来处理空的单元格,可以取的值有 show 和 hide,初始值是 show。这个属性适用于 display 属性的值为 table-cell 的元素。如果 border-collapse 属性的值不是 separate,会忽略 empty-cells 属性。

边框折叠

border-collapse 属性的值为 collapse 时,相邻的两条或两条以上的边框会根据一定的规则选择显示某一边的边框。

表格的尺寸

表格的宽度有两种确定方式:固定宽度布局和自动宽度布局。不管使用哪种方式确定宽度,表格的高度都自动计算。

table-layout 属性

我们可以使用 table-layout 属性在以上两种宽度计算方式中做出选择。

table-layout 属性的可选值有两个,分别是 auto 和 fixed,初始值是 auto。这个属性适用于 display 属性的值为 table 或
inline-table 的元素。

使用 table-layout: auto;table-layout: fixed; 时,二者之间最显著的区别还是速度。用户代理计算表格的布局时,固定宽度的表格布局要比自动宽度模型快一些。

对齐方式

若想横向对齐单元格中的内容,使用 text-align 属性。

单元格中内容的纵向对齐方式使用 vertical-align 属性设定。

小结

加油。

变形

变形

这是学习《CSS 权威指南》第 16 章的笔记。

坐标系

2D(二维)变形只需关注 x 轴和 y 轴。按约定,x 轴上的正值在右侧,负值在左侧。y 轴上的正值沿纵轴向下,负值沿纵轴向上。

如果想在三维空间中改变元素的形态,要加上 z 轴的值。

transform 属性

transform 属性的初始值是 none,适用于除“基元行内”框之外的所有元素。百分数相对范围框计算。

受 CSS 控制的元素,其范围框是边框框,即元素边框的外边界。也就是说,计算范围框时,轮廓和外边距不算在内。

经过缩放的元素可能比变形前小或大,不过元素在页面上所占的空间与变形前保持不变。这一点对所有的变形函数都成立。

#example {
  transform: rotate(30deg) skewX(-25deg) scaleY(2);
}

变形通常不叠加。如果改变了元素的形态,而后想再添加一种变形,那么要在原变形的基础上修改。不过动画变形例外,不管使用过渡还是真正的动画,效果是叠加的。

有趣的是,即使不显式使用过渡或动画,也能通过用户交互伪类(例如 :hover)实现叠加的变形。这是因为悬停等效果就是一种过渡,只不过不是由过渡属性触发的。因此,可以像下面这样声明:

img#one {
  transform: translateX(100px) scale(1.2);
}

img#one:hover {
  transform: rotate(-45deg);
}

变形不能应用到基元行内框上。基元行内框指 span、超链接等行内框。

变形函数

一共有 21 个变形函数:

平移函数 缩放函数 旋转函数 倾斜函数 其他函数
transalte() scale() rotate() skew() matrix()
translate3d() scale3d() rotate3d() skewX() matrix3d()
translateX() scaleX() rotateX() skewY() perspective()
translateY() scaleY() rotateY()
translateZ() scaleZ() rotateZ()
二维平移 缩放元素 绕轴旋转 倾斜元素

transform 属性的值通常是由空格分隔的一个或多个函数,各函数从头(左)至尾(右)依次处理,而且每个函数的值都必须是有效的。倘若有一个函数的值是无效的,那么 transform 属性的整个值都将失效,因而也就不做任何变形。

平移函数

平移变形指沿一个轴或多个轴移动。translateX() 沿元素自身的 x 轴移动元素,translateY() 沿元素自身的 y 轴移动元素,translateZ() 沿元素自身的 z 轴移动元素。

translateX() 和 translateY() 两个函数的值都是一个距离值,可以是长度,也可以是百分数。值为百分数时,移动距离相对元素自身的尺寸计算。

translateZ() 这个函数沿 z 轴平移元素,即在第三个维度中移动元素。与 2D 平移函数不同,translateZ() 只接受长度值。translateZ() 不允许使用百分数值,其实任何有关 z 轴的值都不可以使用百分数。

如果想同时沿 x 轴和 y 轴移动,使用 translate() 更方便。第一个值是沿 x 轴的移动量,第二个值是沿 y 轴的移动量。如果省略 y 值,假定为零。因此,translate(2em) 视作 translate(2em, 0),也等同于 translateX(2em)。

translate3d() 这个简写属性能同时设定 x 轴、y 轴和 z 轴的平移量。与 translate() 不同,如果 translate3d() 的值少于三个,没有假定的默认值。因此,用户代理应该把 translate3d(1em, -50px) 视作无效的,而不能假定为 translate3d(1em, -50px, 0)。

缩放函数

缩放变形把元素放大或缩小,具体取决于提供的值。缩放函数的值都是无单位的实数,而且始终为正数。在 2D 平面内,可以分别在 x 轴和 y 轴上缩放,也可以同时在两个轴上缩放。

提供给缩放函数的数字是个乘数,因此,scaleX(2) 将把元素的宽度变为变形前的两倍,而 scaleY(0.5) 将把元素的高度缩小一半。

如果想在两个轴上同时缩放,使用 scale()。第一个值始终是 x 值,第二个则是 y 值。如果只提供一个值,用作两个轴的缩放值。

scaleZ() 函数仅在 z 轴上缩放,而 scale3d() 则能同时在三个轴上缩放。当然,仅当元素有深度时,这两个函数才有效果,而元素在默认情况并没有深度。

旋转函数

旋转函数绕某个轴旋转元素,或者绕 3D 空间中的一个向量旋转元素。旋转变形有四个简单的函数,以及一个稍微复杂、专门用于 3D 旋转的函数。

rotate()、rotateX()、rotateY() 和 rotateZ() 四个简单的旋转函数都只接受一个值,即角度。角度值以一个数字(可正可负)和一个有效的角度单位(deg、grad、rad 和 turn)表示。

rotate() 函数实施的是 2D 旋转,效果等同于 rotateZ(),是我们最常用的旋转方式。类似地,rotateX() 绕 x 轴旋转,rotateY() 绕 y 轴旋转元素。

使用 rotate3d(),前三个值指定 3D 空间中向量的 x、y 和 z 分量,第四个值是角度值,指定绕向量旋转的量。

倾斜函数

倾斜函数沿 x 轴和(或) y 轴倾斜元素。元素不能沿 z 轴或 3D 空间中的向量倾斜。

skew(a, b) 的效果与 skewX(a)skewY(b) 不同。如果提供两个值,第一个始终是 x 轴的倾斜角度,第二个是 y 轴的倾斜角度。如未指定 y 轴倾斜角度,假定为零。

skew() 倾斜元素

视域函数

在 3D 空间中改变元素的形态时,基本上都要赋予元素一定的视域。视域为元素赋予前后深度,而这深度可以根据需要设定。

视域值必须是正数,而且不能为零。

如果想在变形函数列表中设定视域值,一定要把 perspective() 函数放在首位,至少也要放在依赖视域的变形之前。这一点特别重要,请牢记,transform 函数的编写顺序十分重要。

一般来说,最好使用后面即将提到的 perspective 属性,不过也有需要使用 perspective() 函数的例外情况。

矩阵函数

matrix() 函数的有效值是六个以逗号分隔的数字,不能多也不能少。matrix() 函数的值所用的句法十分复杂,描述的是元素变形后的最终状态,可以涵盖其他所有变形类型(旋转、倾斜等)。

matrix3d() 函数的值是 16 个以逗号分隔的数字,不能多也不能少。

其他变形属性

除了基本的 transform 属性之外,还有几个辅助属性,用于定义变形的原点、“场景”使用的视域等。

transform-origin 属性

transform-origin 属性的值为两个或三个关键字,用于定义相对哪个点变形:第一个值针对横向,第二个值针对纵向,可选的第三个值是 z 轴上的长度。横轴和纵轴可以使用百分数、长度,或者 top 等关键字。z 轴只能使用长度值。初始值是 50% 50%,适用于任何可变形的元素。

长度值设定的是距元素左上角的距离,百分数相对对应的轴和元素的尺寸计算,设定的是距元素左上角的偏移量。

定义原点的不同方式

原点对缩放、旋转和倾斜三种变形类型有影响,对平移没有影响。

transform-style 属性

默认情况下,不管怎么变形,得到的结果都是扁平的。如果希望在 3D 空间中呈现元素,可以使用 transform-style 属性修改。

transform-style 属性有两个可选值:flat 和 preserve-3d。初始值是 flat,适用于任何可变形的元素。

perspective 和 perspective-origin 属性

视域其实由两个属性定义:一个定义视域距离,相当于前面讨论过的 perspective() 函数;另一个定义视域的原点。

(1)定义视域

perspective 属性的值是一个长度,定义视域锥体的深度。初始值是 none,适用于任何可变形的元素。

perspective: 2500px;
perspective: 200px;

perspective() 函数只为目标元素定义视域,那么只有应用这个规则的元素才使用设定的视域。而 perspective 属性定义的视域深度应用到目标元素的所有子元素上。多数时候,应该使用 perspective 属性。

(2)移动视域的原点

视域有原点,也称消隐点,这个点的位置可以使用 perspective-origin 属性修改。这个属性的初始值是 50% 50%,适用于任何可变形的元素。

perspective: 850px;
perspective-origin: 50% 0%;

倘若 perspective 属性的值是默认值 none,不管把 perspective-origin 设为什么,都将被忽略。毕竟,没有视域也就没有视域原点。

backface-visibility 属性

backface-visibility 属性的作用是决定元素的背面朝向我们时是否渲染背面。

这个属性的可选值有两个 visible 和 hidden。初始值是 visible,适用于任何可变形的元素。

小结

Hello, transform.

文本属性

文本属性

这是学习《CSS 权威指南》的第 6 章的笔记。

缩进和行内对齐

缩进文本

CSS 文本缩进使用 text-indent 属性,只能用于块级元素上。

如果想“缩进”行内元素的首行,可以通过内边距或外边距实现。

text-indnet 属性的值可以是负值,这样可以实现一些有趣的效果。

text-indent 属性的值可以使用任何长度单位,包括百分数。

注意,文本缩进只影响元素的第一行,即便有换行也是如此。text-indent 会继承,因此可能会出现预料之外的效果。

文本对齐

文本对齐使用 text-align 属性,适用于块级元素,取值有 start | end | left | right | center | justify | match-parent | start end。

  • 目前支持范围最广的三个值:left、right 和 center。
  • start 意思是文本与元素所在行框的起边对齐。
  • end 把文本与行框的终边对齐。
  • justify 是两端对齐。
  • 与父元素一致:match-parent。
  • start end 也是 text-align 的一个取值,但是它尚未实现,以后的规范可能会将其删除。

对齐最后一行

对齐最后一行使用 text-align-last 属性,取值有 auto | start | end | left | right | center | justify。

只要一行后面有强制换行,不管是不是在元素的末尾,都受 text-align-last 属性的控制。

text-align-last 有个有趣的现象:如果元素的第一行也是最后一行,text-align-last 的优先级比 text-align 高。

块级对齐

行的高度

line-height:行高。

line-height 控制的是行距,是除字体高度之外在文本行上方的额外空间。也就是说,line-height 的值与字体高度之差就是行距。行距可能为负数。

line-height 取默认值 normal 时,行之间的空间由用户代理计算。

em、ex 和百分数相对元素的 font-size 的值计算。

块级元素之间继承的行高有点复杂。从父元素继承 line-height 值时,根据父元素的字号计算,而不根据子元素计算。

body {
  font-size: 10px;
}

div {
  line-height: 1em; /* 计算结果为 10px */
}

p {
  font-size: 18px;
}
<div>
  <p>111</p>
</div>

更好的方法是使用纯数字,即设定一个换算系数:

div {
  line-height: 1.5;
}

p {
  font-size: 18px;
}
<div>
  <p>222</p>
</div>

现在段落里的 line-height 是 27。

纵向对齐文本

CSS 中的 vertical-align 属性只能用于行内元素和置换元素(例如图像和表单输入框)。vertical-align 属性不继承。

  • vertical-align: baseline 强制元素的基线与父元素的基线对齐。如果目标元素没有基线,例如图像、表单输入框或其他置换元素,元素的底端与父元素的基线对齐。

  • vertical-align: sub 把元素放在下标处,即元素的基线(对置换元素来说是底边线)低于父元素的基线。super 的作用与 sub 相反,让元素的基线(或置换元素的底边线)高于父元素的基线。
    注意,sub 和 super 不改变元素的字号,因此下标和上标中的文本不会变小I(或变大)。下标和上标中的文本默认情况下与父元素的字号相等。

  • vertical-align: bottom 把元素所在行内框的底边与行框的底边对齐(底端对齐)。

  • vertical-align: text-bottom 相对行中文本的底边对齐。

  • vertical-align: top 的作用与 bottom 相反。
    vertical-align: text-top 的作用与 text-bottom 相反。

  • vertical-align: middle 中线对齐。

  • 把 vertical-align 的值设为百分数,效果是把元素的基线(或置换元素的底边)相对父元素的基线抬升或下沉指定的量(指定的百分数相对元素自身而非父元素的 line-height 计算)。

  • 把值设为长度值时,vertical-align 的效果很简单:把元素抬升或下沉声明的距离。因此,vertical-align: 5px; 把元素从原位置向上抬升 5 像素。

单词间距和字符间距

单词间距使用 word-spacing 属性,其值为长度,可正可负。其实,word-spacing 属性用于修改单词之间的距离。因此,默认值 normal 等于把值设为零(0)。

用最简单的 CSS 术语来说,“单词”是指两侧有某种空白的非空字符构成的字符串。word-spacing 不能用于象形文字或非罗马书写体。

word-spacing 属性的很多问题在 letter-spacing 属性上也有体现。这两个属性之间唯一的区别是,letter-spacing 属性修改的是字符或字母之间的距离。

文本转换

使用 text-transform 属性转变文本的大小写,取值有 uppercase | lowercase | capitalize | none

其中 capitalize 只把各单词的首字母变成大写。

文本装饰

text-decoration 的取值有:

  • underline 为元素添加下划线。
  • overline 与 underline 正好相反。
  • line-through 绘制一条贯穿文本中部的线,叫删除线。
  • blink 让文本一闪一闪。
  • none 值把应用到元素上的装饰效果去掉。

一个规则中可以使用多个装饰效果。

a:link,
a:visited {
  text-decoration: underline overline;
}

文本渲染结果

text-rendering 是 CSS 最近新增的属性,它其实是一个 SVG 属性,支持它的用户代理不会把它视作 CSS 属性。这个属性的作用是让创作人员指定用户代理在显示文本时应该优先考虑什么方面,取值有:

  • optimizeSpeed 指明首先考虑绘制速度。
  • optimizeLegibility 指明首先考虑清晰性。
  • geometricPrecision 让用户代理尽量精准地绘制文本,确保能无损缩放。
  • auto 用户代理自行决定合适的方法,只要向清晰性倾斜就行。

文本阴影

为文本添加阴影:text-shadow 属性。

阴影由一个可选的颜色和三个长度值定义,最后一个长度值也是可选的。

如果省略颜色,阴影的颜色将与文本的颜色相同。

前两个长度值是阴影离文本的距离。第一个长度值设定横向偏移,第二个长度值设定纵向偏移。可选的第三个长度值定义阴影的模糊半径。

p.cl1 {
  color: black;
  text-shadow: gray 2px 2px 4px;
}

p.cl2 {
  color: white;
  text-shadow: 0 0 4px black;
}

处理空白

white-space 属性,影响用户代理对文档源码中空格、换行符和制表符的处理方式,取值有 normal | nowrap | pre | pre-wrap | pre-line。

空白 换行符 自动换行
pre-line 折叠 保留 允许
normal 折叠 忽略 允许
nowrap 折叠 忽略 禁止
pre 保留 保留 禁止
pre-wrap 保留 保留 允许

设定制表符的宽度 tab-size。

换行和断字

hyphens 自动断字,取值有 manual | auto | none。

word-break 软换行,取值有 normal | break-all | keep-all。

line-break 属性也能影响软换行,取值有 auto | loose | normal | strict。

overflow-wrap 文本换行,取值有 normal | break-word。

有个名为 word-wrap 的属性,其作用与 overflow-wrap 完全一样。

书写模式

设定书写模式的属性是 writing-mode,取值有:

  • horizontal-tb 行内方向为横向,块级方向为从上到下。
  • vertical-rl 和 vertical-lr 采用的行内方向是纵向,块级方向是从右至左或从左至右。

改变文本方向的属性是 text-orientation,取值有 mixed | upright | sideways。

小结

从多个角度考虑问题,多动脑。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.