前端响应式布局原理与方案(详细版)

前端响应式布局原理与方案(详细版)引言响应式布局指的是同一页面在不同屏幕尺寸下有不同的布局 传统的开发方式是 PC 端开发一套 手机端再开发一套 而使用响应式布局只要开发一套就够 缺点就是 CSS 比较重 下面是博客网站对不同设备适配后的结果 分别是 iPhone5 SE iphone6 7 8 iphone6 7 8plus ipadpro dell 台式宽屏 1440X900 响应式设计与自适应设计的区别 响应式开发

引言

响应式布局指的是同一页面在不同屏幕尺寸下有不同的布局。传统的开发方式是PC端开发一套,手机端再开发一套,而使用响应式布局只要开发一套就够,缺点就是CSS比较重。下面是博客网站对不同设备适配后的结果,分别是iPhone5/SE,iphone6/7/8,iphone 6/7/8 plus,ipad pro,dell台式宽屏(1440 X 900)

响应式设计与自适应设计的区别:响应式开发一套界面,通过检测视口分辨率,针对不同客户端在客户端做代码处理,来展现不同的布局和内容;自适应需要开发多套界面,通过检测视口分辨率,来判断当前访问的设备是pc端、平板、手机,从而请求服务层,返回不同的页面。

[图片上传中…(image–77-7)]

[图片上传中…(image-af65de-77-6)]

[图片上传中…(image-94e09f-77-5)]

响应式布局的实现方案

1. 媒体查询

CSS3媒体查询可以让我们针对不同的媒体类型定义不同的样式,当重置浏览器窗口大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。

如何选择屏幕大小分割点

如何确定媒体查询的分割点也是一个开发中会遇到的问题,下面是市场上的移动设备和电脑屏幕分辨率的分布情况,可以发现不同品牌和型号的设备屏幕分辨率一般都不一样

[图片上传中…(image-65d24d-77-4)]

如果我们选择600px,900px,1200px,1800px作为分割点,可以适配到常见的14个机型:

[图片上传中…(image-21b91d-77-3)]

当然这只是其中的一种分割方案,我们还可以这样划分:480px,800px,1400px,1400px

[图片上传中…(image-b0cf6f-77-2)]

而作为曾经典型的响应式布局框架,Bootstrap是怎么进行断点的呢?

[图片上传中…(image-5be700-77-1)]

上面的分割方案不一定满足项目中的实际需求,我们可以先用跨度大的分割点进行分割,如果出现不适配的情况可以再根据实际情况增加新的分割点。

移动优先 OR PC优先

不管是移动优先还是PC优先,都是依据当随着屏幕宽度增大或减小的时候,后面的样式会覆盖前面的样式。因此,移动端优先首先使用的是min-width,PC端优先使用的max-width

移动优先:

/* iphone6 7 8 */ body { background-color: yellow; } /* iphone 5 */ @media screen and (max-width: 320px) { body { background-color: red; } } /* iphoneX */ @media screen and (min-width: 375px) and (-webkit-device-pixel-ratio: 3) { body { background-color: #0FF000; } } /* iphone6 7 8 plus */ @media screen and (min-width: 414px) { body { background-color: blue; } } /* ipad */ @media screen and (min-width: 768px) { body { background-color: green; } } /* ipad pro */ @media screen and (min-width: 1024px) { body { background-color: #FF00FF; } } /* pc */ @media screen and (min-width: 1100px) { body { background-color: black; } } 复制代码 

PC优先:

/* pc width > 1024px */ body { background-color: yellow; } /* ipad pro */ @media screen and (max-width: 1024px) { body { background-color: #FF00FF; } } /* ipad */ @media screen and (max-width: 768px) { body { background-color: green; } } /* iphone6 7 8 plus */ @media screen and (max-width: 414px) { body { background-color: blue; } } /* iphoneX */ @media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) { body { background-color: #0FF000; } } /* iphone6 7 8 */ @media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) { body { background-color: #0FF000; } } /* iphone5 */ @media screen and (max-width: 320px) { body { background-color: #0FF000; } } 复制代码 

2.百分比布局

通过百分比单位,可以使得浏览器中组件的宽和高随着浏览器的高度的变化而变化,从而实现响应式的效果。Bootstrap里面的栅格系统就是利用百分比来定义元素的宽高,CSS3支持最大最小高,可以将百分比和max(min)一起结合使用来定义元素在不同设备下的宽高。

/* pc width > 1100px */
html, body { margin: 0;padding: 0;width: 100%;height: 100%;}
aside {
    width: 10%;
    height: 100%;
    background-color: red;
    float: left;
}
main {
    height: 100%;
    background-color: blue;
    overflow: hidden;
}
/* ipad pro */
@media screen and (max-width: 1024px) {
    aside {
      width: 8%;
      background-color: yellow;
    }
}
/* ipad */
@media screen and (max-width: 768px) {
    aside {
      float: none;
      width: 100%;
      height: 10%;
      background-color: green;
    }
    main {
      height: calc(100vh - 10%);
      background-color: red;
    }
}
/* iphone6 7 8 plus */
@media screen and (max-width: 414px) {
    aside {
      float: none;
      width: 100%;
      height: 5%;
      background-color: yellow;
    }
    main {
      height: calc(100vh - 5%);
      background-color: red;
    }
}
/* iphoneX */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) {
    aside {
      float: none;
      width: 100%;
      height: 10%;
      background-color: blue;
    }
    main {
      height: calc(100vh - 10%);
      background-color: red;
    }
}
/* iphone6 7 8 */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) {
    aside {
      float: none;
      width: 100%;
      height: 3%;
      background-color: black;
    }
    main {
      height: calc(100vh - 3%);
      background-color: red;
    }
}
/* iphone5 */
@media screen and (max-width: 320px) {
    aside {
      float: none;
      width: 100%;
      height: 7%;
      background-color: green;
    }
    main {
      height: calc(100vh - 7%);
      background-color: red;
    }
}
复制代码

但是我们必须要弄清楚css中子元素的百分比到底是相对谁的百分比。直接上结论吧:

子元素的heightwidth中使用百分比,是相对于子元素的直接父元素,width相对于父元素的widthheight相对于父元素的height;子元素的topbottom如果设置百分比,则相对于直接非static定位(默认定位)的父元素的高度,同样子元素的leftright如果设置百分比,则相对于直接非static定位(默认定位的)父元素的宽度;子元素的padding如果设置百分比,不论是垂直方向或者是水平方向,都相对于直接父亲元素的width,而与父元素的height无关。跟padding一样,margin也是如此,子元素的margin如果设置成百分比,不论是垂直方向还是水平方向,都相对于直接父元素的widthborder-radius不一样,如果设置border-radius为百分比,则是相对于自身的宽度,除了border-radius外,还有比如translatebackground-size等都是相对于自身的;

从上述对于百分比单位的介绍我们很容易看出如果全部使用百分比单位来实现响应式的布局,有明显的以下两个缺点:

  • 计算困难,如果我们要定义一个元素的宽度和高度,按照设计稿,必须换算成百分比单位。
  • 从小节1可以看出,各个属性中如果使用百分比,相对父元素的属性并不是唯一的。比如widthheight相对于父元素的widthheight,而marginpadding不管垂直还是水平方向都相对比父元素的宽度、border-radius则是相对于元素自身等等,造成我们使用百分比单位容易使布局问题变得复杂。

3.rem布局

REMCSS3新增的单位,并且移动端的支持度很高,Android2.x+,ios5+都支持。rem单位都是相对于根元素html的font-size来决定大小的,根元素的font-size相当于提供了一个基准,当页面的size发生变化时,只需要改变font-size的值,那么以rem为固定单位的元素的大小也会发生响应的变化。 因此,如果通过rem来实现响应式的布局,只需要根据视图容器的大小,动态的改变font-size即可(而em是相对于父元素的)。

rem响应式的布局思想:

  • 一般不要给元素设置具体的宽度,但是对于一些小图标可以设定具体宽度值
  • 高度值可以设置固定值,设计稿有多大,我们就严格有多大
  • 所有设置的固定值都用rem做单位(首先在HTML总设置一个基准值:pxrem的对应比例,然后在效果图上获取px值,布局的时候转化为rem值)
  • js获取真实屏幕的宽度,让其除以设计稿的宽度,算出比例,把之前的基准值按照比例进行重新的设定,这样项目就可以在移动端自适应了

rem布局的缺点:

在响应式布局中,必须通过js来动态控制根元素font-size的大小,也就是说css样式和js代码有一定的耦合性,且必须将改变font-size的代码放在css样式之前

/*上述代码中将视图容器分为10份,font-size用十分之一的宽度来表示,最后在header标签中执行这段代码,就可以动态定义font-size的大小,从而1rem在不同的视觉容器中表示不同的大小,用rem固定单位可以实现不同容器内布局的自适应。*/ function refreshRem() { var docEl = doc.documentElement; var width = docEl.getBoundingClientRect().width; var rem = width / 10; docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; } win.addEventListener('resize', refreshRem); 复制代码 

REM布局也是目前多屏幕适配的最佳方式。默认情况下我们html标签的font-size为16px,我们利用媒体查询,设置在不同设备下的字体大小。

/* pc width > 1100px */
html{ font-size: 100%;}
body {
    background-color: yellow;
    font-size: 1.5rem;
}
/* ipad pro */
@media screen and (max-width: 1024px) {
    body {
      background-color: #FF00FF;
      font-size: 1.4rem;
    }
}
/* ipad */
@media screen and (max-width: 768px) {
    body {
      background-color: green;
      font-size: 1.3rem;
    }
}
/* iphone6 7 8 plus */
@media screen and (max-width: 414px) {
    body {
      background-color: blue;
      font-size: 1.25rem;
    }
}
/* iphoneX */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 3) {
    body {
      background-color: #0FF000;
      font-size: 1.125rem;
    }
}
/* iphone6 7 8 */
@media screen and (max-width: 375px) and (-webkit-device-pixel-ratio: 2) {
    body {
      background-color: #0FF000;
      font-size: 1rem;
    }
}
/* iphone5 */
@media screen and (max-width: 320px) {
    body {
      background-color: #0FF000;
      font-size: 0.75rem;
    }
}
复制代码

4.视口单位

css3中引入了一个新的单位vw/vh,与视图窗口有关,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vwvh外,还有vminvmax两个相关的单位。各个单位具体的含义如下:

单位 含义
vw 相对于视窗的宽度,1vw 等于视口宽度的1%,即视窗宽度是100vw
vh 相对于视窗的高度,1vh 等于视口高度的1%,即视窗高度是100vh
vmin vw和vh中的较小值
vmax vw和vh中的较大值

[图片上传中…(image-2c6eed-73-0)]

用视口单位度量,视口宽度为100vw,高度为100vh(左侧为竖屏情况,右侧为横屏情况)。例如,在桌面端浏览器视口尺寸为650px,那么 1vw = 650 * 1% = 6.5px(这是理论推算的出,如果浏览器不支持0.5px,那么实际渲染结果可能是7px)。

那么vw或者vh很类似百分比单位。vw和%的区别为:

单位 含义
% 大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate等)
vw/vh 相对于视窗的尺寸

从对比中我们可以发现,vw单位与百分比类似,单确有区别,前面我们介绍了百分比单位的换算困难,这里的vw更像”理想的百分比单位”。任意层级元素,在使用vw单位的情况下,1vw都等于视图宽度的百分之一。

使用视口单位来实现响应式有两种做法:

1.仅使用vw作为CSS单位

  • 对于设计稿的尺寸转换为为单位,我们使用Sass函数编译
    //iPhone 6尺寸作为设计稿基准 $vm_base: 375; @function vw($px) { @return ($px / 375) * 100vw; } 复制代码 
  • 无论是文本还是布局宽度、间距等都使用vw作为单位
    .mod_nav { background-color: #fff; &_list { display: flex; padding: vm(15) vm(10) vm(10); // 内间距 &_item { flex: 1; text-align: center; font-size: vm(10); // 字体大小 &_logo { display: block; margin: 0 auto; width: vm(40); // 宽度 height: vm(40); // 高度 img { display: block; margin: 0 auto; max-width: 100%; } } &_name { margin-top: vm(2); } } } } 复制代码 
  • 1物理像素线(也就是普通屏幕下1px,高清屏幕下0.5px的情况)采用transform属性scale实现
    .mod_grid { position: relative; &::after { // 实现1物理像素的下边框线 content: ''; position: absolute; z-index: 1; pointer-events: none; background-color: #ddd; height: 1px; left: 0; right: 0; top: 0; @media only screen and (-webkit-min-device-pixel-ratio: 2) { -webkit-transform: scaleY(0.5); -webkit-transform-origin: 50% 0%; } } ... } 复制代码 
  • 对于需要保持宽高比的图,应该用padding-top实现
    .mod_banner { position: relative; padding-top: percentage(100/700); // 使用padding-top height: 0; overflow: hidden; img { width: 100%; height: auto; position: absolute; left: 0; top: 0; } } 复制代码 

2.搭配vw和rem

虽然采用vw适配后的页面效果很好,但是它是利用视口单位实现的布局,依赖视口大小而自动缩放,无论视口过大还是过小,它也随着时候过大或者过小,失去了最大最小宽度的限制,此时我们可以结合rem来实现布局

  • 给根元素大小设置随着视口变化而变化的vw单位,这样就可以实现动态改变其大小
  • 限制根元素字体大小的最大最小值,配合body加上最大宽度和最小宽度
    // rem 单位换算:定为 75px 只是方便运算,750px-75px、640-64px、1080px-108px,如此类推
    $vm_fontsize: 75; // iPhone 6尺寸的根元素大小基准值
    @function rem($px) {
         @return ($px / $vm_fontsize ) * 1rem;
    }
    // 根元素大小使用 vw 单位
    $vm_design: 750;
    html {
        font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw; 
        // 同时,通过Media Queries 限制根元素最大最小值
        @media screen and (max-width: 320px) {
            font-size: 64px;
        }
        @media screen and (min-width: 540px) {
            font-size: 108px;
        }
    }
    // body 也增加最大最小宽度限制,避免默认100%宽度的 block 元素跟随 body 而过大过小
    body {
        max-width: 540px;
        min-width: 320px;
    }
    复制代码
    

5.图片响应式

这里的图片响应式包括两个方面,一个就是大小自适应,这样能够保证图片在不同的屏幕分辨率下出现压缩、拉伸的情况;一个就是根据不同的屏幕分辨率和设备像素比来尽可能选择高分辨率的图片,也就是当在小屏幕上不需要高清图或大图,这样我们用小图代替,就可以减少网络带宽了。

1.使用max-width(图片自适应):

图片自适应意思就是图片能随着容器的大小进行缩放,可以采用如下代码:

img { display: inline-block; max-width: 100%; height: auto; } 复制代码 

inline-block 元素相对于它周围的内容以内联形式呈现,但与内联不同的是,这种情况下我们可以设置宽度和高度。 max-width保证了图片能够随着容器的进行等宽扩充(即保证所有图片最大显示为其自身的 100%。此时,如果包含图片的元素比图片固有宽度小,图片会缩放占满最大可用空间),而heightauto可以保证图片进行等比缩放而不至于失真。如果是背景图片的话要灵活运用background-size属性。

那么为什么不能用width:100%呢?因为这条规则会导致它显示得跟它的容器一样宽。在容器比图片宽得多的情况下,图片会被无谓地拉伸。

2.使用srcset

前端响应式布局原理与方案(详细版) 复制代码 

如果屏幕的dpi = 1的话则加载1倍图,而dpi = 2则加载2倍图,手机和mac基本上dpi都达到了2以上,这样子对于普通屏幕来说不会浪费流量,而对于视网膜屏来说又有高清的体验。

如果浏览器不支持srcset,则默认加载src里面的图片。

但是你会发现实际情况并不是如此,在Mac上的Chrome它会同时加载srcset里面的那张2x的,还会再去加载src里面的那张,加载两张图片。顺序是先把所有srcset里面的加载完了,再去加载src的。这个策略比较奇怪,它居然会加载两张图片,如果不写src,则不会加载两张,但是兼容性就没那么好。这个可能是因为浏览器认为,既然有srcset就不用写src了,如果写了src,用户可能是有用的。而使用picture就不会加载两张

3.使用background-image

.banner{ background-image: url(/static/large.jpg); } @media screen and (max-width: 767px){ background-image: url(/static/small.jpg); } 复制代码 

4.使用picture标签

picturefill.min.js :解决IE等浏览器不支持 的问题

 
   
     前端响应式布局原理与方案(详细版)  
   
    复制代码 

picture必须要写img标签,否则无法显示,对picture的操作最后都是在img上面,例如onload事件是在img标签触发的,picturesource是不会进行layout的,它们的宽和高都是0。

另外使用source,还可以对图片格式做一些兼容处理:

 
   
    前端响应式布局原理与方案(详细版)  
   复制代码 

总结:响应式布局的实现可以通过媒体查询+px,媒体查询+百分比,媒体查询+rem+js,vm/vh,vm/vh +rem这几种方式来实现。但每一种方式都是有缺点的,媒体查询需要选取主流设备宽度尺寸作为断点针对性写额外的样式进行适配,但这样做会比较麻烦,只能在选取的几个主流设备尺寸下呈现完美适配,另外用户体验也不友好,布局在响应断点范围内的分辨率下维持不变,而在响应断点切换的瞬间,布局带来断层式的切换变化,如同卡带的唱机般“咔咔咔”地一下又一下。通过百分比来适配首先是计算麻烦,第二各个属性中如果使用百分比,其相对的元素的属性并不是唯一的,这样就造成我们使用百分比单位容易使布局问题变得复杂。通过采用rem单位的动态计算的弹性布局,则是需要在头部内嵌一段脚本来进行监听分辨率的变化来动态改变根元素字体大小,使得CSSJS 耦合了在一起。通过利用纯css视口单位实现适配的页面,是既能解决响应式断层问题,又能解决脚本依赖的问题的,但是兼容性还没有完全能结构接受。

响应式布局的成型方案

现在的css,UI框架等都已经考虑到了适配不同屏幕分辨率的问题,实际项目中我们可以直接使用这些新特性和框架来实现响应式布局。可以有以下选择方案:

  • 利用上面的方法自己来实现,比如CSS3 Media Query,rem,vw等
  • Flex弹性布局,兼容性较差
  • Grid网格布局,兼容性较差
  • Columns栅格系统,往往需要依赖某个UI库,如Bootstrap

响应式布局的要点

在实际项目中,我们可能需要综合上面的方案,比如用rem来做字体的适配,用srcset来做图片的响应式,宽度可以用remflex,栅格系统等来实现响应式,然后可能还需要利用媒体查询来作为响应式布局的基础,因此综合上面的实现方案,项目中实现响应式布局需要注意下面几点:

  • 设置viewport
  • 媒体查询
  • 字体的适配(字体单位)
  • 百分比布局
  • 图片的适配(图片的响应式)
  • 结合flex,grid,BFC,栅格系统等已经成型的方案

参考文章:

  1. 响应式布局的常用解决方案对比(媒体查询、百分比、rem和vw/vh)
  2. 纯CSS3使用vw和vh视口单位实现自适应
  3. 你真的了解响应式布局吗?
  4. 移动端H5页面 iphone6的适配技巧
  5. 响应式开发心得
  6. 详解前端响应式布局、响应式图片,与自制栅格系统
  7. 基于媒体查询和 rem 的响应式布局实践
  8. 从网易与淘宝的font-size思考前端设计稿与工作流
  9. 移动端前端适配方案对比
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228235.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午7:30
下一篇 2026年3月16日 下午7:30


相关推荐

  • java+SQL做学生信息管理系统(增删改查)学生新作「建议收藏」

    java+SQL做学生信息管理系统(增删改查)学生新作「建议收藏」java+SQL做学生信息管理系统(增删改查)过程中需要用到的所有工具数据库以及数据库管理器等等密码:q80t大学学习java后做的第一个小项目忍不住分享一下,也是我自己的面向对象编程的实践作业啦,有点水,不是很优。废话不多数,下面进入正题界面的编写是非常简单的,直接贴代码了,首先看添加功能Add.javaimportjavax.swing.*;importjava.awt.*…

    2026年4月15日
    6
  • JS实现图片循环滚动

    JS实现图片循环滚动之前在前端的时候有遇到这样一个问题,实现JS图片的循环滚动,然后鼠标移入的时候停止滚动,鼠标移开继续滚动,这里无非就是设置了一个定时器,鼠标移上时清除定时器达到滚动停止的目的,鼠标移开时重设定时器,代码如下:<!DOCTYPE><html> <head> <metacharset=”UTF-8″> <title>JS实…

    2022年7月18日
    16
  • 重启Oracle服务

    重启Oracle服务有时需要重启 Oracle 服务 在系统服务中点击 停止 后再点击 启动 实在是很麻烦 可以将要重启的 Oracle 服务放在一个批处理文件中批量执行 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 创建停止 Oracle 服务的批处理文件 stopOracle bat 内容如下 setechooff nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp netstopOracl nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp netstopOracl

    2026年3月16日
    1
  • Python列表建议收藏

    在python中有六种内建的序列:列表、元祖、字符串、Unicode字符串、buffer对象和xrange对象。通用序列操作:1.索引(indexing)2.分片(slicing)3.

    2021年12月18日
    53
  • Php公众号40029,微信开发之微信公众平台,网页授权及 40029 问题解决

    Php公众号40029,微信开发之微信公众平台,网页授权及 40029 问题解决本文将带你了解微信开发微信公众平台,网页授权及40029问题解决,希望本文对大家学微信有所帮助。1、跳转授权链接https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxx&redirect_uri=xxx&response_type=code&scope=snsapi_userinfo&state=…

    2022年4月29日
    48
  • 二叉树性质总结

    二叉树性质总结性质1:二叉树第i(i>=1)层上的节点数最多为2^(i-1)证明:归纳基础:第一层有一个节点,第二层最多有两个节点,第三层最多有四个节点,以此类推,数学归纳法证明如下:i=1时,2^(i-1)=2^0=1,因为第一层上为根节点,所以命题成立。归纳假设:假设对所有的j(1归纳步骤:根据归纳假设,第i-1层上至多有2(i-2)个节点,由于二叉树每个节点至多有两个孩子节点,所以第i

    2022年5月6日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号