Featured image of post 第二章 移动 Web 开发基础(上)

第二章 移动 Web 开发基础(上)

视口

什么是视口

视口(Viewport)是移动 Web 开发中一个非常重要的概念,最早由苹果公司为 iOS 系统的 Safari 浏览器引入,其目的是让 iPhone 的小屏幕尽可能完整地显示整个网页。通过设置视口,不管网页原始的分辨率有多大,都能将其缩小显示在手机浏览器上,这样保证网页在手机上看起来更像在桌面浏览器中的样子。

简单来说, 视口就是浏览器显示页面内容的区域 。在移动端浏览器中,存在着3种视口,分别是布局视口(Layout Viewport)、视觉视口(Visual Viewport)和理想视口(Ideal Viewport)。

布局视口

布局视口是指浏览器绘制网页的视口,一般移动端浏览器都默认设置了布局视口的宽度。根据设备的不同,布局视口的默认宽度有可能是 980px 或1024px等,这个宽度并不适合在手机屏幕中展示。移动端浏览器之所以采用这样的默认设置,是为了解决早期的 PC 端页面在手机上显示的问题。

当移动端浏览器展示PC端网页内容时,由于移动端设备屏幕比较小,不能像PC端浏览器那样完美地展示网页,这是布局视口比设备屏幕宽造成的。这样的网页在手机的浏览器中会出现左右滚动条,用户需要左右滑动才能查看完整的一行内容。

视觉视口

视觉视口是指用户所看到的网站的区域,这个区域的宽度等同于移动设备的浏览器窗口的宽度。

需要注意的是,当在手机上缩放网页时,操作的是视觉视口,而布局视口仍然保持原来的宽度。

理想视口

理想视口是指对设备来讲最理想的视口。采用理想视口的方式,可以使网页在移动端浏览器上获得最理想的浏览和阅读的宽度。在理想视口情况下, 布局视口的宽度和屏幕宽度是一致的 ,这样就不需要左右滑动页面了。在开发中,为了实现理想视口,需要为移动端页面添加 标签来配置视口,通知浏览器来进行处理。

利用 < meta > 标签设置视口

在传统的 PC 端网页开发中,并没有使用过 < meta > 标签来设置视口,此时浏览器会按照默认的布局视口宽度来显示网页。如果希望自己开发的网页在浏览器中以理想视口的形式呈现,就需要利用 < meta > 标签设置视口。

在 < meta > 标签中,将 name 属性设为 viewport,即可设置视口,示例代码如下。

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

视口的常用设置

在使用 < meta > 标签设置视口时,可以在 content 属性中添加一些参数,格式为 “参数名 = 参数值”,多个参数用 “,” 分开。以前面演示过的 “width=device-width” 为例,width 就是参数名,device-width 是参数值。

参数名 说明
width 设置视口宽度,可以设为正整数(像素)或特殊值 device-width
height 设置视口高度,可以设为正整数(像素)或特殊值 device-height
initial-scale 初始缩放比,取值范围为 0.0 ~ 10.0
maximum-scale 最大缩放比,取值范围为 0.0 ~ 10.0
minimum-scale 最小缩放比,取值范围为 0.0 ~ 10.0
user-scalable 用户是否可以缩放,其值为 yes 或 no

可以通过动态的改变缩放值 initial-scale 来进行适配。

这种方式虽然能够解决适配问题,但也会过于简单粗暴,主要有以下两个问题:

	1. 全局缩放,把不需要缩放的也影响了;

	2. 如果有第三方 UI 库,会影响了第三方库的显示效果;

rem 适配

rem(font size of the root element)是指相对于根元素的字体大小的单位,简单的说它就是一个相对单位;em(font size of the element)指相对于父元素的字体大小的单位。它们之间其实很相似,只不过一个计算的规则是依赖根元素一个是依赖父元素计算。

移动端H5开发之页面适配篇-腾讯云开发者社区-腾讯云 (tencent.com)

 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
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html {
            font-size: 100px;
        }
        p {
            font-size: 1rem;
            /* 100px */
        }
    </style>
</head>

<body>
    <p>rem布局下的p标签</p>
    <script>
        (function (window, html) {
            // 规定默认的设计稿宽度720px
            const designWidth = 1080;
            function recalc() {
                const windowWidth = html.clientWidth < designWidth ? html.clientWidth : designWidth;
                // *100 之后,则样式中rem的值就需要相应的缩小100倍
                // 即:设计稿中的20px,在样式中就要写成0.2rem
                const fontSize = windowWidth / designWidth * 100;
                setFontSize(fontSize);
            }
            function setFontSize(fontSize) {
                html.style.fontSize = `${fontSize}px`;
            }
            // 监听resize
            window.addEventListener('resize', recalc);
            recalc();
        }(window, document.documentElement));
    </script>
</body>

</html>
 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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html{
            /* 100vw    375px */
            /*   a      100px */
            font-size: 26.66667vw;
        }
        .box{
            /* 相对于 html 的 font-size */
            font-size: 0.16rem;    /* 此时 1 rem 相当于 100 px */
            position: absolute;
            top: 5%;
            left: 50%;
            /* 往上(x轴)、左(y轴)移动自身长宽的 50%,以使其居于中心位置。 */
            transform: translate(-50%, -50%);
            text-align: center;
            box-sizing: border-box;
            padding: 3px 0;
        }
    </style>
</head>
<body>
    <div class="box">这是一个div标签</div>
</body>
</html>

移动 Web 样式的编写

利用 Normalize.css 初始化默认样式

在开发中,为了确保不同浏览器的默认样式统一,通常会对样式进行初始化,也就是在页面中定义一些初始样式,用来覆盖浏览器的默认样式。

Normalize.IO · GitHub

normalize.github.io/index.css at master · normalize/normalize.github.io · GitHub

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="/Bootstrap/normalize.css">
</head>
<body>
    <div>引入 Normalize.css</div>
</body>
</html>

设置 box-sizing 为 border-box

在 CSS3 中,通过 box-sizing 属性可以更改盒子尺寸的计算方式。将 box-sizing 设为 content-box(默认值)时,表示使用传统的计算方式;设为 border-box 时,表示使用 CSS3 的一种新的计算方式,通过这种方式可以解决传统盒子在添加了边框和内边距后,盒子被撑大的问题。示例代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 传统计算方式(标准盒子、内容盒子、W3C盒子)

box-sizing: content-box;

// 使用 content-box 计算方式的盒子模型,其宽度的计算公式如下。
// 盒子的宽度 = css 中设置的 width + border(left+right) + padding(left+right)
// 盒子的高度 = css 中设置的 height + border(top+buttom) + padding(top+buttom)

-------------------------------------------------------------------------

// 新的计算方式(IE盒子、边框盒子、怪异盒子)

box-sizing: border-box;

// 使用 border-box 计算方式的盒子模型,其宽度的计算公式如下。
// 盒子的宽度 = css 中设置的 width
// 盒子的高度 = css 中设置的 height
 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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            padding: 20px;
            background-color: paleturquoise;
        }
        .b1{
            border: 10px solid black;
            box-sizing: content-box;
            margin: 10px 10px;
        }
        .b2{
            border: 10px solid rgb(0, 0, 0);
            box-sizing: border-box;
            margin: 10px 10px;
        }
    </style>
</head>
<body>
    <div class="b1">content-box</div>
    <div class="b2">border-box</div>
</body>
</html>

设置移动端的特殊样式

在实际开发中,移动 Web 页面的设计风格更接近 APP(手机应用),而不是传统的网页。为了有更好的用户体验,可以给移动 Web 页面设置一些特殊样式。

样式 说明
-webkit-tap-highlight-color: transparent; 去除超链接按下时默认的高亮效果(设为透明)
-webkit-appearance: none; 去除按钮的原生样式
-webkit-touch-callout: none; 禁止长按页面时弹出菜单
-webkit-user-select: none; 禁止文本被手动选择

需要注意的是,上述样式是非标准的,因此加上了私有前缀 “-webkit-",该前缀在 WebKit 和 Blink 内核的浏览器中有效,适用于 Chrome 浏览器和大多数移动端浏览器。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        a{
            -webkit-tap-highlight-color: transparent;
        }
        button{
            -webkit-appearance: none;
        }
        p{
            -webkit-user-select: none;
        }
    </style>
</head>
<body>
    <a href="https://www.baidu.com/">百度官网</a>
    <button>点一下</button>
    <p>文本被禁止选中了</p>
</body>
</html>

分辨率和设备像素比

分辨率

① 屏幕分辨率 屏幕分辨率( 物理分辨率 )是指一个屏幕上可以显示多少信息,通常以像素(px)为单位来衡量。例如,1920 × 1080px 表示水平方向含有1920,垂直方向含有1080,将两者相乘可知,屏幕上总共有2073600px。

在屏幕的大小相同的情况下,如果屏幕的分辨率低(如 640 × 480px ),则屏幕上显示的像素少,单个像素点比较大,看起来会有种颗粒感;如果屏幕的分辨率高(如 1920 × 1080px),则屏幕上显示的像素多,单个像素点比较小,看起来会比较清晰。

② 图像分辨率 在同一台设备上,图片的像素点和屏幕的像素点通常是一一对应的。图片的分辨率越高,图片越清晰;图片的分辨率越低,图片越模糊。

在屏幕上把图片放大时,会发现图片在屏幕上显示的像素也变大,这是因为软件通过算法对图像进行了像素补充,虽然图片本身的像素没有变,但是在显示时已经补充了很多个屏幕像素( 逻辑分辨率 );同理,把图片缩小时,也是通过算法减少了显示的图片像素。

前端页面往往参考 逻辑分辨率 进行开发。

二倍图

为了 防止图片在高分辨率屏幕下模糊失真 ,在设计页面时往往使用更高分辨率的图片,保证图片的原有清晰度。目前二倍图以 iPhone 6/7/8 分辨率为标准,即 375 × 667px 。

在实际开发中,除了设置二倍图外,还可以设置成三倍图、四倍图等。其实现思路都是相同的,可根据项目的实际需要来设置。

背景图片的缩放

在开发中,除了使用插入的图片,还会用到背景图片,所以背景图片也需要设置缩放效果。在CSS3中,提供了 background-size 属性来规定背景图片的尺寸,从而达到背景图片的缩放效果。

1
background-size: 背景图片的宽度 背景图片的高度;

background-size 设置的宽度和高度可以是像素或百分比。除此之外,background-size还可以用其他的属性值来实现不同的缩放效果。

属性值 说明
cover 把背景图像扩展至足够大,以使背景图像完全覆盖背景区域
contain 把背景图像扩展至最大尺寸,以使其宽度和高度完全适应内容区域
 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
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        /* body{
            background-image: url(/MyPra/img/gravel.jpg);
        } */
        div{
            width: 800px;
            height: 600px;
            border: 2px solid black;
            background: url(/MyPra/img/icon.jpg) no-repeat;
            margin: 10px 0;
        }
        .d1{
            width: 256px;
            height: 256px;
            border: 2px solid rgb(255, 0, 0);
            background: url(/MyPra/img/icon.jpg) no-repeat; 
        }
        .d2{
            width: 256px;
            height: 256px;
            border: 2px solid rgb(255, 0, 0);
            background: url(/MyPra/img/icon.jpg) no-repeat; 
            background-size: 256px;
        }
    </style>
</head>
<body>
    <div style="background-size: cover;"></div>
    <div style="background-size: contain;"></div>
    <div style="background-size: 800px;"></div>
    <div style="background-size: 50%;"></div>
    <div class="d1"></div>
    <div class="d2"></div>
</body>
</html>

SVG 矢量图

什么是 SVG

矢量图是根据几何特性来绘制图形,矢量可以是一个点或一条线,矢量图只能靠软件生成。可缩放矢量图形(Scalable Vector Graphics,SVG)是一种开放标准的描述矢量图形的语言,它基于 XML(extensible Markup Language,可扩展标记语言)。在 2003 年 1 月,SVG 1.1 被确立为 W3C 标准。与其他图像格式相比,使用 SVG 的优势如下。

  • SVG 可被非常多的工具读取和修改(如记事本)。
  • SVG 与 JPEG、GIF 图像相比, 文件体积更小 ,且 可压缩性更强
  • SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)。
  • SVG 是开放的标准。
  • SVG 文件是用 XML 编写的。
  • SVG 矢量图形 可伸缩 ,可在任何的分辨率下被高质量地打印,可在 图像质量不下降 的情况下被放大。

< svg > 标签和样式

属性 说明
width 用来控制 SVG 视图的宽度
height 用来控制 SVG 视图的高度
viewBox 定义用户视野的位置和大小

viewBox 可以定义用来观察 SVG 视图的一个矩形区域,它的属性主要包括 x、y、width、height,用数字表示,每个数字之间用空格或逗号隔开,表示定义一个在左上角(x , y)坐标位置且宽度为 width、高度为 height 的矩形。

在 < svg > 标签的内部,可以使用 SVG 提供的一些预定义的标签来绘制图形,或者绘制文字。常用的内部标签如下表所示。

标签名 说明
< rect > 矩形标签
< ellipse > 椭圆形标签
< circle > 圆形标签
< line > 线段标签
< polyline > 折线标签
< polygon > 多边形标签
< path > 路径标签
< lext > 文字标签
< tspan > 类似 < span > ,用在 < text > 内部单独设置样式

上述标签还可以通过属性来设置样式。

属性名 属性值 说明
fill String 定义填充颜色和文字颜色
fill-opacity 0 ~ 1 之间的浮点数 定义填充颜色的透明度
stroke String 定义描边的颜色
stroke-width 大于 0 的浮点数 定义描边的宽度
stroke-opacity 0 ~ 1 之间的浮点数 定义描边的颜色的透明度
opacity 0 ~1 之间的浮点数 定义整个图形元素的透明度
transform translate(x,y) 平移
transform scale(x,y) 缩放
transform rotate(angle, [cx,cy]) 旋转
transform skewX(angel) skewY(angel) 倾斜
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            height: 900px;
        }
    </style>
</head>
<body>
    <svg width="100%" height="100%">
        <circle cx="50" cy="50" r="40" stroke="black" stroke-width="2px" fill="pink"></circle>
        <rect width="80px" height="80px" stroke="black" stroke-width="2px" fill="pink" transform="translate(100,100)" fill-opacity="20%"></rect>
    </svg>
</body>
</html>

练习

填空题

  1. 视口分为( )。

  2. 视口通过( )标签来设置。

  3. 初始化移动端默认样式使用的库是( )。

  4. background-size 中把背景图片扩展至足够大使背景图像完全覆盖背景区域的属性值是( )。

  5. background-size 中的高度可以省略( )。

  6. 布局视口是对设备来讲最理想的视口( )。

  7. 在开发的时候用到的 1 px 一定就等于 1 个物理像素( )。

  8. 在同一台设备上,图片的像素点和屏幕的像素点是一一对应的。如果图片分辨率越高,图片越模糊;图片分辨率越低,图片越清晰( )。

  9. SVG的含义为可缩放矢量图形( )。

选择题

  1. 下列选项中,用来设置盒子模型 border-box 计算方式的属性是( )。

    • A. box-sizing

    • B. box

    • C. boder-sizing

    • D. box-size

  2. 下列选项中,属于Chrome浏览器的内核的是( )。

    • A. Blink

    • B. WebKit

    • C. Presto

    • D. Gecko

  3. 下列选项中,用来定义矩形的标签是( )。

    • A. < circle >

    • B. < rect >

    • C. < line >

    • D. < polygon >

  4. 下列选项中,能够清除 < a > 标签单击时高亮效果的是( )。

    • A. -webkit-tap-highlight-color

    • B. -webkit-appearance

    • C. -webkit-touch-callout

    • D. -webkit-tap-highlight-callout

  5. 下列选项中,用来设置视口初始缩放比的是( )。

    • ​A. initial-scale

    • B. maximum-scale

    • C. minimum-scale

    • D. user-scalable

编程题

  1. 仿照百度热搜,编写页面。
  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
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .main-box {
            position: absolute;
            top: 30%;
            left: 50%;
            /* 往上(x轴)、左(y轴)移动自身长宽的 50%,以使其居于中心位置。 */
            transform: translate(-50%, -50%);
        }

        img {
            width: 101px;
            height: 33px;
            margin-bottom: -2.5px;
        }

        ul {
            list-style: none;
        }
        .list{
            height: 30px;
            padding: 5px 0;
            box-sizing: border-box;
        }
        a{
            -webkit-tap-highlight-color: transparent;
            text-decoration: none;
            color: rgb(48, 80, 221);
            font-size: 16px;
        }
        a:hover{
            color: red;
            text-decoration: underline;
        }
        h2:hover{
            color: #5193f5;
            cursor: pointer;
        }
        #s0, #s1{
            color: rgb(255, 0, 0);
        }
        #s2{
            color: rgb(255, 60, 0);
        }
        #s3{
            color: rgb(255, 102, 0);
        }
        span{
            border-radius: 50%;
            width: 20px;
            height: 20px;
            color: rgb(112, 94, 94);
            margin-right: 10px;
            font-size: 16px;
        }
    </style>
</head>

<body>
    <div class="main-box">
        <div class="title"><img src="/MyPra/img/baidu.png" alt="">
            <h2>百度热搜 ></h2>
        </div>
        <div class="list">
            <div class="news"><span id="s0">#</span><a href="#">风好正是扬帆时</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span id="s1">1</span><a href="#">住建部:防止房地产市场大起大落热</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span id="s3">2</span><a href="#">美国共产主义者宣布成立政党</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span id="s3">3</span><a href="#">2024年全国两会新闻中心启用</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span>4</span><a href="#">上海到北京仅需2.5小时</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span>5</span><a href="#">爆火的秦岭隧道视频系拼接 作者道歉</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span>6</span><a href="#">贵州省长:全面清理拖欠企业账款</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span>7</span><a href="#">理想市值一天涨了1个小鹏</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span>8</span><a href="#">#张雪峰称想出国读书先看这本书#</a></div class="news">
        </div>
        <div class="list">
            <div class="news"><span>9</span><a href="#">河南多地发生山火?</a></div>
        </div>
    </div>
</body>

</html>
Blog for Sandy Memories