CSS学习笔记(八)

视口

视觉视口

visual viewport

移动端的可视视口。(即移动端的可视区域)

布局视口

layout viewport

布局视口是相对于移动端的定义,由meta标签来决定。

1
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

移动端设备的视口相对于浏览器小,我们在一个网页html页面设置一个宽高均为100px的盒子,在浏览器使用终端切换到移动端,并任意切换移动端的宽度值,在没有以上代码的情况下,这个盒子也会进行一定缩放(违背常理)

原因:

  • 在没有设置 时,布局视口的默认宽度为980px(当然移动端设备通常没有980px,且比980px小),在用户进行页面布局时,为了将页面完整的显示在移动端的设备中,会将980px宽度刚好全部放入移动端的视觉视口(对这个页面进行缩小),同时盒子的宽高进行同比例的缩放。
  • 布局视口的默认宽度为980px

设置布局视口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<meta name="viewport" content="width=200px">

<style>
* {
margin: 0;
padding: 0;
}

div {
height: 100px;
width: 100px;
background-color: pink;
}
</style>

<body>
<div></div>
</body>

呈现效果如下:刚好占据一半,布局视口小于384px,为了将页面整个放入移动端,此时会进行放大,然后放入视觉视口,盒子的宽度为100px,占据视觉视口200px的一半,所以看上去就占据了移动端一半的宽度。

呈现效果

理想视口

ideal viewport

但是,由于移动端设备种类繁多,所以布局视口的宽度默认设置为当前移动设备的可视视口

即:

1
<meta name="viewport" content="width=device-width">

当视觉视口和布局视口的宽度一致时,称为理想视口。

meta的其他属性

meta的其他属性

这些属性都属于name=’viewport’,在设置多个不同的值时,在content里用”,”或者”;”隔开。

有些浏览器不支持user-scalable属性,在开发者想禁用缩放时,可以如下设置:

1
<meta name="viewport" content="width=device-width, maximum-scale=1.0, minimum-scale=1.0">

移动端适配

百分比设置

  • 因为不同属性的百分比值,相对的可能是不同参照物,所以百分比往往很难统一;
  • 所以百分比在移动端适配中使用是非常少的;

rem单位+动态html的font-size

rem是针对于根元素(html/:root)的字体大小作为依据的,1rem就是html字体大小的一倍,以此类推。

区分于em,em是相对于当前盒子本身字体大小的作为依据,1em就是当前字体大小的1倍,以此类推。

如果我们需要在不同的屏幕下有不同的尺寸,可动态修改html的font-size尺寸,配合rem来进行适配。

媒体查询

现有如下案例:

案例

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<style>
@media screen and (min-width:375px) {
html {
font-size: 37.5px;
}
}

@media screen and (min-width:320px) {
html {
font-size: 32px;
}
}

@media screen and (min-width:417px) {
html {
font-size: 41.4px;
}
}

div {
width: 1rem;
height: 1rem;
background-color: red;
}
</style>

<body>
<div>

</div>
</body>

可以通过媒体查询来设置不同尺寸范围内的屏幕html的font-size尺寸;

缺点:

  • 1.我们需要针对不同的屏幕编写大量的媒体查询;
  • 2.如果动态改变尺寸,不会实时的进行更新(在一定的范围内尺寸不会发生变化)。

js实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// test.js 
function setRemUnit() {
// html根
let htmlEl = document.documentElement;
// 获得客户端宽度
let clientWidth = htmlEl.clientWidth;
// 动态计算根字体大小,(此处为屏幕宽度的十分之一)
const rootFontSize = clientWidth / 10 + 'px';
htmlEl.style.fontSize = rootFontSize;
}
// 页面加载完成就要调用
setRemUnit()
window.addEventListener('resize', setRemUnit);
// 用于监听移动端的页面跳转(页面的大小可能会有变化,但是如果浏览器有缓存,就会造成新页面的布局出现问题,所以需要重新计算rem)
window.addEventListener('pageshow', function (e) {
// 表示页面有缓存
if (e.persisted) {
setRemUnit()
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.test-box {
width: 5rem;
height: 10rem;
background-color: red;
}
</style>
</head>
<body>
<script src='./test.js'></script>
<div>测试测试测试测试测试测试</div>
<div class="test-box">测试盒子</div>
</body>
</html>

此处字体大小也会发生变化,继承了html根元素的字体大小

参考:https://github.com/amfe/lib-flexible

由于viewport单位(vw和vh)得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方。

vw单位

vw是相对于可视区的宽度的百分比。

使用vw可以替换rem,但是vw也有一定的弊端:

  • vw一定是相对于视口的;
  • 在某些场景下,我们想要有一个最值,即:屏幕宽度达到一个最大值,页面的元素不要再变大了;
  • 在rem的情况下,可以使用媒体查询来限制继续放大;
  • 使用vw放大不能停止放大。

rem事实上是作为一种移动端适配的一种过度方案,利用的也是vw的思想。

vw相比于rem的优势:

  • 优势一:不需要去计算html的font-size大小,也不需要给html设置这样一会font-size;
  • 优势二:不会因为设置html的font-size大小,而必须给body再设置一个font-size,防止继承;
    • 因为rem会给根html设置一个字体大小,其所有的子元素如果没有设置字体大小都会继承html的字体(很大),所以使用rem方法时,会在body重新设置一个字体,使其子元素的字体大小继承于body
  • 优势三∶因为不依赖font-size的尺寸,所以不用担心某些原因html的font-size尺寸被篡改,页面尺寸混乱;
  • 优势四: vw相比于rem更加语义化,1vw刚才是1/100的viewport的大小;
  • 优势五:可以具备rem之前所有的优点;

flex弹性布局