# 移动 WebApp 项目开发常用技术及标准、规范和最佳实践
在项目实战开始前,我们先来学习以下三方面知识
- 移动端与 PC 端有哪些不同 ?
- 移动端常见的布局处理技术有哪些 ?
- 移动设计稿的标准与规范 ?
# 1、移动端与 PC 端有哪些不同?
TIP
在上一章节,我们讲过,移动端与 PC 端有以下 4 点大的区别
- 屏幕大小不同
- 交互方式不同
- 网络环境和设备性能不同
- 兼容性不同
因为屏幕大小的不同,所以造成我们在实际的移动端布局时,不能和 PC 端一样采用固定大小来布局,而需要自适应屏幕的宽。
移动端屏幕的常见可视区大小为320-480px
之间,也就意味着我们在实际开发代码时,我们的页面宽在320-480px
之间。
所以移动端开发,元素的宽肯定不能用 px 绝对定位写死,我们得采用相对单位来做开发。
不同手机的详细配置,可点击查看详细参数 (opens new window) 👆
# 2、移动端常见的布局处理技术
移动端常见的 5 种布局技术如下:
- 流体布局
- rem 和 vw 布局
- 响应式布局
- Flex 弹性布局(工具)
- Grid 网格布局(工具)
其中的流体布局、rem/vw 布局、响应式布局是可以独立实现移动端页面的开发
Flex 弹性和 Grid 网格布局,并不能独立实现移动端布局的开发,他们更像是工具,配合流体布局、rem/vw 布局、响应式布局来实现移动端页面的开发。
具体的每一种技术,我们会通过一个个单独的项目来讲解。
# 3、移动设计稿的标准与规范
TIP
在学习具体的项目开发前,我们来了解下移动开发的设计稿设计标准和规范,这样就更有利于我们后期在开发时的尺寸测量和取色。
我们以京东的移动端设计稿的标准与规范来和大家讲解
注:
详细的规范标准,在钉钉群文件中 京东视觉规范.pdf ,或联系助理老师获取。
接下来我们学习移动 WebApp 开发布局技术中的流体布局。
# 一、流体布局
TIP
所谓的流体布局,也叫百分比%布局,本质上就是通过 %(百分比)和 怪异盒子模型结合来实现元素的宽相对视口缩放。
接下来我们就利用流体布局来实现以下效果图的页面开发
# 1、搭建本项目的目录结构
TIP
- 首先新建项目文件夹 WebApp
- 在 WebApp 中新建 css、js、images 文件夹,分别用来存放 CSS、JS 文件和图片内容
- 在 CSS 中新建 reset.css、global.css、index.css 文件,分别用来存放重置默认样式、全局通用样式,首页样式
reset.css 样式文件的内容
可参考博客:标签默认博客地址 (opens new window) 👆 中如下截图内容
其它相关重要的重置样式介绍
/* 去掉点击的高亮显示效果 */
-webkit-tap-highlight-color: transparent;
/* 在移动端浏览器默认的外观在ios上加上这个属性才能给按扭和输入框自定义样式 */
-webkit-appearance: none;
/* 禁用长按页面时的弹出菜单 */
img,
a {
-webkit-touch-callout: none;
}
/* 表单会有外轮廓 */
input {
outline: none;
}
/* 去掉图片下面的空隙 */
vertical-align: top;
注:
建议在一开始学习时,不要引用 reset.css 文件,这样就可以在学习过程中把所有问题暴露,对于为什么要重置这个默认样式,会有更深的理解。
在实际开发中,我们直接引用 reset.css 文件就好。
进到蓝湖,打开设计稿,点击设计稿,按以下截图操作,下载所有切图,然后放到 images 文件夹,修改好名字。
# 2、了解设计稿的整体标准和规范
TIP
设计稿采用的标准色(如下图)
字体大小、行间距、字体颜色、字体类型
- 字体大小(12px、14px、16px)
- 行间距为字体大小的 1.5 倍
- 字体类型,以微软雅黑为主,数字是 Arial 类型
- 字体颜色主要以 #101010 黑色为主
通过以上数据最后得到如下代码,添加到 global.css 文件中
font: 12px/1.5 Microsoft YaHei;
color: #101010;
具体的设计标准,每个公司都有自己的规范,在实际开发中,以公司规范为主。
# 3、新建 index.html 网页,进行首页开发
TIP
- 在当前根目录下新建 index.html 网页
- 做好 viewport 视口配置
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
- 引用相关的 CSS 文件,注意引入文件的顺序
/* 重置样式 */
css代码...
/* 网站通用布局 */
css代码...
/* 通用模块 */
css代码...
/* 通用元件 */
css代码...
/* 通用响应式系统 */
css代码...
<link rel="stylesheet" href="./css/reset.css">
<link rel="stylesheet" href="./css/global.css" />
<link rel="stylesheet" href="./css/index.css" />
# 4、网站整体(html)结构划分
TIP
通过对整个设计稿页面的分析,我们可以用 html 来将整个页面划分成以下几个部分
<!-- header start -->
<header class="header"></header>
<!-- end header-->
<!-- menu start-->
<nav class="menu"></nav>
<!-- end menu -->
<!-- main start -->
<main class="main">
<!-- cheap start-->
<section class="cheap"></section>
<!-- end start-->
<!-- recommend start -->
<section class="recommend"></section>
<!-- end recommend -->
<!-- product-category start -->
<section class="product-category"></section>
<!-- end product-category -->
</main>
<!-- end main -->
<!-- tabbar start -->
<footer class="tabbar"></footer>
<!-- end tabbar -->
# 5、每个版块开发
TIP
本次项目我们采用的是流体布局(%百分比 + 怪异盒子模型布局),所以整个页面中会用到的所有元素,在最开始都需要设置为怪异盒子模型 。
由于一开始,我们并不清楚,页面可能会用到那些 html 元素,所以我们一开始可以用*
来处理,等页面开发完,再把*
换成对应的 html 标签。
* {
/* 怪异盒子模型 ,不过在移动端开发,我们一般会以怪异盒子模型为主 */
box-sizing: border-box;
}
页面开发完,把*
替换页面用到的 html 元素
ul,
li,
div,
p,
a,
span,
i,
input,
img {
/* 怪异盒子模型 */
box-sizing: border-box;
}
# 6、iOS 下 tabbar 底部留白与黑线遮挡问题
TIP
要解决 IOS 下 tabbar 底部留白问题,我们需要先了解两个概念,安全区域和刘海区
我们来看一个简单的案例,代码如下:
<style>
html,
body {
margin: 0;
}
.tabbar {
width: 100%;
height: 100px;
background-color: red;
position: fixed;
z-index: 222;
bottom: 0;
}
</style>
<body>
<footer class="tabbar"></footer>
</body>
以上代码显示效果如下:
页面默认填宽的是安全区域的高度,并不包括刘海区
那如何让页面高度填充到刘海区呢?
- 在
viewport
中添加viewport-fit=cover
<meta
name="viewport"
content="width=device-width,viewport-fit=cover,initial-scale=1.0"
/>
- 高度填充到刘海区后,tabbar 的内容就会被底下的黑线给遮挡一小部分。
如何解决底部被黑线遮挡问题 ?
我们只需要给 tabbar 加下如下代码
方法一:
添加以下代码的元素,不能是怪异盒子模型,否则元素自身高度会减少
/* 兼容 IOS<11.2 */
padding-bottom: constant(safe-area-inset-bottom);
/* 兼容 IOS>11.2 */
padding-bottom: env(safe-area-inset-bottom);
方法二:
100px 是 tabbar 原来的高度
/* 兼容 IOS>11.2 */
height: calc(50px+ constant(safe-area-inset-bottom));
/* 兼容 IOS>11.2 */
height: calc(50px + env(safe-area-inset-bottom));
在实际开发中,我们一般是先 constant,再 env
针对其它一些机型,不支持上面两种写法的,可以选择用 CSS 的@supports
@supports not (constant(safe-area-inset-bottom)) {
.tabbar {
padding-bottom: 30px;
}
}
# 7、流体布局的布局思路与缺陷
(1) 流体布局思路
通过计算每个子元素占容器的比例,来平分父容器的整体大小。
所有子元素宽的百分比% 加起来要等于 100%。
然后通过给子元素设置对应的内边距来实现元素间的空隙。
为了保证给子元素添加内边距实现空隙时,不会造成元素宽度变宽,所有元素都设为
box-sizing: border-box
;
(2) 流体布局缺陷
- 只能实现图片和容器的宽高等比缩放,没有办法实现间距,字体大小的等比缩放
- 如果想实现对应的字体和间距在不同尺寸下,有所变化,可以与
@media
媒体询结合来实现微调。
# 二、移动端 rem 布局原理
TIP
在学习 rem 布局前,首先我们先来学习 rem 适配的原理
# 1、rem 实现适配的原理
TIP
假设我们现在要实现 750 * 400
px 的 div,在 750px 宽的设备下,改用 rem 单位实现等比展现,那我们的 css 代码如何写呢 ?
假设此时1rem = 10px
,则对应 CSS 样式如下:
div {
/* 相当于将整个页面分成 75份 每一份大小为10px */
width: 75rem;
height: 40rem;
}
如果以上 CSS 代码不变(将页面分成 75 份),要实现在不同大小屏幕上能等比缩放,我们来看下,对应的 rem 要设置为多少?
设备可视宽 | 750px | 375px | 540px |
---|---|---|---|
1rem 大小 | 10px | 5px | 7.2px |
通过上面的表格,我们知道,要计算不同设备下对应 1rem 的大小,我们需要思考将整个页面分成多少份。
然后通过公式:1rem= 设备可视宽 / 对应份数。
假设我们现在将页面分成10 份,那不同设备下1rem
的大小具体如下表
设备可视宽 | 750px | 375px | 540px |
---|---|---|---|
1rem 大小 | 75px | 37.5px | 54px |
所以我们要用 rem 来开发移动端之前,需要思考,先将页面分成多少份?然后通过以下公式
- 1rem = 设备可视宽 / 对应份数
- 得到不同设备下 1rem 的大小
在实际开发中,不同尺寸的手机屏幕下 1rem 的大小,是通过 js 来动态获取当前设备可视宽 / 对应份数来实现
# 2、JS 动态实现不同设备下 1rem 的大小
TIP
1rem=(html)中 font-size 的大小,则我们只需要动态修改 html 的 font-size 的大小就可以
以下 js 代码,假设将页面分成 10 份来计算 font-size 大小的
<script>
// 页面初时化时调用
initPage();
function initPage() {
// 获取html元素
var html = document.documentElement;
// 获取屏幕可视区宽
var clientWidth = html.clientWidth;
// 动态设置html的font-size大小
html.style.fontSize = clientWidth / 10 + "px";
}
// 当窗口发生改变时调用
window.onresize = initPage;
</script>
# 3、px 单位如何转换为 rem
TIP
在实际开发的时候,我们是以 750px 的设计稿为标准来开发的
- 现在假设我将页面分成 10 份,那
1rem = 750px / 10 = 75px
- 那对应的 px 单位,转换成对应的 rem 单,计算公式:
?rem = 元素对应的px单位大小 / 1rem 大小
我们来看下面这个例子,在 750px 设计稿下对应的 px 单位大小
.box {
width: 750px;
height: 500px;
font-size: 20px;
padding: 10px;
background-color: red;
}
转换成 rem 单位, 就是用**px 单位 / 75 ** 得到
.box {
/* 750 * 75= 10 */
width: 10rem;
height: 6.666rem;
font-size: 0.2666rem;
padding: 0.1333rem;
background-color: red;
}
实际开发中我们并不会手动将
px
转换成对应rem
单位,我们会用vscode
的px to rem
插件来实现。
# 4、px to rem 插件使用
第一步:打开 Vscode,然后搜索 px to rem 插件,具体操作如下图
第二步:安装 px to rem 插件
第三步:参数配置
第四步:查看 px to rem 转换的快捷键
第五步:回到 html 页面,ctrl+A 选中所有 CSS 样式,然后按 Alt+Z,就会自动将 px 转成 rem 单位。
# 5、利用 rem 实现元素宽高等比缩放
TIP
- 将页面分成 10 份,通过 js 来实现不同视口下 1rem 的大小
- 利用 px to rem 插件,将 px 单位转换成对应 rem 单位
- px to rem 插件中,1rem 大小设置为 75 (以 750px 设计稿开发)
<style>
body {
margin: 0;
}
.box {
width: 9.3333rem;
height: 6.666rem;
font-size: 0.2666rem;
padding: 0.1333rem;
background-color: red;
}
</style>
<body>
<div class="box"></div>
<script>
// 页面初时化时调用
initPage();
function initPage() {
// 获取html元素
var html = document.documentElement;
// 获取屏幕可视区宽
var clientWidth = html.clientWidth;
// 动态设置html的font-size大小
html.style.fontSize = clientWidth / 10 + "px";
}
// 当窗口发生改变时调用
window.onresize = initPage;
</script>
</body>
# 6、总结:实际开发如何用 rem 做适配
TIP
在实际开发中,我们会按以下步骤来实现开发
1、要求设计师以 750px 宽,来设计移动端的设计稿;
2、我们按正常的 750px 的设计稿,以 px 单位来开发;
3、我们会假定将页面分成对应的份数,然后求得不同份数下的 1rem 的大小;
- 如果在 750px 设备下,将页面分成 75 份,则 html 的 font-size 大小=设备可视宽
(750) / 75 = 10px
- 如果在 750px 设备下,将页面分成 10 份,则 html 的 font-size 大小=设备可视宽
(750) / 10 = 75px
4、将 px 单位转换为对应的 rem 单位
- 将 px 像素转换 rem 单,公式:
?rem = px值 / 1rem大小
得到最对应 rem 单位值 - 我们并不会手动一个一个去计算,而是利用 vscode 中的插件
px to rem
一次搞定 - 假定将页面分成 75 份,那就把
px to rem
插件中对应 1rem 大小设为 10 - 假定将页面分成 10 份,那就把
px to rem
插件中对应 1rem 大小设为 75 - 最后切换到 CSS 代码,
ctrl+A
选中所有代码,然后Alt+Z
之后,就会自动把所有px
单位,转换成对应vw
单位。
在实际开发中,我们是以 750px 的设计稿来开发,假定将页面分成 10 份,每
1rem = 75px
# 三、rem 布局项目实战
TIP
接下来我们就利用 rem 布局来实现以下设计稿的开发,在 rem 中我们会结合之前学会的 flex 弹性布局一起来实现。
# 1、搭建本项目的目录结构
TIP
- 首先新建项目文件夹 WebApp
- 在 WebApp 中新建 css、js、images 文件夹,分别用来存放 CSS、JS 文件和图片内容
- 在 CSS 中新建 reset.css、global.css、index.css 文件,分别用来存放重置默认样式、全局通用样式,首页样式
reset.css 样式文件的内容
可参考博客:标签默认博客地址 (opens new window) 👆 中如下截图内容
其它相关重要的重置样式介绍
/* 去掉点击的高亮显示效果 */
-webkit-tap-highlight-color: transparent;
/* 在移动端浏览器默认的外观在ios上加上这个属性才能给按扭和输入框自定义样式 */
-webkit-appearance: none;
/* 禁用长按页面时的弹出菜单 */
img,
a {
-webkit-touch-callout: none;
}
/* 表单会有外轮廓 */
input {
outline: none;
}
/* 去掉图片下面的空隙 */
vertical-align: top;
注:
建议在一开始学习时,不要引用 reset.css 文件,这样就可以在学习过程中把所有问题暴露,对于为什么要重置这个默认样式,会有更深的理解。
在实际开发中,我们直接引用 reset.css 文件就好。
进到蓝湖,打开设计稿,点击设计稿,按以下截图操作,下载所有切图,然后放到 images 文件夹,修改好名字。
# 2、了解设计稿的整体标准与规范
字体大小、行间距、字体颜色、字体类型
- 字体大小(24px、28px、32px)
- 行间距为字体大小的 1.5 倍
- 字体类型,以微软雅黑为主,数字是 Arial 类型
- 字体颜色主要以 #000 黑色为主
通过以上数据最后得到如下代码,添加到 global.css 文件中
font: 24px/1.5 Microsoft YaHei;
color: #000;
具体的设计标准,每个公司都有自己的规范,在实际开发中,以公司规范为主。
# 3、新建 index.html 网页,进行首页开发
TIP
- 在当前根目录下新建 index.html 网页
- 做好 viewport 视口配置
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
- 引用相关的 CSS 文件,注意引入文件的顺序
/* 重置样式 */
css代码...
/* 网站通用布局 */
css代码...
/* 通用模块 */
css代码...
/* 通用元件 */
css代码...
/* 通用响应式系统 */
css代码...
<link rel="stylesheet" href="./css/reset.css">
<link rel="stylesheet" href="./css/global.css" />
<link rel="stylesheet" href="./css/index.css" />
# 4、网站整体 html 结构划分
<!-- m-header start -->
<header class="m-header"></header>
<!-- end m-header -->
<!-- m-menu start -->
<nav class="m-menu"></nav>
<!-- end m-menu -->
<!-- m-banner start -->
<section class="m-banner"></section>
<!-- end m-banner -->
<!-- m-main start-->
<main class="m-main">
<!-- m-nav start -->
<nav class="m-nav"></nav>
<!-- end m-nav -->
<!-- m-recommend start -->
<section class="m-recommend"></section>
<!-- end m-recommend -->
<!-- m-hot start -->
<section class="m-hot"></section>
<!-- end m-hot -->
<!-- m-focus start -->
<section class="m-focus"></section>
<!-- end m-focus -->
<!-- view-list start -->
<section class="view-list"></section>
<!-- end view-list -->
</main>
<!-- footer start -->
<footer class="tabbar"></footer>
<!--end footer -->
# 5、每个版块开发
TIP
本次项目我们采用的是 rem + Flex
弹性布局技术来实现
多行文本显示省略号
/* 超出部分隐藏 */
overflow: hidden;
/* 超出部分显示省略号 */
text-overflow: ellipsis;
/* 对象做为弹性盒子模型显示 */
display: -webkit-box;
/* 块容器 中的内容限制为指定的行数。 */
-webkit-line-clamp: 2;
/* 弹性盒子对象的子元素排列方式为竖排 */
-webkit-box-orient: vertical;
# 四、移动端 vw 项目实战
TIP
在学习 vw 项目实战前,我们现在学习下 vw 的适配原理。
# 1、vw 的适配原理
TIP
我们知道 100vw = 视口宽,相当于把整个屏幕分成了 100 份,所以不同屏幕尺寸下,1vw 的大小如下
设备可视宽(屏幕宽) | 1vw 大小 |
---|---|
750px | 7.5px |
680px | 6.8px |
480px | 4.8px |
375px | 3.75px |
- 上面表格中,不同屏幕尺寸下 1vw 的大小,不需要我们手动或通过 js 来计算,而是浏览自动会帮我转换
- 其实你可以理解,如果用 rem 来实现,把页面分 100 份,不同屏幕下 1rem 的大小与对应的 1vw 的大小时一样。
- 唯 一的区别,1vw 的大小是浏览器自动转换,而 1rem 的大小,需要通过 js 获取屏幕大小 / 100 来得到。
# 2、px 如何转换成对应 vw 单位
TIP
我们同样以 750px 的设计稿为例,那 1vw = 7.5px
,则转换成对应 vw 单位,公式如下:
? vw = 元素 px 大小 / 7.5
如下代码
.box {
width: 750px;
height: 400px;
background-color: skyblue;
}
转换成 vw
.box {
/* 750 / 7.5 =100vw */
width: 100vw;
/* 400 / 7.5 = 53.3333 */
height: 53.3333;
}
注:
我们不需要一个个手动将px
转成vw
,我们可以借助VScode
的插件px to vw
来实现。
px to vw
的使用方法和上面讲到的px to rem
是一样,唯 一的区别,就是在扩展设置时不一样
# 3、实际开发如何用 vw 做适配
TIP
在实际开发中,我们会按以下步骤来实现开发
1、要求设计师以 750px 宽,来设计移动端的设计稿
2、我们按正常的 750px 的设计稿,以 px 单位来开发
3、将 px 单位转换为对应的 vw 单位
- 将 px 像素转换 vw 单位,对应公式:
?vw = px值 / 7.5
- 我们并不会手动一个一个去计算,而是利用 vscode 中的插件
px to vw
一次搞定 - 在 VSCode 中安装 px to vw 软件中,然后将“扩展设置” 中 Viewport Width 值设为 750
- 切换到 CSS 代码,
ctrl+A
选中所有代码,然后Alt+Z
之后,就会自动把所有 px 单位,转换成对应 vw 单
# 4、项目实战
TIP
- 我们只需将上一个项目对应的 px 代码,转换成对应的 vw 单位,就可以了。
- 所以你会发现,vw 本质上就是 rem 的一种特殊情况(将页面分成 100 份),而不同屏屏幕尺寸下,1vw 是浏览自动计算。所以有了 vw,rem 这种方式几乎可以淘汰了。
- 但是,vw 还存在一定的兼容问题,除此之外,我们之前开发的所有项目,都是用的 rem,如果我们需要对原项做相关修改,我们还是需要会 rem 的。所以本质上还是需要 rem,只是说淘汰是个时间问题。
- 相关兼容型查询地址:https://caniuse.com/?search=rem (opens new window) 👆
rem 兼容,全部支持
vw 兼容,少部分不支持
# 5、rem+vw 混合方式
如果
公司项目不需要考虑不同浏览器兼容性(公司做 B 端业务,会指定客户使用指定浏览器来访问 WebApp),你需要在原来的代码上修改,就可以采用 rem+vw 混合的方式,修改部分,可以采用 vw 来实现,原有的 rem 方案不做更改
# 五、移动端开发常见问题
TIP
在实际项目开发中经常会遇到的常见问题 ...
# 1、图片缩放
TIP
- 我们现在要实现下图 gif 中,第一个图片缩放效果
- 图片的比例与填充区的比例不一样
- 希望达到效果,图片填充满当前区块,同时等比裁剪,居中显示在当前区块中
代码实现:
<style>
.box {
width: 40vw;
height: 40vw;
border: 2px solid red;
}
.box1 img {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
<body>
<div class="box box1">
<img src="./images/rotate3.webp" alt="" />
</div>
</body>
处理这个问题的意义
在实际的网站上线后,数据都是从后台读取的,用户在上传图片尺寸时,并不一定会按照设计师设计的比例来上传,这样就会造成图片上传后,大小不一样。
- 图片高度过小,会在下面留下空白,
- 图片高度过大,会有一部分下面的内容看不到
- 我们实际在设计一张图时,重要的内容会在中间显示,所以最理想的效果是让图片能水平垂直居中于容器中
# 2、背景图缩放
TIP
- 当背景图片的宽高比与容器的宽高比不一样时
- 我们希望不管容器宽高如何缩放,图片一直填充整个容器,然后水平垂直居中显示
<style>
body {
margin: 0;
}
.box {
width: 100vw;
height: 31.467vw;
/* 背景图片 不重复 水平垂直居中显示 */
background: url(./images/banner1-@2x.png) no-repeat center;
/* 背景图填充整个容器 */
background-size: cover;
}
</style>
<body>
<div class="box"></div>
</body>
# 3、精灵图使用
TIP
- 精灵图采用的是 2 倍图
- 所以在处理精灵图时,我们需要通过
background-size: 50%;
,来将背景图片大小缩小一半 - 测量尺寸时,也需要按一半的大小来测量
比如下面这种图就是一个二倍精灵图,整个图大小 401 * 123px
现在我们要在页面插入第二排第二个精灵图,同时实现等比缩放效果
先按正常 px 单位来实现,代码如下:
<style>
.icon-play {
width: 26px;
height: 26px;
border: 1px solid red;
background-image: url(images/sprite.png);
background-position: -36px -29px;
background-size: 200px;
}
</style>
<body>
<div class="icon-play"></div>
</body>
最后转换成对应 vw 单位,如下:
<style>
.icon-play {
width: 3.467vw;
height: 3.467vw;
border: 0.133vw solid red;
background-image: url(images/sprite.png);
background-position: -4.8vw -3.867vw;
background-size: 26.667vw;
}
</style>
<body>
<div class="icon-play"></div>
</body>
# 4、元素正方形缩放
TIP
元素在缩放过程中,元素的高始终等于宽,同时元素中的内容在元素中水平垂直居中
- 利用
padding-bottom:100%;
来实现元素的高与元素宽一样大小,同时等比缩放 - 利用
absolute
绝对定位与transform
实现子项在容器中水平垂直居中
<style>
.box {
width: 200px;
}
.item {
width: 100%;
/* 通过内边距,实现元素高与宽一样大小 */
padding-bottom: 100%;
background-color: khaki;
position: relative;
}
.content {
width: 100px;
height: 100px;
background-color: skyblue;
/* 元素水平垂直居中 */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
<body>
<div class="box">
<div class="item">
<div class="content"></div>
</div>
</div>
</body>
把 px 单位转换成 vw
<style>
.box {
width: 26.667vw;
}
.item {
width: 100%;
/* 通过内边距,实现元素高与宽一样大小 */
padding-bottom: 100%;
background-color: khaki;
position: relative;
}
.content {
width: 13.333vw;
height: 13.333vw;
background-color: skyblue;
/* 元素水平垂直居中 */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
<body>
<div class="box">
<div class="item">
<div class="content"></div>
</div>
</div>
</body>
图片缩放总结
只要涉及到图片缩放问题,最好将图片放在一个 html 标签中,然后设置 html 标签的宽高
html 标签的宽高,就是我们希望图片等比例缩放的展示区大。
# 5、经典的 1 像素问题
TIP
在面试中,经常会问到移动端 1px 的处理问题,那到底 1px 问题,是个什么问题呢 ?
# (1)何为 1 像素问题
TIP
为了更好的理解 1 像素问题,我们从两个方面来展开讲解
- PSD 设计稿
- 1px 实际显示的大小
PSD 设计稿
- 我们的设计稿是以 750px 宽来设计的,而我们实际开发时,代码是按 375px 来的。
- 在 750px 设计稿中的 1px,按我们实际的开发代码来说,要折半,折成 0.5px 才对。
- 但是不同手机上,不同浏览器对小数的处理是不一样的
- 0.5px 在一些老的 IOS 和 Android 设备上不支持,他会把低于 0.5px 当成 0 来处理,
>= 0.5px
当成 1px 来显示。 - IOS 上会: 把
>= 0.75px
的当作 1px 来处理 ,< 0.75
当成 0.5px 来处理< 0.5px
当成 0 来处理 - 而且 IOS 上,用
height: 1px
来代替border-bottom: 1px solid red;
测出的效果不同 - 具体不同的手机上,效果不一样,具体以真机测试为主
- 所以直接把代码折半,设置成 0.5px 显然是达不到目的。
如何解决这个问题,我们讲完下面这个问题再来解答。
1px 实际显示的大小
TIP
我们都知道 1px 在 dpr 不同时,其显示的大小不同,如下
dpr=1 | dpr=2 | dpr=3 |
---|---|---|
1px 就用一个物理像素显示 | 1px 就用 4 个物理像素来显示 | 1px 就用 9 个物理像素来显示 |
而在设计师眼中,他设计的 1px,就是当前设备能显示的最小方格(最细的那个线),也就是物理像素中的 1 像素。
所以在不同 dpr 下,显示的 1px 的线的宽度是下面图标出的蓝色的高度大小(1 物理像素大小)
dpr=1 | dpr=2 | dpr=3 |
---|---|---|
因此, 1px 像素问题,本质上不是问题,如果公司觉得没有必要,也就不用处理。
如果公司认为就是要用设备能显示的最细的那个小方格显示,那我们就要处理这个问题。
# (2)1px 像素解决方案
TIP
关于 1px 像素的处理方案有很多,这里我们提供一个最优的解决方案给到大家 transform+伪元素来实现
实现原理:
- 利用伪元素来绘制 1px 的线条,然后利用定位,把线条放在对应位置
- 利用
media
查询判断不同的设备像素比对线条进行缩放
<style>
.box {
height: 50px;
margin: px auto;
position: relative;
}
.border-1px::before {
position: absolute;
content: "";
height: 1px;
width: 100%;
background-color: red;
bottom: 0;
/* transform: scaleY(0.5); */
/* 变换原点 */
transform-origin: 50% 0%;
}
/* dpr=2,需要缩放一半,即0.5 */
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
.border-1px:before {
transform: scaleY(0.5);
}
}
/* dpr=3,需要缩放到1/3,即0.33 */
@media only screen and (-webkit-min-device-pixel-ratio: 3) {
.border-1px:before {
transform: scaleY(0.33);
}
}
</style>
<body>
<div class="box border-1px"></div>
</body>
当然,也可以通过 js 来判断 dpr,然后给元素添加对应的 Class 名字,来实现
if (window.devicePixelRatio && devicePixelRatio >= 2) {
document.querySelector(".box").className = "border-1px";
}
你可以电脑端,打开头条的移动端,查看头条的 1px 解决方案,和我们这里讲到的是一个逻辑
大厂最新技术学习分享群

微信扫一扫进群,获取资料
X