今天这一章节主要是响应式布局需要补充的部分,以及通过 CSS 进行元素的2D、3D转换。
1 响应式布局
响应式布局,其实就是同一个页面会针对不同设备的浏览器大小,改变为不同的布局结构,使得页面可以适应不同的环境,以最佳的布局显示页面内容。
前面的几个章节,其实已经零散的把响应式布局必需的几个关键点都提到了,包括:弹性盒子、网格布局、媒体查询,而且在样例当中也有用到过viewport。
下面的内容,主要就是把针对响应式布局还需要补充的几个部分加上;题图是昨天网格布局+媒体查询所构成的纯文字式的响应式布局样例,今天还要考虑到图片和视频。
1.1 viewport
viewport 是用户网页的可视区域。
viewport 翻译为中文可以叫做"视区"。
移动设备的浏览器是把页面放在一个虚拟的窗口(viewport)中,通常这个虚拟的窗口比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机浏览器优化的网页的布局),用户可以通过平移和缩放来看网页的不同部分——但是没有经过特殊优化过的页面,会显得非常不方便。
我们通过 <meta> 标签来设置 viewport,一个常用的针对移动网页优化过的页面的 viewport meta 标签大致如下:
- width:控制 viewport 的大小,可以指定的一个值,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)
- height:和 width 相对应,指定高度
- initial-scale:初始缩放比例,也即是当页面第一次加载时候的缩放比例
- maximum-scale:允许用户缩放到的最大比例
- minimum-scale:允许用户缩放到的最小比例
- user-scalable:用户是否可以手动缩放
一个简单的例子如下,在一个普通页面上加入如下标签:
<
并加入适当的 CSS 媒体查询和布局优化,当移动设备的浏览器访问到有该设置的页面时,就会根据标签内容自动进行初始设置。
viewport meta 虽然是个 HTML 标签,但是因为它和 CSS 的关系更近,所以放在这里来介绍。
1.2 图像
显然,一个吸引人的页面是不可能只有纯文字的,图象是必不可少丰富页面的元素。那么响应式布局,也需要针对图像进行一定的优化。
(1)图片按情况缩放
最原始的方式,就是同一张图片根据不同的情况进行缩放,这是在不考虑用户网络条件、设备响应速度等等实际条件的时候,一种简单粗暴的解决方式:
img
在上面这种设置当中,一张图片的最大宽度不会超过它的实际宽度,并且由于宽高比固定,高度设置为自动的情况下,无论浏览器宽度为何,图片都会按其宽度自动缩放,如下:
(2)根据条件使用不同的图片
大尺寸的图片在小尺寸的设备上,可能会显得突兀,而且太过于占用带宽,所以我们很多时候会发现同一个页面在不同设备上,图片也会相应的改变,这是一种非常有效的解决方案。
不过因为 <img> 标签本身只能指定一张图片,按需使用不同的图片就非常的不方便,这里我们需要使用到 HTML 5 的 <picture> 标签来帮忙解决了(可以参考HTML从零开始——列表和图像标签,里面更详细)。
对之前章节有看过,或者对该标签比较熟悉的话就会清楚,通过指定不同的像素密度、不同尺寸等条件的不同图像,可以得到不同的图片,从而更加适应页面或者减少带宽的占用,是个非常实用的标签,下面是个例子:
<
(3)配合媒体查询设置背景图片
CSS 里面可以直接设置的图片,其实就是背景图片,而这个相应的设置起来就更简单一些,只要配合媒体查询来对背景图片进行设置就可以了,比如:
/* For width smaller than 500px: */
当然也可以使用设备宽度来代替页面宽度,比如:
/* For device width smaller than 500px: */
不过这个我没办法做演示了,可以自己试试看。
1.3 视频
这个其实很简单,因为视频不能像图片那样选择不同的来源,一般来说无论什么设备上,视频都是一样内容的,最多在专业视频网站上可以提供不同分辨率的视频(这个不是我们讨论范围之内的了),所以我们最常用的就是如下样式:
video
可以在保证不超过原有大小的情况下随容器或者页面宽度的变化而变化。
1.4 其他
在2017年w3c正式把网格布局纳入 CSS 3 标准之前,有很多项目是使用 bootstrap 的栅格系统来实现类似的响应式布局的,而且现在还有很多网站采用了这一套系统,所以我们也可以在很多地方看到 bootstrap 的教程,或者相关讨论。
Bootstrap 来自 Twitter,是曾经很受欢迎的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的,同时支持 HTML 和 CSS 规范,是由 CSS 的动态Less语言写成的。
其实我个人并没有真的在工作或者自己的项目里大范围用过 bootstrap,即便我是个老 jQuery 党了,也没考虑过用 bootstrap,因为大部分的复杂布局其实使用原生 CSS 已经完全足够了,网格布局的引入成为了我不去使用 bootstrap 的更直接原因。
有鉴于此,这里也就是提上一下,并不打算真的做几个章节来介绍这个框架,如果有兴趣了解,我建议看看菜鸟教程的相关介绍:bootstrap 教程
当然我的建议是,在基于对弹性盒子、网格布局、媒体查询等等基础知识了解透彻,实际应用已经很熟了之后,工作中、项目里需要用到的时候,自己做一套更适合自己的小框架,或者干脆就是一个代码段,岂不是比用一个动辄超过100K的面向公众的框架,要更直接和简单么?
2 2D、3D转换
CSS 3 的转换,使得我们可以移动,比例化,反置,旋转,和拉伸元素,比如:
2.1 2D转换
2D转换,其实就是在一个平面的情况下对元素进行改变,最明显最常用的就是旋转和缩放,需要使用到 transform 属性,以及如下的函数:
- translate():包含两个参数值,根据左(水平轴x)和顶部(垂直轴y)位置给定的参数,从当前元素位置移动,也可以使用如下替代函数:
- translateX():表示只在水平方向(X轴)移动
- translateY():表示只在垂直方向(Y轴)移动
- rotate():根据一个给定度数顺时针旋转的元素,可以使用负值,这时元素逆时针旋转
- scale():包含两个参数值,根据数值增加或减少元素的大小,取决于宽度和高度的参数,也可以使用如下替代函数:
- scaleX():表示只在垂直方向(Y轴)改变大小
- scaleY():表示只在垂直方向(Y轴)改变大小
- skew():包含两个参数值,分别表示X轴和Y轴倾斜的角度,如果第二个参数为空,则默认为0,参数为负表示向相反方向倾斜,也可以使用如下替代函数:
- skewX():表示只在水平方向(X轴)倾斜
- skewY():表示只在垂直方向(Y轴)倾斜
- matrix():使用 3 * 3 的矩阵来表示旋转,缩放,移动(平移)和倾斜功能
这里一个个来看看(这里的例子都有两个相同大小的 div,一个保持原状作为参照物,一个进行转换):
(1)translate()
<!DOCTYPE html>
上面的代码使得 exdiv 向右移动 50px,向下移动 100px。
(2)rotate()
仍然使用上面的样例,仅仅更改转换的函数:
transform
上面的代码将 exdiv 顺时针旋转了 60°。
(3)scale()
transform
上面的代码使得 exdiv 的宽度不变,而高度转换为原来的3倍,当然这里为了有个参照,我把 div 的透明度调整了一下,这里正好插入 CSS 3 透明度调整的属性 opacity,完整 CSS 代码如下:
div
opacity 也可以调整图像的透明度,所以很好用——不过不值得单独开一章节来介绍,所以放在这里明白怎么用就好
(4)skew()
因为这个比起 skewX() 和 skewY() 用的更多,所以后两个单独的函数就不演示了,我们直接来看这个简写函数:
transform
上面的代码使得 exdiv 在水平轴和垂直轴上分别顺时针倾斜了 20°。
(5)matrix()
因为这个简写的方法参数比较多,由于参数实际上使用的不是之前提及的度数单位,也导致我个人不怎么会实际使用,其格式如下:
transform
上面伸缩、倾斜以及位移的关键字都算是很好分辨的,但是旋转是怎么得来的?
看了一下MDN,原来是笛卡尔坐标!也就是说,旋转和倾斜,其实都要涉及到相对复杂的三角函数计算:
旋转角度 = matrix(cosθ, sinθ, -sinθ, cosθ)
结合矩阵公式,是这样计算的:
x' = x * cosθ- y *sinθ+0 = x * cosθ- y * sinθ
y' = x * sinθ+ y * cosθ+0 = x * sinθ+ y * cosθ
比如如果只要旋转60°,要这样设置样式(其实也就是倾斜 + 伸缩):
transform
同样,如果需要设置倾斜,也是三角函数打遍天下:
倾斜角度 = matrix(1, tan(θy), tan(θx), 1, 0, 0)
结合矩阵公式,是这样计算的:
x' = x+ y*tan(θx) + 0 = x + y * tan(θx)
y' = x* tan(θy) + y + 0 = x * tan(θy) + y
应用起来如下:
transform
上面的代码使得 exdiv 倾斜了60°,并向右下方移动了 80px。
这么复杂的函数,也只适用于复杂的应用场景,如果仅仅是普通的转换,我真的建议就用前面理解起来相对简单的函数了。如果对矩阵了解的比较透彻,那这其实是个功能非常强大的函数。
2.2 转换属性
除了 transform 属性之外,其实 CSS 3 还有一些相关属性,是用来定义转换基础或者转换后特性的,包括有:
- transform-origin:允许更改转化元素位置
- transform-style:3D空间中的指定如何嵌套元素
- perspective:指定3D元素是如何查看透视图
- perspective-origin:指定3D元素底部位置
- backface-visibility:定义一个元素不面向屏幕时,是否应该是可见
其中我自己比较常用的是 perspective 以及 perspective-origin,因为在做3D转换时,需要有个参照物来对比最后得到的效果是不是自己想要的。
2.3 3D转换
其实3D转换就是在2D转换的基础上增加了一个Z轴,即将屏幕想象成是有厚度的,在三个轴上面做各种转换,包括旋转、缩放和移动,除了上面的2D转换函数外,还增加了如下函数:
- translate3d(x, y, z):定义 3D 移动
- translateZ():表示只在Z轴移动
- scale3d(x, y, z):定义 3D 缩放
- scaleZ():表示只在Z轴缩放
- rotate3d(x, y, z, angle):定义 3D 旋转
- rotateX():表示只在水平方向(X轴)旋转
- rotateY():表示只在垂直方向(Y轴)旋转
- rotateZ():表示只在Z轴旋转,等同于 rotate()
- matrix3d():使用 4 * 4 矩阵来定义3D转换
下面是个例子:
<!DOCTYPE html>
上面的代码比较容易懂,就不详细解释了,不过因为 perspective 和 perspective-origin 没有完整部署在 Chrome 以及 Chromium 浏览器当中的缘故,需要添加 -webkit- 前缀,这点需要留意。
3D转换的效果就不特别演示了,因为的确不太好看懂,还是自己亲眼看到动起来的元素,会比较容易理解,所以下面是一个比较完整和稍微复杂一点的演示样例,大家可以接下来自己试一试效果:
<!DOCTYPE html>
鼠标悬浮在对应元素上,就可以看到对应的效果了,值得一试。