# 自适应和响应式（移动端适配）

### 是什么

什么是自适应布局：同一张网页自动适应不同大小的屏幕，根据屏幕宽度，自动调整网页内容大小。

什么是响应式布局：可以自动识别屏幕宽度、并做出相应调整的网页设计，布局和展示的内容可能会有所变动。

区别：如果网页内容过多，整体会显得拥挤。所以响应式布局是自适应布局的改进，布局和展示的内容可能会有所变动。



### 为什么

- 屏幕显示器的分辨率越来越多样化，在pc端和手机端需要做样式上的平衡，如果每个屏显都需要一套独立的网页或者样式，会加大工作量
- 单纯使用meta-viewport虽然可以解决部分问题，但是单纯的进行缩放，达到的平衡点，用户体验不佳

如携程的pc 和手机版效果

![image-20201221112132098](自适应和响应式.assets/image-20201221112132098.png)

segmentfault网站的响应式布局：

![image-20201221112409483](自适应和响应式.assets/image-20201221112409483.png)

如果想要更好的用户体验，建议使用响应式布局



### 怎么做

1.  媒体查询（media query）	

   ​	媒体查询就是对设备按照某些条件进行查询，使符合条件的设备显示对应的样式  从而实现不同设备样式不同的效果
   语法：

   @media (max-width: 屏幕最大宽度){

   ​	...  符合条件的样式  跟style样式表一样 含多个元素样式

   }

   

   示例：

   ```
   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Document</title>
       <style>
            @media (max-width: 960px){ /*屏幕宽度为0~960的样式*/
               body{
                   background: gold;
               }
            
            }
            @media (max-width: 760px){ /*屏幕宽度为0~760的样式*/
               body{
                   background: pink;
               }
            
            }
            @media (max-width: 640px){ /*屏幕宽度为0~640的样式*/
               body{
                   background: pink;
               }
            
            }
            @media (max-width: 520px){ /*屏幕宽度为0~520的样式*/
               body{
                   background: blue;
               }
            
            }
            @media (max-width: 480px){ /*屏幕宽度为0~480的样式*/
               body{
                   background:gray
               }
            
            }
       </style>
   </head>
   <body>
       
   </body>
   </html>
   ```

   

效果参考b.html 运行



2.  百分比布局

   通过百分比单位 " % " 来实现响应式的效果。 比如当浏览器的宽度或者高度发生变化时，通过百分比单位，可以使得浏览器中的组件的宽和高随着浏览器的变化而变化，从而实现响应式的效果

   示例：

   ```
   <!DOCTYPE html>  
     <!--  -->
   <html lang="en">
   
   <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Document</title>
       <style>
           .box{
              width: 900px;
              height: 600px;
              background:orange;
           }
           .item1{
               width: 40%;
               height:80%;
               background: paleturquoise;
               float: left;
           }
           .item2{
               width:40%;
               height: 80%;
               background: blue;
               float: right;
           }
       </style>
   </head>
   
   <body>
     <div class="box">
         <div class="item1"></div>
         <div class="item2"></div>
     </div>
   </body>
   </html>
   ```

   ![image-20201221143946222](自适应和响应式.assets/image-20201221143946222.png)

3. rem

   rem是一个相对单位，1rem等于html元素上字体设置的大小。我们只要设置html上font-size的大小，就可以改变rem所代表的大小。**其实rem布局的本质是等比缩放，一般是基于宽度**.

   这样我们就有了一个可控的统一参考系。我们现在有两个目标：

   - rem单位所代表的尺寸大小和屏幕宽度成正比，也就是设置html元素的font-size和屏幕宽度成正比
   - rem单位和px单位很容易进行换算，方便我们按照标注稿写css

   

使用：

借助js

```
//designWidth:设计稿的实际宽度值，需要根据实际设置
//maxWidth:制作稿的最大宽度值，需要根据实际设置
//这段js的最后面有两个参数记得要设置，一个为设计稿实际宽度，一个为制作稿最大宽度，例如设计稿为750，最大宽度为750，则为(750,750)
;(function(designWidth, maxWidth) {
	var doc = document,
	win = window,
	docEl = doc.documentElement,
	remStyle = document.createElement("style"),
	tid;

	function refreshRem() {
		var width = docEl.getBoundingClientRect().width;
		maxWidth = maxWidth || 540;
		width>maxWidth && (width=maxWidth);
		var rem = width * 100 / designWidth;
		remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
	}

	if (docEl.firstElementChild) {
		docEl.firstElementChild.appendChild(remStyle);
	} else {
		var wrap = doc.createElement("div");
		wrap.appendChild(remStyle);
		doc.write(wrap.innerHTML);
		wrap = null;
	}
	//要等 wiewport 设置好后才能执行 refreshRem，不然 refreshRem 会执行2次；
	refreshRem();

	win.addEventListener("resize", function() {
		clearTimeout(tid); //防止执行两次
		tid = setTimeout(refreshRem, 300);
	}, false);

	win.addEventListener("pageshow", function(e) {
		if (e.persisted) { // 浏览器后退的时候重新计算
			clearTimeout(tid);
			tid = setTimeout(refreshRem, 300);
		}
	}, false);

	if (doc.readyState === "complete") {
		doc.body.style.fontSize = "16px";
	} else {
		doc.addEventListener("DOMContentLoaded", function(e) {
			doc.body.style.fontSize = "16px";
		}, false);
	}
})(750, 750);
/*
	第一个参数是设计稿的宽度，一般设计稿有640，或者是750，你可以根据实际调整
	第二个参数则是设置制作稿的最大宽度，超过750，则以750为最大限制。
*/
```

1.复制上面这段代码到你的页面的头部的script标签的最前面。

2.根据设计稿大小，调整里面的最后两个参数值。

3.使用1rem=100px转换你的设计稿的像素，例如设计稿上某个块是100px*300px,换算成rem则为1rem*3rem。

