1、什么是响应式 Responsive?
响应式是一种设计和开发方法,通过这种方法可以使网页能够在各种设备和屏幕尺寸上进行良好的展示和使用。
无论是桌面电脑、笔记本电脑、平板电脑还是智能手机,响应式前端页面都能够根据屏幕的大小、分辨率和方向自动调整布局、内容和功能,提供一致且优雅的用户体验。
响应式的实现方法一般有如下特点:
- 页面使用相对单位(如百分比)而不是绝对单位(如像素)来定义布局,注意说的是布局,而不是元素的大小;
- 图片和其它媒体内容(如视频)使用相对尺寸或 css 属性(如 max-width: 100%) 来确保它们在不同屏幕上都能正确的显示,不会超出容器的宽度;
- 通常会使用到媒体查询(media queries),来设置不同的屏幕尺寸断点,定义不同的样式规则;
- 一般还会使用到 flex,grid 进行流式网格布局,分别常用的属性包括 flex-wrap、flex-grow、flex-shrink、grid-template-colums、grid-template-rows 等;
2、什么是自适应 Adaptive?
自适应也是一种设计和开发方法,这种方法主要是根据用户的设备类型和屏幕尺寸加载不同的固定布局和样式。
与响应式设计不同,自适应设计并不是一个流动的、灵活的布局,而是为不同的设备类型预先设计一系列固定的布局版本,并根据设备的属性选择适当的版本加载。
自适应的实现方法一般有如下特点:
页面根据设备的特性(如屏幕分辨率、浏览器类型)自动选择加载合适的布局,为每个设备类别定义不同的 css 样式表。
通常,这种检测是在服务端完成的,但是也可以在客户端通过 js 进行判断。
自适应的方案会存在以下缺点:
- 维护成本会比较高,需要为每个设备类别维护不同的布局和样式,增加了开发和维护的工作量,(但同时也会让每个设备单独加载的资源更少,有可能提供更快的加载速度,这个算是一个优点);
- 设备检测起来比较复杂,尤其是在客户端设备种类繁多的情况下;
- 缺乏灵活性,固定布局在某些情况下可能无法适应一些介于预设设备类别之间的屏幕尺寸;
以上就是响应式设计和自适应设计的介绍,在实际开发中,两者不是非此即彼的关系,要根据实际情况结合进行应用。
3、如何进行响应式开发?
下面主要介绍响应式开发过程中 css media query 和 rem 相关的问题,其它诸如百分比、流式网格布局等方面由于相对简单,不作介绍。
3.1、Less Media Query 断点设置
3.1.1、常见屏幕尺寸
首先,需要了解一下有哪些常见的屏幕尺寸,用来确定 media query 的断点设置。
打开浏览器的 device toolbar ,可以看到默认有以下常用设备选项:
设备名称 | 屏幕宽度(仅关注屏幕宽度,不考虑高度) |
---|---|
iPhone SE | 375 |
iPhone XR | 414 |
iPhone 12 Pro | 390 |
iPhone 14 Pro Max | 430 |
iPad Mini | 768 |
iPad Air | 820 |
iPad Pro | 1024 |
笔记本电脑的屏幕尺寸一般有以下几种:
- 1280
- 1440
- 1800
- 1920
- 2560
桌面显示器的屏幕尺寸一般有以下几种:
- 1600
- 1920
- 2560
- 3840
3.1.2、断点变量设置
下面列举一下已知的设计团队在进行页面设计时遵循的原则,当然不同的设计团队可能存在差异,设计原则示例如下:
x>=1801 | 1800>= x >=1200 | 1199 >= x >= 992 | 991 >= x >= 768 | 767 >= x >= 600 | x <= 599 |
---|---|---|---|---|---|
内容不再放大 | rem 等比例适配 | ipad 端固定 px 值 | ipad 端固定 px 值 | 移动端固定 px 值 | 移动端固定 px 值 |
- 屏幕宽度小于 600px 时:字体大小(font-size)、行高(line-height)、内外间距(margin、padding)采用固定值,元素宽度采用百分比;
- 屏幕宽度大于等于 600px 小于等于 767px 时:依旧采用固定值,只不过和屏幕宽度小于 600px 时的赋值大小有所差异;
- 屏幕宽度大于等于 768px 小于等于 991px 和 屏幕宽度大于等于 992px 小于等于 1199px 时同上;
- 屏幕宽度大于等于 1200px 小于等于 1800px 时:字体大小、行高、内外间距、部分元素宽度采用 rem 进行定义;
- 屏幕宽度大于等于 1801px 时,中间内容区域不再方法,两边区域进行背景色填充或者背景图片填充。
根据以上列举的屏幕尺寸和设计规则,可以定义以下断点,为了方便管理和使用断点,我们使用 less 变量进行定义:
// 小型移动端设备
@mobile-sm: ~"only screen and (max-width: 374.98px)";
// 中型移动端设备
@mobile-md: ~"only screen and (min-width: 375px) and (max-width: 599.98px)";
// 大型移动端设备
@mobile-lg: ~"only screen and (min-width: 600px) and (max-width: 767.98px)"
// 所有移动端设备(组合变量)
@mobile: ~"@{mobile-sm}, @{mobile-md}, @{mobile-lg}";
// 小型平板设备
@tablet-sm: ~"only screen and (min-width: 678px) and (max-width: 991.98px)";
// 一般平板设备
@tablet-md: ~"only screen and (min-width: 992px) and (max-width: 1199.98px)";
// 所有平板设备(组合变量)
@tablet: ~"@{tablet-sm}, @{tablet-md}";
// 一般桌面设备
@desktop-md: ~"only screen and (min-width: 1200px) and (max-width: 1800.98px)";
// 大型桌面设备
@desktop-lg: ~"only screen and (min-width: 1801px)";
// 所有桌面设备(组合变量)
@desktop: ~"@{desktop-md}, @{desktop-lg}";
3.2、REM 设置
如上述,桌面端 1200px 宽度以上我们采用 rem,小于 1200px 的平板端和移动端我们均采用固定像素值。(不同宽度下设置的固定像素值会有所差异)
3.2.1、font-size 设置
加入我们拿到的设计稿是 1200px 和 1800px 的尺寸,设置 font-size 如下:
- 当屏幕宽度小于 1200px 时,设置 font-size 固定为 10px,避免 font-size 过小;
- 当屏幕宽度大于 1800px 时,设置 font-size 固定为 15px,避免 font-size 过大;
- 当屏幕宽度介于 1200px 和 1800px 之间时,设置 font-size 为屏幕宽度 / 120;
html {
font-size: calc(100vw / 120);
@media screen and (max-width: 1200px) {
font-size: 10px;
}
@media screen and (min-width: 1800px) {
font-size: 15px;
}
}
按照上述的 font-size 设置,当某个元素 A 在 1200px 下的 margin 值等于 60px 时,项目编译时会将其转化为 6rem, 则在 1800px 宽度的屏幕上,margin 实际值为 15px * 6 = 90px。
3.2.2、rem 自动转换
在开发时,可以复制设计稿中的元素样式到编辑器之后,手动将值进行计算然后修改编辑器代码中的 px 为 rem ,这种方式在开发效率上存在一定问题。
下面介绍以 postcss-pxtorem 插件的形式,自动对 less 文件中的像素单位进行转换。
插件地址:www.npmjs.com/package/pos…
插件示例配置, postcss.config.js 内容如下:
module.exports = {
'plugins': [
[
'postcss-pxtorem',
{
rootValue: 10,
unitPrecision: 5,
propList: ['*'],
selectorBlackList: ['html'],
replace: true,
mediaQuery: false,
minPixelValue: 2,
exclude: file => {
return !/.module/.test(file);
},
},
],
],
};
postcss-pxtorem 插件属性介绍如下:
属性名称 | 建议取值 | 属性解释 |
---|---|---|
rootValue | 10 (根据实际情况) | 根元素字体大小或根据输入参数返回根元素字体大小 (Number/Function) Represents the root element font size or returns the root element font size based on the input parameter |
unitPrecision | 5 | 允许REM单位增长到的十进制数 (Number) The decimal numbers to allow the REM units to grow to. |
propList | ['*'] | 标识可以改变从px到rem的属性列表。 1、值需要精确匹配; 2、使用通配符 * 来启用所有属性。例如:(“ * ”); 3、在单词的开头或结尾使用 * ,例如 ( ['position'] 将匹配 background-position-y); 4、 使用 ! 不匹配属性,示例: ['','!letter-spacing']); 5、将“not”前缀与其他前缀组合。示例:['','!字体*’)(Array) The properties that can change from px to rem. 1、Values need to be exact matches. 2、Use wildcard * to enable all properties. Example: ['*'] 3、Use * at the start or end of a word. (['*position*'] will match background-position-y ) 4、Use ! to not match a property. Example: ['*', '!letter-spacing'] 5、Combine the "not" prefix with the other prefixes. Example: ['*', '!font*'] |
selectorBlackList | ['html'] | 处理时忽略的选择器,将保留为px。如果value是字符串,它检查选择器是否包含该字符串。['body']将匹配。body-class如果value是regexp,它检查选择器是否匹配regexp。 |
replace | true | 替换包含rems的规则,而不是添加回退。 (Boolean) Replaces rules containing rems instead of adding fallbacks. |
mediaQuery | false | 允许在媒体查询中转换px。 (Boolean) Allow px to be converted in media queries. |
minPixelValue | 2 | 设置要替换的最小像素值。 (Number) Set the minimum pixel value to replace. |
exclude | 根据实际情况设置 | (String, Regexp, Function)要忽略并保留为px的文件路径。 1、如果value为string,则检查文件路径是否包含该字符串。 2、'exclude'将匹配\project\postcss-pxtorem\exclude\path如果value为regexp,则检查文件路径是否与regexp匹配。 3、/exclude/i将匹配\project\postcss-pxtorem\exclude\path 4、如果value是function,你可以使用exclude函数返回true,文件将被忽略。回调函数将文件路径作为参数传递,它应该返回一个布尔值结果。 |
unit | PX (建议将需要转化为 rem 的单位都写为大写的 PX,用于避免不想转化为 rem 的 px 规则被转换) | 设置转换的默认单位,默认为px (String) Set the default unit to convert, default is px |
replace 属性设置为 true 时,直接会将 原始 less 文件中的 值进行替换,如 width:10PX 转化为 width: 1rem。
如果设置为 false, 将会在编译后的文件中输出两行代码,width: 10PX;width: 1rem; 主要的作用是,兼容不支持 rem 单位的旧版浏览器,并且可以在开发过程中,方便调试和验证转换结果,能够同时看到 px 值和 rem 值,但是代码会冗余,如果不需要考虑这两点,建议将 replace 的值设置为 true.
3.3、背景图片设置
背景图片基本采用以下样式属性进行设置:
- @color 是背景图片的兜底颜色
- 下述代码是在 less 中定义的 mixin,所有的属性值都是通过变量传递,需要注意如果是 Less3.0 以下的版本,不支持只传递部分参数,需要根据实际情况进行调整。
.bg-img(@image-url: 'path/to/image.jpg', @repeat: no-repeat, @position: center center, @size: cover, @color: #fff) {
background-image: url(@image-url);
background-repeat: @repeat;
background-position: @position;
background-size: @size;
background-color: @color;
}