移動適配布局
1. 像素有關
1.1 設備像素(物理像素 )
顯示器的最小物理單位(對于一個顯示器來說是固定的)
以手機屏幕為例,屏幕上的真實像素點。iphone6 的設備像素 750 * 1334
通常說的4K顯示屏指的是 4096x2160。(像素多少是由生產(chǎn)廠商生產(chǎn)決定的),就是設備像素,物理像素。
1.2 CSS像素
CSS 中的長度單位,在 CSS 中使用的 px 都是指 CSS 像素,width:200px。
在頁面不縮放的情況下,1px的CSS像素 === 1設備像素===1物理像素
頁面放大200%時,頁面的設備物理像素依舊不變,放大的是CSS像素。但是此時CSS像素與設備物理像素的關系變化了,1css像素 === 4設備物理像素(寬x2,高x2兩個方向都放大)
1.3 設備獨立像素(獨立像素)(虛擬的窗口)
可以通過 window.screen.width/ window.screen.height 查看 375
操作系統(tǒng)定義的一種長度單位。iphone6 的設備獨立像素,
設備(手機)的寬度是固定的,不是將網(wǎng)頁設置的css寬度直接壓縮到設備寬度上,而是另外一個像素概念--設備獨立像素

早期網(wǎng)頁版心980px。
設備像素:獲取設備屏幕寬/高window.screen.width/height 控制臺切換到手機端,寬高也會跟著變化。
設備獨立像素:window.innerWidth,對于PC沒有設備獨立像素的概念,PC端就是視口的顯示的寬度,手機端則始終是個固定的值--設備獨立像素,980或1000等。
<meta name="viewport" content="width=device-width, initial-scale=1.0">
這段代碼是視口的配置:代表自適應,viewport就是視口,處理視口的寬度為設備的寬度,縮放比例是1.0
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 視口的配置:沒有這段代碼,移動端窗口就不會自適應,就會出現(xiàn)滾動條,比如iphone5 320px 而css寬度是980px -->
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
overflow: auto;
}
#box {
width: 980px;
height: 200px;
background: pink;
font-size: 18px;
}
</style>
</head>
<body>
<div id="box">11111111</div>
</body>
1.4 PPI
- 指每英寸的物理像素數(shù)
- 以尺寸為5.8英寸(屏幕對角線長度)屏幕對角線上的像素點 / 對角線的英寸數(shù)
1.5 devicePixelRatio 設備像素比(dpr)
- devicePixelRatio指的是物理像素和設備獨立像素的比 即1獨立像素由多少物理像素渲染。
- window.devicePixelRatio可查看
- window.devicePixelRatio = 物理像素 / 獨立像素
1.6 解決移動端1像素的問題
因為不同設備具有不同的dpr 所以,css1px 所代表的設備像素不同, 所以在有些設備上看到的粗,有些設備看到的細,如果解決一像素邊框問題,
方法一
通過媒體查詢,查詢設備的dpr,根據(jù)dpr設置不同的寬度大小
#box{
height: 200px;
border-bottom:1px solid red;
}
@media screen and (-webkit-min-device-pixel-ratio: 2) {
#box { border-bottom: 0.5px solid #999 }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
#box{ border-bottom: 0.333333px solid blue }
}
缺點: 小數(shù)像素目前兼容性較差,一些以前的版本可能不支持。
理論上最小的單位是 1px。 所以會出現(xiàn)有的設備寫 0.5px 無效(沒有邊框)的情況。
方法二: 借助偽元素縮放處理
.button:after{
content: "";
display: block;
height: 0;
border-top: #999 solid 1px;
width: 100%;
position: absolute;
top: 0;
right: 0;
transform: scaleY(0.5); /* 將 1px 的線條縮小為原來的 50% */
}
缺點: 不是所有設備的dpr都是2 所以固定縮放0.5 也會有問題
方法三借助媒體查詢和偽元素縮放來解決
// 定義mixin
.border-1px(@color: rgba(7,17,27,0.2)){
position:relative;
&:after{
display:block;
position:absolute;
left:0;
bottom:0;
content:'';
width:100%;
border-top:1px solid @color;
}
}
// 根據(jù)不同的dpr 使用不同的縮放
@media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5){
.border-1px {
.border-1px;
&:after {
-webkit-transform: scaleY(0.7);
-moz-transform: scaleY(0.7);
-ms-transform: scaleY(0.7);
-o-transform: scaleY(0.7);
transform: scaleY(0.7);
}
}
}
@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2){
.border-1px {
.border-1px;
&:after {
-webkit-transform: scaleY(0.5);
-moz-transform: scaleY(0.5);
-ms-transform: scaleY(0.5);
-o-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
}
@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3){
.border-1px {
.border-1px;
&:after {
-webkit-transform: scaleY(0.3);
-moz-transform: scaleY(0.3);
-ms-transform: scaleY(0.3);
-o-transform: scaleY(0.3);
transform: scaleY(0.3);
}
}
}
2. viewport
2.1 什么是視口
在移動端viewport視口就是瀏覽器顯示頁面內容的屏幕區(qū)域,
在viewport中有兩種視口,分別表示為 :
- visual viewport (可視視口) 正常屏幕視口
- layout viewport (布局視口) 設備獨立像素 默認980px
兩個視口是疊加在一起
visual viewport 固定大小跟屏幕大小相同, 可以通過window.innerWidth 來獲取.
layout viewport 可改變大小, 默認大小為980像素, 可以通過document.documentElement.clientWidth 獲取
視口默認的寬度是980px,我們可以用meta標簽來舒服視口看度.此時視口寬度被束縛為320-480之間(不同的手機)
現(xiàn)代網(wǎng)頁需要將layout viewport 設置成跟visual viewport 相同的大小,方便網(wǎng)頁制作
2.2 視口的設置
通過<meta>標簽進行設置,name屬性指定viewport的值,content屬性進行視口配置
<meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=false,maximum-scale=2.0" >
| 取值 | 含義 |
|---|---|
| width | 設置layout view的寬度為特定值 device-width表示設備的寬度 |
| height | 設置layout view的寬度為特定值,一般不設置 |
| initial-scale | 設置頁面初始縮放 |
| minimum-scale | 設置頁面最小縮放 |
| maximum-scale | 設置頁面的最大縮放 |
| user-scalable | 設置頁面能否縮放 允許user-scalable=true ,不允許user-scalable=false |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- 針對IE瀏覽器,盡量選擇IE=edge -->
<meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=false,maximum-scale=2.0">
<!--原信息 視口原信息 內容寬度layout viewport設備獨立像素視口寬度等于設備的視口寬度。user-scalable=false 不允許縮放 -->
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
overflow: auto;
}
#box {
width: 980px;
/* 如果超出設備寬度就會出現(xiàn)滾動條,不超就沒有滾動條 */
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div id="box">ddddddddd</div>
</body>
</html>
3.適配
3.1、為什么要做適配
a) 為了適應各種移動端設備,完美呈現(xiàn)應有的布局效果
b) 各個移動端設備,分辨率大小不一致,網(wǎng)頁想鋪滿整個屏幕,并在各種分辨下等比縮放
現(xiàn)在主流的開發(fā)思路
- PC端 和移動端 分開開發(fā)
- 如果想在既能適應PC、又能適應移動端 響應式開發(fā)(麻煩 寫好多套css )
3.2、自適應適配方案(布局方案)
3.2.1 先了解一些單位
em: 相對單位, 1em等于當前元素的font-size值
rem 相對單位 r -> root 根節(jié)點( html ) 根據(jù)html的字體大小計算其他元素尺寸 1rem 就是html的font-size值
vw/vh ; 把屏幕分為100份, 1vw就等于屏幕寬度的1%。也就是元素的寬高根據(jù)屏幕尺寸來定的。
width:300%;寬度值為百分比時是相對于父級寬度值的。
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 200px;
height: 200px;
background-color: pink;
}
#wrap {
width: 50vw; /* 元素的寬度根據(jù)視口來定 */
height: 100px;
background-color: blue;
}
</style>
</head>
<body>
<div id="box">
<div id="wrap"></div>
</div>
</body>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!--縮放比例:移動端css像素自適應設備像素 -->
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 50vw;
/*寬度始終是屏幕的一半*/
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
3.2.2 媒體查詢布局方式
meida queries 的方式可以說是早期采用的布局方式,它主要是通過查詢設備的寬度來執(zhí)行不同的 css 代碼,最終達到界面的配置。核心語法是:
@media screen and (max-width: 600px) { /*當屏幕尺寸小于600px時,應用下面的CSS樣式*/
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--縮放比例:移動端css像素自適應設備像素 -->
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
overflow: auto;
}
#box {
height: 200px;
background: pink;
}
/* 媒體查詢做適配 */
@media screen and (width: 320px) {
#box {
width: 160px;
}
}
@media screen and (width: 375.2px) {
#box {
width: 187.5px;
}
}
@media screen and (width: 414px) {
#box {
width: 207px;
}
}
@media screen and (width: 414px) {
#box {
width: 207px;
}
}
@media screen and (width: 768px) {
#box {
width: 384px;
}
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
優(yōu)點
- 方法簡單,成本低,特別是對移動和PC維護同一套代碼的時候。
- 調整屏幕寬度的時候不用刷新頁面即可響應式展示
缺點
- 代碼量比較大,維護不方便
- 為了兼顧大屏幕或高清設備,會造成其他設備資源浪費,特別是加載圖片資源
- 為了兼顧移動端和PC端各自響應式的展示效果,難免會損失各自特有的交互方式
3.2.3 百分比與Flex布局(百分百與彈性盒模型是目前常用的布局方式)
布局的特性: 關鍵元素高寬和位置都不變,只有容器元素在做伸縮變換
這種布局是一種典型的彈性布局
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
#box {
display: flex;
/* 彈性盒模型 */
flex-wrap: wrap;
/*換行*/
justify-content: space-around;
/*水平對齊*/
width: 90%;
/* height: 200px;高度不固定,不需要啦 */
background-color: pink;
margin: 0 auto;
}
li {
width: 80px;
height: 80px;
background-color: skyblue;
margin-bottom: 10px;
}
</style>
</head>
<body>
<ul id="box">
<li>觀察文字大小</li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
布局的方式:
- 布局盒子采用百分比
- 容器盒子與文字采用固定大小
- Flex 確定位置(也可以采用浮動)
優(yōu)缺點:
- 好處: 大屏下可以展示更多內容
- 壞處: 寬屏下比例會比較不協(xié)調
注意: 這種情況css尺寸單位用px就好,不要用rem,避免增加復雜度。
例子: 拉勾網(wǎng)
3.2.4 rem布局方式
布局的特性: 關鍵元素盒子大小與文字都隨著屏幕大小不同,而展示不同的大小
布局的方式:
- 根據(jù)屏幕大小不同設置html不同的字體大小
- 所有的盒子尺寸和文字大小采用rem的布局方式
<!DOCTYPE html>
<html lang="en" style="font-size: 10px;">
<!-- rem布局 font-size如果寫死,box的width就是固定的了,不能自適應。所以font-size需要動態(tài)的-->
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
#box {
width: 30rem;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<ul id="box">
</ul>
</body>
</html>
動態(tài)設置font-size,設置方式,常用的是通過JS
首先找一個基準屏幕iphone6/7/8 375px
var fontSize= document.documentElement.clientWidth /3.75 //獲取當前屏幕的寬度/ 3.75
document.documentElement.style.fontSize = fontSize + 'px'
字體也可以不使用rem單位(通常也不建議字體用rem單位), 采用不同的媒介方式,
@media screen and (max-width:321px){
.basesize{font-size:15px}
}
@media screen and (min-width:321px) and (max-width:400px){
.basesize{font-size:16px}
}
@media screen and (min-width:400px){
.basesize{font-size:18px}
}
如果只是希望盒子根據(jù)屏幕大小不同而改變, 但是文字大小不改變,可以在body重新固定文字大小
body{
font-size:16px;
}
rem的布局--使用js動態(tài)設置font-size方式布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var fontSize = document.documentElement.clientWidth / 3.75 //基準屏的font-size為100px,整數(shù)好開發(fā)。不同寬度的屏幕,font-size會自動計算。rem布局 font-size如果寫死,box的width就是固定的了,不能自適應
document.documentElement.style.fontSize = fontSize + 'px'
</script>
<style>
* {
margin: 0;
padding: 0;
}
body {
font-size: 16px;
}
#box {
width: 1.875rem;
/*占屏幕的一半 */
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div id="box">ddddddddd
</div>
</body>
</html>
代表網(wǎng)站: 網(wǎng)易, 美團
rem另一種使用vw單位布局寫法--代表網(wǎng)易
<!DOCTYPE html>
<!-- 網(wǎng)易不使用js處理基準值,使用vw處理基準值 一份是375/100 共有 100/3.75 份 -->
<html lang="en" style="font-size:26.666vw;">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
font-size: 16px;
}
#box {
width: 1.875rem;
/*占屏幕的一半 */
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div id="box">ddddddddd
</div>
</body>
</html>
3.2.5 縮放布局方式
.固定高度寬度.文字大小,通過改變縮放比例適配
根據(jù)屏幕的分辨率動態(tài)設置適配縮放比例,達到等比縮放的功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Document</title>
<script>
let baseWidth = 375;//定義基準頁面進行開發(fā),然后以這個基準頁面為準進行縮放
let screeWidth = window.screen.width;//獲取當前設備屏幕寬度
console.log(screeWidth)
let scale = screeWidth / baseWidth;//縮放比例=屏幕寬度/基準值
console.log(scale);
let meta = document.createElement('meta')//創(chuàng)建meta標簽
meta.setAttribute('name', 'viewport')// 添加name屬性也可以meta.name='viewport'
//添加content屬性
meta.setAttribute('content', `width=${baseWidth},initial-scale=${scale},minimun-sacle=${scale},maximun-scale=${scale},user-scalable=no`);
document.head.appendChild(meta)//將meta標簽添加到頁面上 實現(xiàn)適配當前手機屏幕的寬度,視口寬度等于設備寬度,不出現(xiàn)滾動條或空白區(qū)域了
</script>
<style>
* {
margin: 0;
padding: 0;
}
body {
overflow: auto;
/* 超出自動加滾動條 */
}
#box {
width: 375px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div id="box">ddddddddd</div>
</body>
</html>
根據(jù)dpr來設置不同的viewport縮放比例
// 改變視口的縮放比例
(function(){
// 方法一
var width = window.screen.width;
var fixedW = 375;
var scale = width / fixedW;
var meta = document.createElement('meta');
meta.setAttribute('name','viewport');
meta.setAttribute('content',`width=${fixedW},initial-scale=${scale},minimun-sacle=${scale},maximun-scale=${scale},user-scalable=no`);
document.head.appendChild(meta);
})()
如果是double設計圖(雙倍屏,真實的設備上有雙倍的像素點)
// 改變視口的縮放比例
(function(){
// 方法一
var width = window.screen.width;
var fixedW = 375;
var scale = width / fixedW * 0.5;
var meta = document.createElement('meta');
meta.setAttribute('name','viewport');
meta.setAttribute('content',`width=${fixedW},initial-scale=${scale},minimun-sacle=${scale},maximun-scale=${scale},user-scalable=no`);
document.head.appendChild(meta);
})()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Document</title>
<script>
let baseWidth = 375;//定義基準頁面進行開發(fā),然后以這個基準頁面為準進行縮放
let screeWidth = window.screen.width;//獲取當前設備屏幕寬度
let scale = screeWidth / baseWidth * .5;//基準值保留375,這里要縮小.5倍.縮放比例=屏幕寬度/基準值
let meta = document.createElement('meta')//創(chuàng)建meta標簽
meta.setAttribute('name', 'viewport')// 添加name屬性也可以meta.name='viewport'
//添加content屬性
meta.setAttribute('content', `width=${baseWidth},initial-scale=${scale},minimun-sacle=${scale},maximun-scale=${scale},user-scalable=no`);
document.head.appendChild(meta)//將meta標簽添加到頁面上 實現(xiàn)適配當前手機屏幕的寬度,視口寬度等于設備寬度,不出現(xiàn)滾動條或空白區(qū)域了
</script>
<style>
* {
margin: 0;
padding: 0;
}
body {
overflow: auto;
/* 超出自動加滾動條 */
}
#box {
width: 750px;
/* UI給的設計圖一般750px 放大2倍*/
height: 400px;
/*放大2倍*/
font-size: 32px;
/*字體也放大2倍*/
background-color: pink;
}
</style>
</head>
<body>
<div id="box">ddddddddd</div>
</body>
</html>
3.3 通過vw設置 html 字體
以iphone6為例 375px=100vw 1vw = 3.75
如果我希望 html的字體大小是100px
html{
font-size:26.6666667vw;
}
如果切換到iphone 6plus 1vw = 4.41px
注意, 要給body重置一下font-size: 16px;
3.4 其他小技巧
3.4.1固比固
三欄布局,
利用box-sizing
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
#wrap {
position: relative;
box-sizing: border-box;
/* 怪異盒模型 */
padding: 0 50px;
width: 100%;
height: 60px;
background-color: skyblue;
}
#left,
#right {
width: 50px;
height: 40px;
;
background-color: red;
}
#left {
position: absolute;
top: 0;
left: 0;
}
#right {
position: absolute;
top: 0;
right: 0;
}
</style>
</head>
<body>
<div id="wrap">
<div id="left"></div>
<div id="middle">
左右固定50 中間部分放大縮小</div>
<div id="right"></div>
</div>
</body>
</html>
利用flex
#box{
width: 100%;
height: 60px;
display:flex;
}
#box .left{
width:60px;
height: 100%;
background-color: red;
}
#box .content{
flex:1;
height: 100%;
background-color: blue;
}
#box .right{
width:60px;
height: 100%;
background-color: yellow;
}
3.4.2 設置高度按比例變換
- 不設置高度
盒子不設置高度,圖片寬度100%,高度默認按比例縮放
2.采用padding-top給盒子設置自動,然后用背景圖
一個元素的padding、margin值的百分比是相對于父元素的寬度的百分比。
借用padding-top來處理,我們知道padding也可以顯示背景
width: 60%;
height: 0;
padding-top:60%;
padding-bottom也可以但是,padding-top更好一點 ,因為可以overflow:hidden ;關閉超出的部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Document</title>
<style>
* {
margin: 0;
}
#img-wrap {
position: relative;
padding-top: 50%;
background-color: pink;
}
#img {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, 0)
}
</style>
</head>
<body>
<!--避免 圖片有時加載速度很慢,可能會一點點加載,會破壞布局 -->
<div id="img-wrap">
<img id="img" height="207" src="./images/3333.jpg" alt="">
<!--圖片不顯示時,該有的占位還存在 -->
</div>
<div> 大家好</div>
</body>
</html>
3.通過js
var boxWidth = parseInt(getComputedStyle(box)['width']);
box.style.height = boxWidth+'px'
補充:
http://gs.statcounter.com 瀏覽器市場占比
https://h5.m.taobao.com/#index 手機淘寶 rem http://m.jd.com/ 手機京東 100% http://jx.tmall.com/ 天貓 100% http://3g.163.com/touch/all?nav=1&version=v_standard 網(wǎng)易 rem
http://www.cnblogs.com/2050/p/3877280.html viewport 解析 meta解析 http://ljinkai.github.io/2015/06/06/mobile-web-skill/ 移動端布局注意技巧