我的回答

  1. rem, 通过修改根节点字体大小
  2. %, 百分百
  3. vw, vh, 视窗大小
  4. queryScreen, 媒体查询
  5. flex
  6. grid

参考回答

响应式布局

Responsive design,意在实现不同屏幕分辨率的终端上浏览网页的不同展示方式。通过响应式设计能使网站在手机和平板电脑上有更好的浏览阅读体验。
传统的开发模式是pc端开发一套,手机端在开发一套,而使用响应式布局只要开发一套就够,缺点是依赖css比较严重

响应式布局实现方案

1. 媒体查询

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

  • 1.如何选择屏幕大小分割点 如何确定媒体查询的分割点也是一个开发中会遇到的问题,不同品牌和型号的设备屏幕分辨率一般都不一样

    1. 选择600px,900px,1200px,1800px作为分割点,也可以选择480px,800px,1400px,1400px作为分割点
    2. 如果自己确定分割点不好确定,可以参考经典的响应式布局框架,Bootstrap是如何进行断点的。
    3. 超小屏幕手机 <768px
    4. 小屏幕 平板 >=768px
    5. 中等屏幕 桌面显示器 >=992px
    6. 大屏幕 大桌面显示器 >=1200px
  • 2.移动优先 or PC优先 不管是移动还是pc优先,都是依据当随着屏幕宽度增大或减少的时候,后面的样式会覆盖前面的样式。因此,移动端优先使用的是min-width, pc端优先使用的max-width

    1. /* 移动优先 */
    2. /* iphone6 7 8 */
    3. body{
    4. background-color:red;
    5. }
    6. /* iphone5 */
    7. @media screen and (max-width:320px){
    8. body{
    9. background-color:green
    10. }
    11. }
    12. /* iphoneX */
    13. @media screen and (min-width:375px) and (-webkit-device-pixel-ratio:3){
    14. body{
    15. background-color:black;
    16. }
    17. }
    18. /* iphone6 7 8 plus */
    19. @media screen and (min-width:414px){
    20. body{
    21. background-color:pink;
    22. }
    23. }
    24. /* ipad */
    25. @media screen and (min-width:768px){
    26. body{
    27. background-color:blue;
    28. }
    29. }
    30. /* ipad pro */
    31. @media screen and (min-width:1024px){
    32. body{
    33. background-color:orange;
    34. }
    35. }
    36. /* pc */
    37. @media screen and (min-width:1100px){
    38. body{
    39. background-color:#333;
    40. }
    41. }
    1. /* pc优先 pc.width > 1024px*/
    2. /* pc */
    3. body{
    4. background-color:red;
    5. }
    6. /* iphone 6 7 8 */
    7. @media screen and (max-width:375px) and (-webkit-device-pixel-ratio:2){
    8. body{
    9. background-color:green
    10. }
    11. }
    12. /* iphoneX */
    13. @media screen and (max-width:375px) and (-webkit-device-pixel-ratio:3){
    14. body{
    15. background-color:black;
    16. }
    17. }
    18. /* iphone6 7 8 plus */
    19. @media screen and (max-width:414px){
    20. body{
    21. background-color:pink;
    22. }
    23. }
    24. /* ipad */
    25. @media screen and (max-width:768px){
    26. body{
    27. background-color:blue;
    28. }
    29. }
    30. /* ipad pro */
    31. @media screen and (max-width:1024px){
    32. body{
    33. background-color:orange;
    34. }
    35. }
    36. /* iphone 5 */
    37. @media screen and (max-width:320px){
    38. body{
    39. background-color:#333;
    40. }
    41. }

    2. 百分比布局

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

如果使用百分比布局,我们必须弄清楚css中子元素的百分比到底是相对谁的百分比。

  • 子元素的height或width中使用百分比,是相对于子元素的直接父元素,width相对于父元素的width,height相对于父元素的height
  • 子元素的top和bottom如果设置百分比,则相对于非static定位(默认定位)的父元素的高度,同样子元素的left和right如果设置百分比,则相对于直接非static定位(默认定位)父元素的宽度
  • 子元素的padding如果设置百分比,不论是垂直方向或者水平方向,都是相对于直接父元素的width,而与父元素的height无关
  • 跟padding一样,margin也是如此,子元素的margin如果设置成百分比,不论是垂直方向或是水平方向,都相对于直接父元素的width
  • border-radius不一样,如果设置border-radius为百分比,则是相对于自身的宽度
  • 除了border-radius之外,还有比如translate、background-size等都是相对于自身的

所以百分比布局有明显的两个缺点:

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

    3. rem布局

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

  • 1.rem响应式的布局思想

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

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

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

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

  1. /* pc优先 pc.width > 1100px*/
  2. html{
  3. font-size:100%;
  4. }
  5. body{
  6. background-color:red;
  7. font-size:1.5rem;
  8. }
  9. /* ipad pro */
  10. @media screen and (max-width:1024px){
  11. body{
  12. background-color:green;
  13. font-size:1.4rem;
  14. }
  15. }
  16. /* iphoneX */
  17. @media screen and (max-width:375px) and (-webkit-device-pixel-ratio:3){
  18. body{
  19. background-color:black;
  20. font-size:1.125rem;
  21. }
  22. }
  23. /* iphone6 7 8 */
  24. @media screen and (max-width:375px)and (-webkit-device-pixel-ratio:2){
  25. body{
  26. background-color:pink;
  27. font-size:1rem;
  28. }
  29. }
  30. /* iphone6 7 8 pkus */
  31. @media screen and (max-width:414px){
  32. body{
  33. background-color:pink;
  34. font-size:1.25rem;
  35. }
  36. }
  37. /* ipad */
  38. @media screen and (max-width:768px){
  39. body{
  40. background-color:blue;
  41. font-size:1.3rem;
  42. }
  43. }
  44. /* iphone 5 */
  45. @media screen and (max-width:320px){
  46. body{
  47. background-color:#333;
  48. font-size:0.75rem;
  49. }
  50. }

4. 视口单位 CSS3中引入了一个新的单位vw/vh

vw/vh,与视图窗口有关,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口的高度,除了vw和vh外,还有vmin和vmax两个相关的单位

  1. vw: 相对于视图的宽度,1vw等于视口宽度的1%,即视图宽度是100vw
  2. vh: 相对于视图的高度,1vh等于视口高度的1%,即视图高度是100vh
  3. vmin:vwvh中较小的值
  4. vmax:vwvh中较大的值
    1. 仅用vw作为css单位 对于设计稿的尺寸转换为单位,我们使用Sass函数进行编译
      1. /* 作为iphone6 尺寸作为设计稿基准 */
      2. $vm_base:375;
      3. @function vw($px){
      4. @return ($px/375)*100vw
      5. }
      无论是文本还是布局宽度、间距等都使用vw作为单位
      1. .mod_nav{
      2. background:#fff;
      3. &_list{
      4. display:flex;
      5. padding:vm(15) vm(10) vm(10);//内间距
      6. &_item{
      7. flex1;
      8. text-align:center;
      9. font-size:vm(10);//字体大小
      10. &_logo{
      11. display:block;
      12. margin:0 auto;
      13. width:vm(40);
      14. height:vm(40);
      15. img{
      16. display:block;
      17. margin:0 auto;
      18. max-width:100%;
      19. }
      20. }
      21. &_name{
      22. margin-top:vm(2);
      23. }
      24. }
      25. }
      26. }
  • 2.搭配vw和rem 虽然采用vw适配后的页面效果很好,但是它是利用视口单位实现的布局,依赖视口大小而自动缩放,无论视口过大还是过小,它也随之过大或者过小,失去了最大最小宽度的限制,此时我们可以结合rem来实现布局

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

    5. 图片响应式

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

    1. 使用max-width(图片自适应) 图片自适应意思是图片能随着容器的大小进行缩放
      1. img{
      2. display:inline-block;
      3. max-width:100%;
      4. height:auto;
      5. }
  • 2.使用srcset

    1. <img srcset="photo_w350.jpg 1x,photo_w640.jpg 2x" src="地址" alt="" >

    如果屏幕的dpi=1的话则加载1倍图,而dpi=2的话则加载2倍图,手机和mac基本上dpi都达到了2以上,这样子对于普通屏幕来说不会浪费,而对于视网膜屏来说又有高清的体验,如果浏览器不支持srcset,则默认加载src里面的图片

  • 3.使用background-image

    1. .bar{
    2. background-image:url(/public/commonmax.jpg);
    3. }
    4. @media screen and (max-width:767px){
    5. background-image:url(/public/commonmin.jpg);
    6. }
  • 4.使用picture标签 解决IE等浏览器不支持的问题,可以引入picturefill.min.js

    1. // picturefill.min.js
    2. <picture>
    3. <source srcset="banner_w100jpg" media="(min-width:801px)">
    4. <source srcset="banner_w80jpg" media="(max-width:800px)">
    5. <img src="banner_w80.jpg" alt="">
    6. </picture>
  • 6.总结

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

    响应式布局成型方案

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

  1. 利用前面介绍的方法自己来实现,比如CSS3 media、rem等
  2. flex弹性布局
  3. Grid网格布局
  4. Columns栅格系统,往往需要依赖某个ui库,Bootstrap