记得刚学前端那会儿,做页面就按固定宽度来,960px居中,觉得完美了。结果客户拿手机打开,横向滚动条一拉,丑得不行。没办法,只能硬着头皮学着做响应式。

走了不少弯路,看了一堆教程,越看越迷糊。flexbox、grid、媒体查询,一堆概念搅在一起,不知道什么时候该用什么。后来项目做多了,才慢慢理清楚这里面的门道。

今天把响应式设计的核心知识梳理一遍,从思路到实践,争取让新手也能看懂。

移动优先这个思路很重要

以前做响应式都是先做PC端,然后往小了缩。后来发现不对劲,很多东西在小屏幕上本来就不该那么复杂,缩着缩着就出问题了。

移动优先的意思是,先按手机屏幕做设计,然后逐步增加屏幕宽度,每一步都考虑更大的屏幕该怎么处理。这样做出来的东西结构更清晰,不会出现PC上塞得太满、手机上又太空的情况。

代码上怎么体现呢?就是媒体查询里用min-width而不是max-width。先写小屏幕的样式,然后通过min-width: 768px来给平板以上的屏幕加样式,再通过min-width: 1024px来给桌面环境加样式。

flexbox适合一维布局

flexbox出来之前,垂直居中是个老大难问题。现在简单了,display: flex,加几行属性就搞定了。

flexbox最适合的场景是导航栏、卡片列表、表单元素对齐这些。特点是内部元素要么是横向排列要么是纵向排列,不需要复杂的网格。

常用的几个属性要记住:flex-direction控制方向,justify-content控制主轴对齐,align-items控制交叉轴对齐,flex-wrap控制换行。flex-grow和flex-shrink控制伸缩比例,这个很重要,能让元素根据容器大小自动调整。

有个坑要提醒一下,flex容器直接给子元素设置的宽高可能不生效,因为flex item有自己的伸缩逻辑。如果想固定大小,要用flex-basis而不是width或height。

grid适合二维布局

如果说flexbox是一维的,那grid就是二维的。grid适合做页面整体布局、相册、时间线这种需要行列对齐的场景。

最简单的方式是用grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)),配合grid-auto-rows设置行高,就能实现一个自适应的网格布局。图片画廊、商品列表用这个特别省事。

grid的命名网格线功能很强大,可以给网格线起名字,然后用grid-area或者grid-column/row来指定元素占用的区域。复杂的布局用这个比用float和position简单多了。

subgrid这个属性现在兼容性也好了,用在嵌套的grid上能让内层网格继承外层的轨道大小,特别适合做对齐要求高的表格式布局。

媒体查询怎么写

媒体查询不只是写几个断点就完了。断点设在哪里,要根据内容来定,而不是根据某个特定设备。

常见的做法是,内容优先于设备。比如一段文字,在600px宽的时候一行能显示多少字、超过多少就该换行了,就在这个点设断点。而不是去研究iPhone SE是320px、iPhone 14是390px。

rem和em在响应式里很好用。基于根元素字体大小来设置长宽高,在不同屏幕上能自动按比例缩放。当然也要注意,有些地方用px更合适,比如边框和轮廓。

还有个容易被忽略的是,媒体查询的顺序很重要。因为CSS是层叠的,后面的规则会覆盖前面的。如果用min-width写,断点从小到大排;如果用max-width写,断点从大到小排。

图片和视频要适配

响应式布局做好了,内容适配跟不上也是白搭。图片要用srcset和sizes来提供不同分辨率的版本,不然在小屏幕上也加载大图,浪费流量还影响加载速度。

现在浏览器大多支持webp格式,体积比jpg小很多,能显著提升加载速度。配合图片CDN的服务,可以根据浏览器自动返回合适的格式。

视频的话,embed和iframe要记得加aspect-ratio属性,不然视频加载前会没有高度,页面会跳动。这个问题很常见,但很多人忽视了。

背景图片用media query或者image-set来处理,切换不同分辨率的图片。现在的屏幕有1x、2x、3x之分,高清屏上不用高分辨率图片会模糊,但低分辨率屏幕上用高分辨率图片又浪费。

表格的响应式处理

表格是最难处理的部分。复杂的表格在小屏幕上怎么显示,没有标准答案,要根据数据特点来定。

简单表格可以直接给table设置overflow-x: auto,让表格可以水平滚动。这是最省事的做法,用户需要的时候能看全。

复杂表格可以考虑转置,把原来按行展示的改成按列展示。或者是把次要信息藏起来,在小屏幕上通过点击展开。也有人用卡片的形式来展示表格数据,每张卡片代表一行。

不管用哪种方案,都要确保数据不会丢失,用户能访问到完整信息。不要为了视觉效果就把数据藏起来用户看不到。

调试工具要会用

Chrome DevTools的设备模拟功能很好用,能模拟各种屏幕尺寸和像素比。但要注意,这是模拟,不是真实设备测试。有些问题只有在真机上才能发现。

我一般会在真机上测试几个关键场景:不同尺寸的手机、不同尺寸的平板、笔记本屏幕、桌面外接显示器。特别是触控和hover效果,模拟器上没法完全复现。

浏览器的开发者工具还能模拟网络限速,看页面在弱网下的表现。首屏加载时间、LCP这些指标,都要关注。

性能不能忘

响应式网站一个问题就是资源加载。有时候PC和手机加载同样的JS和CSS,手机明显更慢。代码分割、按需加载能缓解这个问题。

CSS也要注意,媒体查询里用screen and (...)而不是screen and (...) and (hover: hover),某些老浏览器可能不支持导致样式丢失。渐进增强的思路很重要,核心功能要保证在各种环境都能用。

字体大小要设置viewport宽度相关的单位,或者用clamp()函数来设置一个范围。不然在大屏幕上字体太大,在小屏幕上字体又太小。

写在最后

响应式设计不是一项独立的技术,而是从前端到后端一整套的思路。设计的时候就要考虑不同屏幕,产品经理提需求的时候也要说清楚各端的需求,前端实现的时候更要权衡好各方面的因素。

技术是为人服务的,响应式的目的不是炫技,而是让网站在各种设备上都有好的体验。用户用手机打开你的网站,能正常浏览、能完成任务,这就是响应式设计的意义。