《深入解析CSS》书籍tuijian

2020/01/26 书籍推荐

推荐理由

和css 世界结合看,很不错,两本书可以互补了

层叠

(1)样式表的来源:样式是从哪里来的,包括你的样式和浏览器默认样式等。

(2) 选择器优先级:哪些选择器比另一些选择器更重要。

(3) 源码顺序:样式在样式表里的声明顺序。

实际上行内元素属于“带作用域的”声明,它会覆盖任何来自样式表或者<style>标签的样式。行内样式没有选择器,因为它们直接作用于所在的元素

很多时候开发人员使用ID选择器,却不知道它会创建更高的优先级,之后就很难覆盖它。如果要覆盖一个ID选择器的样式,就必须要用另一个ID选择器。 所以不建议我们使用ID选择器

一旦引入一个!important,就会带来更多的!important,所以一般不建议使用 important

如果两个声明的来源和优先级相同,其中一个声明在样式表中出现较晚,或者位于页面较晚引入的样式表中,则该声明胜出。

书写顺序之所以很重要,是因为层叠。优先级相同时,后出现的样式会覆盖先出现的样式。如果一个元素同时处于两个或者更多状态,最后一个状态就能覆盖其他状态。如果用户将鼠标悬停在一个访问过的链接上,悬停效果会生效。如果用户在鼠标悬停时激活了链接(即点击了它),激活的样式会生效。这个顺序的记忆口诀是“LoVe/HAte”(“爱/恨”),即link(链接)、visited(访问)、hover(悬停)、active(激活)。注意,如果将一个选择器的优先级改得跟其他的选择器不一样,这个规则就会遭到破坏,可能会带来意想不到的结果。

浏览器遵循三个步骤,即来源、优先级、源码顺序,来解析网页上每个元素的每个属性。如果一个声明在层叠中“胜出”,它就被称作一个层叠值

层叠值——作为层叠结果,应用到一个元素上的特定属性的值。

如果一个元素上始终没有指定一个属性,这个属性就没有层叠值。还是拿段落举例,可能就没有指定的边框或者内边距

当创建一个用于分发的JavaScript模块(比如NPM包)时,强烈建议尽量不要在JavaScript里使用行内样式。如果这样做了,就是在强迫使用该包的开发人员要么全盘接受包里的样式,要么给每个想修改的属性加上!important。因为只有在样式表里面的类加上 important 属性才能覆盖javascript里面的样式

正确的做法是在包里包含一个样式表。如果组件需要频繁修改样式,通常最好用JavaScript给元素添加或者移除类。这样用户就可以在使用这份样式表的同时,在不引入优先级竞赛的前提下,按照自己的喜好选择编辑其中的样式。

继承

如果一个元素的某个属性没有层叠值,则可能会继承某个祖先元素的值

它们主要是跟文本相关的属性:color、font、font-family、font-size、font-weight、font-variant、font-style、line-height、letter-spacing、text-align、text-indent、text-transform、white-space以及word-spacing。还有一些其他的属性也可以被继承,比如列表属性:list-style、list-style-type、list-style-position以及list-style-image。表格的边框属性border-collapse和border-spacing也能被继承

有很多细节可以帮助开发人员弄清楚一个元素的样式是怎么产生的。靠近顶部的样式会覆盖下面的样式。被覆盖的样式上划了删除线。右侧显示了每个规则集的样式表和行号,你可以在源代码中找到它们。这样就能准确判断哪个元素继承了哪些样式以及这些样式的来源。还可以在顶部的筛选框中选择特定的声明,同时隐藏其他声明。

我们想用继承代替一个层叠值。这时候可以用inherit关键字。可以用它来覆盖另一个值,这样该元素就会继承其父元素的值

可以使用inherit关键字强制继承一个通常不会被继承的属性,比如边框和内边距。通常在实践中很少这么做,但是第3章介绍盒模型时,你会看到一个实际用例

如果想让一个元素恢复到默认宽度,设置width: initial即可。你可能已经习惯了使用auto来实现这种重置效果。实际上,用width: auto是一样的,因为width的默认值就是auto

padding: 1em 2em先指定了垂直方向的上/下属性值,然后才是水平方向的右/左属性值,而background-position: 25% 75%则先指定水平方向的右/左属性值,然后才是垂直方向的上/下属性值。

相对单位

px

人们最熟悉同时也最简单的应该是像素单位(px)。它是绝对单位,即5px放在哪里都一样大。而其他单位,如em和rem,就不是绝对单位,而是相对单位。相对单位的值会根据外部因素发生变化。比如,2em的具体值会根据它作用到的元素(有时甚至是根据属性)而变化。因此相对单位的用法更难掌握。

em

em是最常见的相对长度单位,适合基于特定的字号进行排版。在CSS中,1em等于当前元素的字号,其准确值取决于作用的元素

谈到font-size属性时,em表现得不太一样。之前提到过,当前元素的字号决定了em。但是,如果声明font-size: 1.2em,会发生什么呢?一个字号当然不能等于自己的1.2倍。实际上,这个font-size是根据继承的字号来计算的。如果他的父元素字号是16px,那么他的字号就是16px1.2=19.2,如果此时设置padding 是1.2em,换算为像素就是19.21.2=23.04px。因为继承的关系,会导致设置em子元素的像素值越来越大,或者越来越小。如果用不好的话就很麻烦了

rem

rem是root em的缩写。rem不是相对于当前元素,而是相对于根元素的单位。不管在文档的什么位置使用rem,1.2rem都会有相同的计算值:1.2乘以根元素的字号。

与em相比,rem降低了复杂性。实际上,rem结合了px和em的优点,既保留了相对单位的优势,又简单易用。那是不是应该全用rem,抛弃其他选择呢?答案是否定的。在CSS里,答案通常是“看情况”。rem只是你工具包中的一种工具。掌握CSS很重要的一点是学会在适当的场景使用适当的工具。我一般会用rem设置字号,用px设置边框,用em设置其他大部分属性,尤其是内边距、外边距和圆角(不过我有时用百分比设置容器宽度)。

vh vw

视口——浏览器窗口里网页可见部分的边框区域。它不包括浏览器的地址栏、工具栏、状态栏。

1vh=视口高度的1/100

1vw=视口宽度的1/100

calc()函数内可以对两个及其以上的值进行基本运算。当要结合不同单位的值时,calc()特别实用。它支持的运算包括:加(+)、减(−)、乘(×)、除(÷)。加号和减号两边必须有空白

说明如果刚好用了内置变量功能的CSS预处理器,比如Sass或者Less,你可能就不太想用CSS变量了。千万别这样。新规范里的CSS变量有本质上的区别,它比任何一款预处理器的变量功能都多。因此我倾向于称其为“自定义属性”,而不是变量,以强调它跟预处理器变量的区别。

root根元素代码义了一个名叫–main-font的变量。将其值设置为一些常见的sans-serif字体。变量名前面必须有两个连字符(–),用来跟CSS属性区分,剩下的部分可以随意命名。调用函数var()就能使用该变量。利用该函数引用前面定义的变量–main-font(font-family:var(–main-font))。var()函数接受第二个参数,它指定了备用值。如果第一个参数指定的变量未定义,那么就会使用第二个值

自定义属性只不过为减少重复代码提供了一种便捷方式,但是它真正的意义在于,自定义属性的声明能够层叠和继承:可以在多个选择器中定义相同的变量,这个变量在网页的不同地方有不同的值。自定义属性就像作用域变量一样,因为它的值会被后代元素继承(可能现在还有很多浏览器不支持这个功能

对颜色使用了自定义变量,使用变量以后,一旦后续需要修改这些值,就会很省事。我曾经参与过的一个项目,已经进行到后期了,设计师决定调整品牌颜色。我只需要在一个地方修改一下变量,非常简单,但实际上已经修改了代码里所有用到变量的地方。

盒模型

因为IE有一个bug,它会默认将<main>元素渲染成行内元素,而不是块级元素,所以代码中我们用声明display: block来纠正

盒模型通常不会被继承,但是使用inherit关键字可以强制继承

通常最好避免给元素指定明确的高度。普通文档流是为限定的宽度和无限的高度设计的。内容会填满视口的宽度,然后在必要的时候折行。因此,容器的高度由内容天然地决定,而不是容器自己决定。

普通文档流——指的是网页元素的默认布局行为。行内元素跟随文字的方向从左到右排列,当到达容器边缘时会换行。块级元素会占据完整的一行,前后都有换行。

请谨慎地使用滚动条。浏览器给网页最外层加上了滚动条,如果网页内部再嵌套滚动区域,用户就会很反感。如果用户使用鼠标滚轮滚动网页,当鼠标到达一个较小的滚动区域,滚轮就会停止滚动网页,转而滚动较小的区域

vertical-align声明只会影响行内元素或者table-cell元素。对于行内元素,它控制着该元素跟同一行内其他元素之间的对齐关系。如果块级原生设置这个就会失效

负外边距并不常用,但是在某些场景下很实用,尤其是当创建列布局的时候。不过应当避免频繁使用,不然网页的样式就会失控。

说明只有上下外边距会产生折叠,左右外边距不会折叠。(可以利用BFC解决这个问题

页面布局

最简单的方式是先将网页的大块区域布局好,再逐级布局内部的小元素。先整体后部分

这是因为浮动元素不同于普通文档流的元素,它们的高度不会加到父元素上。所以就会有高度坍塌的情况出现,会形成BFC

BFC里的内容不会跟外部的元素重叠或者相互影响

给元素添加以下的任意属性值都会创建BFC。 ❑ float: left或right,不为none即可。

❑ overflow:hidden、auto或scroll,不为visible即可。

❑ display:inline-block、table-cell、table-caption、flex、inline-flex、grid或inline-grid。拥有这些属性的元素称为块级容器(block container)。

❑ position:absolute或position: fixed。

说明网页的根元素也创建了一个顶级的BFC

使用overflow: auto通常是创建BFC最简单的一种方式。也可以使用前面提到的其他方式,但是有些问题需要注意,比如,使用浮动或者inline-block方式创建BFC的元素宽度会变成100%,因此需要限制一下元素的宽度,防止因为过宽而换行,导致内容移动到浮动图片的下面。相反,使用table-cell方式显示的元素,其宽度只会刚好容纳其中的内容,因此需要设置一个较大的宽度,强制使其填满剩余空间。

通常网格系统的每行被划分为特定数量的列,一般是12个,但也可以是其他数。每行子元素的宽度可能等于1~12个列的宽度

使用负外边距来拉伸行元素的宽度。给行元素添加一个−0.75em的左侧外边距。但是一般我们很少用负外边距,为了别人能够更好的看懂我们的代码。有必要的时候还是可以用的

❑ 浮动的设计初衷是让文字围绕一个元素排列,但有时这种效果并不是我们想要的。

❑ 使用清除浮动来包含浮动元素。

❑ BFC有3个好处:包含浮动元素,防止外边距折叠,防止文档流围绕浮动元素排列。

层叠上下文负责决定哪些元素出现在另一些元素前面,而BFC负责处理文档流,以及元素是否会重叠。

flex 原则

给元素添加display: flex,该元素变成了一个弹性容器(flexcontainer),它的直接子元素变成了弹性子元素(flexitem)。弹性子元素默认是在同一行按照从左到右的顺序并排排列。弹性容器像块元素一样填满可用宽度,但是弹性子元素不一定填满其弹性容器的宽度。弹性子元素高度相等,该高度由它们的内容决定

一个弹性容器能控制内部元素的布局

弹性盒子内部的auto外边距会填充所有可用空间(margin-left:auto,可以实现靠右边)

flex属性是三个不同大小属性的简写:flex-grow、flex-shrink和flex-basis。只提供了flex-grow的值,剩下的两个属性是默认值(分别是1和0%)

使用flex-basis属性:如果没有,则用元素内容自身的大小。如果flex-basis的值不是auto, width属性会被忽略

如果一个弹性子元素的flex-grow值为0,那么它的宽度不会超过flex-basis的值;如果某个弹性子元素的增长因子非0,那么这些元素会增长到所有的剩余空间被分配完,也就意味着弹性子元素会填满容器的宽度

flex-grow的值越大,元素的“权重”越高,也就会占据更大的剩余宽度。一个flex-grow:2的子元素增长的宽度为flex-grow: 1的子元素的两倍

如果某个子元素为flex-shrink: 0,则不会收缩;如果值大于0,则会收缩至不再溢出。按照flex-shrink值的比例,值越大的元素收缩得越多

每个弹性子元素的初始主尺寸确定后,它们可能需要在主轴方向扩大或者缩小来适应(或者填充)弹性容器的大小。这时候就需要flex-grow和flex-shrink来决定缩放的规则。

如果在flex中忽略某个子属性,那么子属性的值并不会被置为初始值。相反,如果某个子属性被省略,那么flex简写属性会给出有用的默认值:flex-grow为1、flex-shrink为1、flex-basis为0%。这些默认值正是大多数情况下所需要的值

改变弹性方向,如果改成垂直方向的,那么主轴也会跟着发生旋转,现在变成了从上到下(副轴变成了从左到右)。也就是对于弹性子元素而言,flex-basis、flex-grow和flex-shrink现在作用于元素的高度而不是宽度

弹性容器会占据100%的可用宽度,而高度则由自身的内容来决定。即使改变主轴方向,也不会影响这一本质。

弹性容器的高度由弹性子元素决定,它们会正好填满容器。在垂直的弹性盒子里,子元素的flex-grow和flex-shrink不会起作用,除非有“外力”强行改变弹性容器的高度。在本章的网页里,“外力”就是从外层弹性盒子计算出来的高度。

容器的属性

flex-wrap属性允许弹性子元素换到新的一行或多行显示。它可以设置为nowrap(初始值)、wrap或者wrap-reverse。启用换行后,子元素不再根据flex-shrink值收缩,任何超过弹性容器的子元素都会换行显示。

flex-flow属性是flex-direction和flex-wrap的简写。例如,flex-grow: column wrap指定弹性子元素按照从上到下的方式排列,必要时换到新的一列。

当子元素未填满容器时,justify-content属性控制子元素沿主轴方向的间距。它的值包括几个关键字:flex-start、flex-end、center、space-between以及space-around

间距是在元素的外边距之后进行计算的,而且flex-grow的值要考虑进来。也就是说,如果任意子元素的flex-grow的值不为0,或者任意子元素在主轴方向的外边距值为auto,justify-content就失效了

justify-content控制子元素在主轴方向的对齐方式,align-items则控制子元素在副轴方向的对齐方式。align-items的初始值为stretch,在水平排列的情况下让所有子元素填充容器的高度,在垂直排列的情况下让子元素填充容器的宽度,因此它能实现等高列。

如果开启了换行(用flex-wrap), align-content属性就可以控制弹性容器内沿副轴方向每行之间的间距。它支持的值有flex-start、flex-end、center、stretch(初始值)、space-between以及space-around。这些值对间距的处理类似上面的justify-content。

子元素的属性

align-self属性:该属性控制弹性子元素沿着容器副轴方向的对齐方式。它跟弹性容器的align-items属性效果相同,但是它能单独给弹性子元素设定不同的对齐方式。auto为初始值,会以容器的align-items值为准。其他值会覆盖容器的设置。align-self属性支持的关键字与align-items一样:flex-start、flex-end、center、stretch以及baseline。

一旦你熟悉了它,你可能想要在页面的每个地方都开始使用,不过你应该依靠正常的文档流,只在必要的时候才使用Flexbox。这么说并不是让你不用它,而是希望你不要拿着锤子满世界找钉子

栅格布局(现在用的少

使用display: grid定义一个网格容器。容器会表现得像一个块级元素,100%填充可用宽度。

grid-template-columns和grid-template-rows。这两个属性定义了网格每行每列的大小。本例使用了一种新单位fr,代表每一列(或每一行)的分数单位(fraction unit)。这个单位跟Flexbox中flex-grow因子的表现一样。grid-template-columns:1fr 1fr 1fr表示三列等宽

例如,grid-template-columns: 300px 1fr定义了一个固定宽度为300px的列,后面跟着一个会填满剩余可用空间的列。2fr的列宽是1fr的两倍。

grid-gap属性定义了每个网格单元之间的间距。也可以用两个值分别指定垂直和水平方向的间距(比如grid-gap: 0.5em 1em)

grid-template-rows: repeat(4, auto);定义了四个水平网格轨道,高度为auto,这等价于grid-template-rows:auto auto auto auto。轨道大小设置为auto,轨道会根据自身内容扩展。宽度使用repeat也是一样的道理

Flexbox本质上是一维的,而网格是二维的。

❑ Flexbox是以内容为切入点由内向外工作的,而网格是以布局为切入点从外向内工作的。

因为Flexbox是一维的,所以它很适合用在相似的元素组成的行(或列)上。它支持用flex-wrap换行,但是没法让上一行元素跟下一行元素对齐。相反,网格是二维的,旨在解决一个轨道的元素跟另一个轨道的元素对齐的问题。它们的区别如图6-8所示。

层级

给一个元素设置position: fixed就能将元素放在视口的任意位置。这需要搭配四种属性一起使用:top、right、bottom和left。这些属性的值决定了固定定位的元素与浏览器视口边缘的距离

所有层叠上下文内的元素会按照以下顺序,从后到前叠放:

❑ 层叠上下文的根

❑ z-index为负的定位元素(及其子元素)

❑ 非定位元素❑ z-index为auto的定位元素(及其子元素)

❑ z-index为正的定位元素(及其子元素)

有些开发人员会忍不住给页面的大量元素使用定位。一定要克制这种冲动。定位用得越多,网页就越复杂,也就越难调试。如果你定位了大量元素,就回头评估一下现在的情况,尤其是当你发现很难调试出自己想要的布局时,一定要反思。如果可以用别的方法实现某个布局,应该优先用那些方法

定位会将元素拉出文档流。一般来说,只有在需要将元素叠放到别的元素之前时,才应该用定位。

粘性定位(sticky positioning)。它是相对定位和固定定位的结合体:正常情况下,元素会随着页面滚动,当到达屏幕的特定位置时,如果用户继续滚动,它就会“锁定”在这个位置。最常见的用例是侧边栏导航

响应式设计

响应式设计的三大原则如下。

(1) 移动优先。这意味着在实现桌面布局之前先构建移动版的布局。=> 渐进增强 为pc端或者大屏用户增加体验

(2) @media规则。使用这个样式规则,可以为不同大小的视口定制样式。用这一语法,通常叫作媒体查询(mediaqueries),写的样式只在特定条件下才会生效。

(3) 流式布局。这种方式允许容器根据视口宽度缩放尺寸

重点做响应式设计时,一定要确保HTML包含了各种屏幕尺寸所需的全部内容。你可以对每个屏幕尺寸应用不同的CSS,但是它们必须共享同一份HTML。

视口的meta标签。这个HTML标签告诉移动设备,你已经特意将网页适配了小屏设备。如果不加这个标签,移动浏览器会假定网页不是响应式的,并且会尝试模拟桌面浏览器,那之前的移动端设计就白做了

@media (min-width:20em) and (max-width:35em) :这种联合媒体查询只在设备同时满足这两个条件时才生效

@media (max-width:20em),(min-width:35em):这句媒体查询匹配小于等于20em的视口,以及大于等于35em的视口。

媒体查询还可以放在<link>标签中。在网页里加入<link rel="stylesheet"media="(min-width:45em)" href="large-screen.css" />,只有当min-width媒体查询条件满足的时候才会将large-screen.css文件的样式应用到页面。然而不管视口宽度如何,样式表都会被下载。这种方式只是为了更好地组织代码,并不会节省网络流量

流式布局,有时被称作液体布局(liquid layout),指的是使用的容器随视口宽度而变化。它跟固定布局相反,固定布局的列都是用px或者em单位定义

要习惯将容器宽度设置为百分比,而不是任何固定的值,这样的话后期扩展比较方便

使用srcset提供对应的图片,可是根据不同的屏幕大小使用不同的图片。不支持的浏览器会根据src属性加载相应的URL。这种方式允许针对不同的屏幕尺寸优化图片。更棒的是,浏览器会针对高分辨率的屏幕做出调整。如果设备的屏幕像素密度是2倍,浏览器就会相应地加载更高分辨率的图片

<img srcset="./elva-fairy-320w.jpg 320w,
             ./elva-fairy-480w.jpg 480w,
             ./elva-fairy-800w.jpg 800w"
     sizes="(max-width: 320px) 280px,
            (max-width: 480px) 440px,
            800px"
     src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

响应式图片

em是相对长度单位。 相对于当前对象内文本的字体尺寸。 如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸,浏览器字体默认为16px。 所以,1em = 16px

模块 css

这跟组合家具的原理类似。例如,宜家厨房不是建造一个大型的橱柜单元,而是设计成各种独立的小件,让顾客可以任选购买。这些小件看上去风格一致,组合起来也会很和谐。这样一来,顾客就可以在布置的时候把这些小件随意摆放到自己喜欢的位置。模块化CSS也是这样,它不是直接编写一个大型网页,而是编写页面的每个部分,然后按照你需要的效果组合在一起

基础样式:打好基础。基础样式配置完成以后,很少会再修改。我们会在基础样式的稳定表现之上,构建模块化CSS。在样式表中,基础样式后面的内容将主要由各种模块组成。

公共样式的时候,不要使用依赖语境的选择器。

写.dropdown–dark,而不是写成.page-header.dropdown。通过这种方式,模块本身,并且只能是它本身,可以决定自己的样式表现。其他模块不能进入别的模块内部去修改它。这样一来,深色下拉列表并没有绑定到深层嵌套的HTML结构上,也就可以在页面上需要的地方随意使用。

避免在模块选择器中使用通用标签名

每个模块应该只做一件事情。消息模块的职责是使消息提示醒目;媒体模块的职责是在一段文本中配置一张图片。我们可以简洁明了地概括出它们的目标。有的模块是为了版面布局,有的是为了编写体例。当模块想要完成不只一件事的时候,我们应该考虑把它拆分成更小的模块。

如果你不得不使用并(或者和)这个词来表述模块的职责,那你可能正在描述多项职责,这个时候就需要拆分逻辑了

状态类一般以is-或者has-开头。这样状态类的目的就会比较明显,它们表示模块当前状态下的一些特征或者即将发生的变化。再举一些状态类的示例,比如is-expanded、is-loading或者has-error等。这些状态类具体会表现成什么样子取决于使用它们的模块

为模块的变体类命名的时候,应该遵守同样的原则。例如,如果已经有按钮模块了,就不应该使用button–red和button–blue命名红色和蓝色变体子类。网站设计在将来有可能会改变,你不知道这些按钮的颜色会不会也跟着变化。应该使用一些更有意义的名称,比如button–danger和button–success。

使用大或小这样具有相对意义的词语来命名修饰符不是最佳方式,但也可以接受。没人说过网站重构的时候不能更改button–large的尺寸,只要它还是比标准按钮大一些就可以。一定要牢记,不要使用像button–20px这样特别精确的修饰符。

❑ 把CSS拆解成可复用的模块。

❑ 不要书写可能影响其他模块或者改变其他模块外观的样式。

❑ 使用变体类,提供同一模块的不同版本。

❑ 把较大的结构拆解成较小的模块,然后把多个模块组合在一起构建页面。

❑ 在样式表中,把所有用于同一个模块的样式放在一起。

❑ 使用一种命名约定,比如双连字符和双下划线,以便一眼就可以看清楚模块的结构。

应该问如何编写样式才能更好地复用到任意页面上。我们应该先写好CSS,结构良好的HTML自然就有了。

考虑好CSS定义的API,之后不要轻易修改它。

CSS3 新属性

设计师可是花费了很多精力推敲那些细节的,一定要认真对待这件事情,所以我们在还原设计稿的时候,尽可能还原度高一点

background

background-image——指定一个文件或者生成的颜色渐变作为背景图片。

background-position——设置背景图片的初始位置。

background-size——指定元素内背景图片的渲染尺寸。cover:缩放背景图片以完全覆盖背景区,可能背景图片部分看不见;contain:缩放背景图片以完全装入背景区,可能背景区部分空白

background-repeat——决定在需要填充整个元素时,是否平铺图片。

background-origin——决定背景相对于元素的边框盒、内边距框盒(初始值)或内容盒子来定位。

background-clip——指定背景是否应该填充边框盒(初始值)、内边距框盒或内容盒子。

background-attachment——指定背景图片是随着元素上下滚动(初始值),还是固定在视口区域。注意,使用fixed值会对页面性能产生负面影响。❑ background-color——指定纯色背景,渲染到背景图片下方。

background-color——指定纯色背景,渲染到背景图片下方。linear-gradient函数使用三个参数来定义行为:角度、起始颜色和终止颜色

background-image:linear-gradient(90deg, red 40%,white 40%, white 60% blue 60%) 因为第一个颜色节点是红色,在40%的位置,所以渐变从左侧边缘一直到40%是纯红色;因为第二个颜色节点是白色,也是在40%的位置,所以渐变在这里直接变成了白色;接下来因为在60%的位置,还有一个白色的颜色节点,所以40%到60%之间的渐变是纯白色;最后一个颜色节点是蓝色,也是在60%的位置,这样就会直接变换成蓝色,然后一直到右侧边缘是蓝色。

重复渐变:repeating-linear-gradient()

repeating-radial-gradient()函数可以重复生成图样,形成同心圆环。

### 阴影 box-shadow可以为元素盒子生成阴影,text-shadow可以为渲染后的文字生成阴影

声明box-shadow: 1em 1em black。其中1em代表偏移量,即阴影从元素的位置偏移了多少距离(先水平方向,后垂直方向)。如果偏移量都设置为0,那么阴影会直接渲染在元素下方。black指明了阴影的颜色。

文本阴影的语法也基本上完全一样:水平偏移量、垂直偏移量、模糊半径(可选)和颜色

渐变和阴影可以以各种各样的方式组合使用。随着时间的推移,又会有新的设计流行起来。我们要做的是,在看到某个网站上的新设计时,停下来花些时间,用浏览器的开发者工具检查一下,看看这是如何实现的。不要觉得麻烦哦,见多才能识广。

对比是设计中的一种手段,通过突出某物来达到吸引注意力的目的。我们的眼睛和思维天生对模式比较敏感,一旦某种东西破坏了模式的整体效果,我们就自然而然地注意到了它。

网页都有目的,可能是讲述一个故事,也可能是为了收集信息,或者是要求用户完成某些任务。在核心目标之外,还可能会有导航元素、广告、文本段落、填满版权信息和友情链接的页脚等。设计师的工作是让最重要的信息突显出来,而我们作为开发者,是不要弄乱设计师的设计。

对于段落和标题这样的元素,内容盒子并不是只有显示出来的文字区域,元素的行高决定了内容盒子最终的高度,这要超出字符的顶部和底部。文字高度是1em,但是行高超出了文字上下边缘一点。网页里的行高是1.4,这是从<body>元素上设置并继承下来的。这样只有一行文字的元素,内容盒子的高度就是1.4em,文字在内部垂直居中。字号是16px,内容盒子的最终高度就是22.4px。额外的6.4px平均分配到文字的上方和下方。

设计师习惯使用行距(leading)来表示每行文字之间的间距。在CSS中,文字间距由行高控制,不能直接转换成行距。

文本行的高度是由行高乘以字号决定的。如果为行内元素添加内边距,元素本身会变高,却不会增加文本行的高度。文本行的高度只由行高来决定。行高可以影响垂直间距

line-height属性的初始值是关键字normal,大约等于1.2(确切的数值是在字体文件中编码的,取决于字体的em大小),但是在大部分情况下,这个值太小了。对于正文主体来说,介于1.4和1.6之间的值比较理想。

文字行越长,行高应该设置得越大。这样读者的眼睛扫到下一行的时候才更容易,不会注意力分散。理想情况下,每行文字的长度应该控制在45~75个字符,一般认为这样的长度最利于阅读。

## 过渡 过渡是通过一系列transition-*属性来实现的。如果某个元素设置了过渡,那么当它的属性值发生变化时,并不是直接变成新值,而是使用过渡效果

我们可以使用几个关键字值来描述移动过程,比如linear、ease-in和ease-out。使用linear过渡,值以固定的速度改变;使用ease-in,变化速度开始时慢,然后一直加速,直到过渡完成;ease-out是减速,开始时快速变化,结束时比较慢。

对于鼠标悬停、淡入淡出和轻微缩放特效,应该使用较快的过渡速度。一般要控制在300ms以下,有时候甚至可能要低到100ms。对于那些包含较大移动或者复杂定时函数的过渡,比如弹跳特效(参见第15章),要使用较长的300~500ms的持续时间。

不是所有属性都可以添加动画效果,display属性就是其中之一。你可以在display: none和display: block之间切换,但不能在这两个值之间过渡,因此,任何应用到display上的过渡属性都会被忽略。

大部分的接受长度值、数值、颜色值或者calc()函数值的属性可以添加动画效果;大部分的使用关键字或者其他非连续性值的属性(比如url())不可以使用动画。

opacity属性可以是介于0(完全透明)和1(完全不透明)之间的任意值。

但跟display不同的是,visibility可以支持动画。为它设置过渡不会使其逐渐消失,但transition-delay可以生效,而在display属性上是不生效的。

第一组值为opacity设置0.2s的过渡,第二组值为visibility设置0s的过渡(立即执行),但有0.2s的延迟。这就意味着先执行opacity的过渡,结束之后再执行visibility的过渡。这样就实现了菜单的缓慢淡出,当完全透明的时候,可见性切换为hidden。现在用户就可以点击“Read more”链接而不受菜单的干扰了。

height 不能从一个长度为0的过渡到auto

如果一个元素使用display: none隐藏起来,那它的scrollHeight属性等于0。遇到这种情况的时候,可以先把display属性设置为block(el.style.display=’block’),获取到scrollHeight,然后重置display的值(el.style.display = ‘none’)

变换

❑ 旋转(Rotate)——元素绕着一个轴心转动一定角度。

❑ 平移(Translate)——元素向上、下、左、右各个方向移动(有点类似于相对定位)。

❑ 缩放(Scale)——缩小或放大元素。

❑ 倾斜(Skew)——使元素变形,顶边滑向一个方向,底边滑向相反的方向。

使用变换的时候要注意一件事情,虽然元素可能会被移动到页面上的新位置,但它不会脱离文档流。你可以在屏幕范围内以各种方式平移元素,其初始位置不会被其他元素占用。当旋转某元素的时候,它的一角可能会移出屏幕边缘,同样也可能会遮住旁边其他元素的部分内容。某些情况下,为变换元素或者所有元素设置较大的外边距,有助于避免不必要的重叠。

变换不能作用在<span>或者<a>这样的行内元素上。若确实要变换此类元素,要么改变元素的display属性,替换掉inline(比如inline-block),要么把元素改为弹性子元素或者网格项目(为父元素应用display: flex或者display: grid)

变换在浏览器中的性能要好得多。如果我们要对元素的定位使用动画(比如为left属性添加过渡效果),可以明显感受到性能很差。对复杂元素使用动画或者在页面内一次性对多个元素使用动画,问题尤其明显

因为文档流的工作方式,所以一个元素的大小和位置可以影响页面上无数其他元素的大小和位置。

任何时候改变一个元素的宽度或高度,或者调整位置属性(比如top或者left),元素的布局都会重新计算。如果使用JavaScript在DOM中插入或者移除元素,也会重新计算布局。一旦布局发生改变,浏览器就必须重排(reflow)页面,重新计算所有其他被移动或者缩放的元素的布局。

布局之后是绘制。这个过程就是填充像素:描绘文本,着色图片、边框和阴影。这不会真正显示在屏幕上,而是在内存中绘制。页面各部分生成了很多的图层(layers)。

如果改变某个元素的背景颜色,就必须重新绘制它。但因为更改背景颜色不会影响到页面上任何元素的位置和大小,所以这种变化不需要重新计算布局。改变背景颜色比改变元素大小需要的计算操作要少。

某些条件下,页面元素会被提取到自己的图层。这时候,它会从页面的其他图层中独立出来单独绘制。浏览器把这个图层发送到计算机的图形处理器(graphics processingunit, GPU)进行绘制,而不是像主图层那样使用主CPU绘制。这样安排是有好处的,因为GPU经过了充分的优化,比较适合做这类计算这叫硬件加速。但是多个图层就意味着需要消耗更多的内存,但好处是可以加快渲染。

合成过程需要按照特定顺序进行,以确保图层出现重叠时,正确的图层显示在其他图层之上。opacity和transform这两个属性如果发生改变,需要的渲染时间就会非常少。当我们修改元素的这两个属性之一时,浏览器就会把元素提升到其自己的绘制图层并使用GPU加速

如果碰到这种情况,你可以使用一个叫作will-change的属性对渲染图层添加控制。这个属性可以提前告知浏览器,元素的特定属性将改变。这通常意味着元素将被提升到自己的绘制图层。例如,设置了will-change:transform就表示我们将要改变元素的transform属性。

处理过渡或者动画的时候,尽量只改变transform和opacity属性。如果有需要,可以修改那些只导致重绘而不会重新布局的属性。只有在没有其他替代方案的时候,再去修改那些影响布局的属性,并且密切关注动画中是否存在性能问题

过渡

我们定义第一帧(起始点)和最后一帧(结束点),浏览器计算所有中间值,使得元素可以在这些值之间平滑变换。但使用关键帧动画,我们就不再局限于只定义两个点,而是想加多少加多少。浏览器负责填充一个个点与点之间的值,直到最后一个关键帧,最终生成一系列无缝衔接的过渡。

用来定义动画的@keyframes规则和为元素添加动画的animation属性。

animation-name(over-and-back)——代表动画名称,就像@keyframes规则定义的那样。

❑ animation-duration(1.5s)——代表动画持续时间,在本例中是1.5s。

❑ animation-timing-function(linear)——代表定时函数,用来描述动画如何加速和/或减速。可以是贝塞尔曲线或者关键字值,就像过渡使用的定时函数一样(ease-in、ease-out,等等)。

❑ animation-iteration-count(3)——代表动画重复的次数。初始值默认是1


有时候,虽然素未谋面。却已相识很久,很微妙也很知足。在逝去的岁月里,我们在某一刻,共同经历着一样的情愫。

如果喜欢我的话,我们可以互相关注,相互学习的哟!互相鼓励,你的关注是我最大的动力来源

sunseekers

Search

    Table of Contents