跳到主要内容位置

实现网页响应式设计

现在,各种屏幕尺寸的设备越来越多,一个网页要在不同设备上都显示正常美观,就需要一定的技术手段来实现。我们可以针对不同设备开发不同的网页版本,但是这种方式会极大的增加开发工作量,另一种方式就是使用响应式设计。

什么是响应式网页设计

响应式网页设计,指的是,利用 CSS 或 JavaScript,让同一个网页,能根据屏幕的大小,自动调整布局和样式,包括对容器元素、布局、图片和字体的响应式调整。这个视频我们来看一下如何利用 CSS 来实现响应式。

纯 HTML 元素默认都是响应式的

要注意的是,原生的 HTML 元素,在没有编写任何 CSS 的情况下,本身就是响应式的,不过每个网页都避免不了使用 CSS 设置样式,响应式则主要针对设置了固定宽度,或者影响布局的元素进行调整。

开启移动设备响应式

要开启响应式,需要在在 html 中添加一个 meta 元素,设置 name 属性值为 viewport, content 属性值为 content="width=device-width, initial-scale=1.0",这是因为移动设备下,默认是对 PC 网页进行缩放来展示,把它缩小到能放下整个网站为止,用户体验不友好,在设置 width=device-width 之后,网页的可视区域(视口)就会取移动设备屏幕的宽度,设置了 initial-scale 为 1.0 之后,就会使用正常的缩放比例,即 1 倍,不缩放。 设置 view port <meta name="viewport" content="width=device-width, initial-scale=1.0">

容器响应式

对于设置了固定宽度的容器,在浏览器可视区域大于它的宽度时,会有大片的空白,如果小于它的宽度就会有横向滚动条,影响阅读:

<div class="container">
<p>
晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。<b>忽逢桃花林,夹岸数百步</b>,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。见渔人,乃大惊,<del>问所从来。具答之</del>。便要还家,设酒杀鸡作食。<em>村中闻有此人,咸来问讯</em>。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。南阳刘子骥,高尚士也,闻之,<strong>欣然规往</strong>。未果,寻病终,后遂无问津者。
</p>
</div>

.container { width: 1200px; }

那么,我们可以百分比宽度,来让它根据浏览器的可视区域宽度,自动调整尺寸:

.container { width: 100%; }

或者使用 max-width,限制最大宽度:

.container {
max-width: 80%;
margin: 0 auto;
}

如果必须使用固定宽度,我们可以利用 media query,查询可视区域的宽度,根据不同的宽度,调整容器的尺寸:

.container {
width: 800px;
}

@media (max-width: 900px) {
.container {
width: 600px;
}
}

@media (max-width: 700px) {
.container {
width: 500px;
}
}

布局响应式

对于布局,HTML 元素默认为竖向排列,这个情况下没有问题。如果对里边的子元素进行横向排列,例如使用 flex 布局,那么在浏览器可视区域过窄时,会影响阅读:

.container {
display: flex;
}

我们可以利用 flex-wrap 和 flex 属性,来让 flex 子元素保持最小宽度,并自动折行:

/* 当屏幕过窄,会影响阅读,设置换行 */
.container {
display: flex;
flex-wrap: wrap;
}

.container p {
/* 每个 flex item 最小宽度 */
flex: 250px;
}

如果是使用 grid 布局,默认它是竖向排列,这样没问题:

.container {
display: grid;
}

但如果是多列布局,并且每列都是浮动宽度的话,也会出现 flex 一样影响阅读的问题:

.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}

这时有两种解决方法,第一种方法是,在一行中,尽量容纳最多的列,通过 repeat 和 minmax 函数,设置每列最小宽度为 250px,超出后自动折行,与 flex-wrap 效果类似:

.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}

第二种方法是:使用 media query,手动控制列数:

.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}

@media (max-width: 900px) {
.container {
grid-template-columns: 1fr 1fr;
}
}

@media (max-width: 600px) {
.container {
grid-template-columns: 1fr;
}
}

图片响应式

对于图片,浏览器默认会显示图片原本大小。要开启图片响应式,我们可以使用百分比宽度,设置 width 或 max-width,但是在移动设备下:

  • 仍然会加载原图,造成体积过大,影响性能。
  • 移动设备可能需要不同的图片纵横比。
img {
max-width: 100%;
}

这个时候也有两中解决方案: 解决方案 1,img + srcset + sizes:

  • srcset 设置一组不同尺寸的图片路径,多个值用逗号隔开,每个值第一项为图片 url,第二项是图片原始宽度,这里使用 w 单位而不是 px,因为浏览器还要考虑像素密度。
  • sizes 里通过 media query 查询可视区域宽度,满足条件时,通过第二值指定图片的宽度。
  • 浏览器会自行根据像素密度和屏幕宽度来加载合适的图片。
<img
src="../image-300.png"
srcset="../image-1240.png 1240w, ../image-600.png 600w, ../image-300.png 300w"
sizes="(max-width: 400px) 300px, (max-width: 900px) 600px, 1240px"
/>

解决方案 2,picture:

  • 结合 source 元素,指定图片 url 和 media query,在不同可视区域宽度下,加载不同的图片。
  • 最后使用 img 来加载保底的图片。
<picture>
<source media="(max-width: 400px)" srcset="../image-300.png" />
<source media="(max-width: 900px)" srcset="../image-600.png" />
<img src="../image-1240.png" />
</picture>

字体响应式

对于字体响应式,我们也可以使用 media query 或浮动单位来设置。需要注意一下,字体单位使用 rem 或 em,就可以根据用户设置的浏览器默认字体大小,进行缩放,而不是固定尺寸。不过即使使用这两个单位,也需要根据屏幕的大小做响应式调整。 使用 media query:

h1 {
font-size: 4rem;
}

@media (max-width: 900px) {
h1 {
font-size: 3rem;
}
}

@media (max-width: 700px) {
h1 {
font-size: 2rem;
}
}

使用浮动大小:

h1 {
font-size: 4vw;
}

防止过小,以及避免影响移动设备字体缩放:

h1 {
font-size: calc(2rem + 2vw);
}

小结

好了,这个就是实现网页响应式的方法,你学会了吗?如果有帮助请三连并关注,想学更多的开发知识,可以在评论区留言,感谢观看!

提示

一系列的课程让你成为高级前端工程师。课程覆盖工作中所有常用的知识点和背后的使用逻辑,示例全部都为工作项目简化而来,学完即可直接上手开发!

即使你已经是高级前端工程师,在课程里也可能会发现新的知识点和技巧,让你的工作更加轻松!

《React 完全指南》课程,连载中现只需 48 元(领取优惠券)点击查看详情。

《Vue 3.x 全家桶完全指南与实战》课程,包括 Vue 3.x、TypeScript、Vue Router 4.x、Vuex 4.x 所有初级到高级的语法特性详解,让你完全胜任 Vue 前端开发的工作。点击查看详情。

《React即时通信UI实战》课程,利用 Storybook、Styled-components、React-Spring 打造属于自己的组件库。

《JavaScript 基础语法详解》本人所著图书,包含 JavaScript 全面的语法知识和新特性, 可在京东、当当、淘宝等各大电商购买