淺談-web螢幕適配的解決方案
就目前看來,web的螢幕適配是貫穿整個前端行業的,如常見的PC端,移動端,響應式,小程式等。
PC端
特點
PC端的螢幕具備以下特點:
- 螢幕大小一般是大於
13.3英寸
- 使用者會經常拖拉瀏覽器的大小
原因
正是因為 PC端上的瀏覽器大小會經常被改變,而且改變的範圍還很大,使用者會全屏瀏覽器,使用者也會縮小瀏覽器到一個很小的值,如600px左右。 所以pc端上如果使用流式佈局(百分比佈局),會導致頁面很難看。
解決
所以,PC端上只能通過版心佈局來解決這種情況。
- 當螢幕大於版心寬度時,版心居中顯示
- 當螢幕小於版心寬度時,螢幕出現一個橫向的滾動條,這種方案几乎所有的PC端網站都在採用。
案例
程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>版心佈局</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,body{
height: 100%;
background-color: #ccc;
}
main{
width: 1200px;
height: 100%;
margin: 0 auto;
font-size: 40px;
background-color: pink;
}
header{
height: 80px;
background-color: aqua;
}
</style>
</head>
<body>
<main>
<header>版心</header>
<section>內容</section>
</main>
</body>
</html>
複製程式碼
效果
移動端
特點
移動端下的螢幕存在以下特點:
- 螢幕相比較於PC端要小
- 瀏覽器不PC端,隨時各種調整大小
原因
移動端由於螢幕整體比PC端小,而且也不能出現拖動瀏覽器來調整大小的情況,所以在移動端上的佈局是流式佈局最多,其中有些小分支,如固定小版心。
解決
流式佈局,也叫做百分比佈局,指的是頁面上大部分的容器和元素的寬度都不是定死,可能是 百分比單位,也可能是rem單位
案例
程式碼
普通的圖片和容器,寫單位的時候換成 百分比 或者 flex即可。
對於頁面中的某些元素,如字型大小,可以使用 淘寶 flexibile + rem
的解決方案
普通的流式佈局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>流式</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #ccc;
}
ul {
list-style: none;
display: flex;
height: 100px;
}
li {
flex: 1;
border: 1px solid #000;
background-color: aqua;
}
</style>
</head>
<body>
<main>
<section>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
</main>
</body>
</html>
複製程式碼
效果
淘寶flexible + rem
flexible 和flex佈局沒關係 老婆和老婆餅 也沒有關係
這個解決方案是可以和以上的流式佈局搭配使用的,rem的作用是主要是針對字型實現 跟隨螢幕變化而變化
-
rem css單位,相對長度,它的值等於根標籤的字型大小如
<style> html { font-size: 100px; } div { /* 相對於 100px */ font-size: 1rem; } </style> <div> rem單位 </div> 複製程式碼
效果
-
淘寶flexible
- 是手淘團隊出的一個處理移動端rem設定的js庫
- 把根標籤的字型大小改成了 當前螢幕的十分之一大小
- 根標籤的字型大小發生改變了,使用了rem單位的元素或者字型大小也跟著改變
流程
flexible程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>版心佈局</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
<script> (function flexible(window, document) { var docEl = document.documentElement; var dpr = window.devicePixelRatio || 1; function setBodyFontSize() { if (document.body) { document.body.style.fontSize = 12 * dpr + "px"; } else { document.addEventListener("DOMContentLoaded", setBodyFontSize); } } setBodyFontSize(); function setRemUnit() { var rem = docEl.clientWidth / 10; docEl.style.fontSize = rem + "px"; } setRemUnit(); window.addEventListener("resize", setRemUnit); window.addEventListener("pageshow", function (e) { if (e.persisted) { setRemUnit(); } }); if (dpr >= 2) { var fakeBody = document.createElement("body"); var testElement = document.createElement("div"); testElement.style.border = ".5px solid transparent"; fakeBody.appendChild(testElement); docEl.appendChild(fakeBody); if (testElement.offsetHeight === 1) { docEl.classList.add("hairlines"); } docEl.removeChild(fakeBody); } })(window, document); </script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<div>
</div>
<script>
window.onload = function () {
setFont();
window.addEventListener("resize", function () {
setFont();
})
function setFont() {
var div = document.querySelector("div");
div.style.fontSize = document.querySelector("html").style.fontSize;
div.innerHTML = "html的字型大小為" + document.querySelector("html").style.fontSize;
}
}
</script>
</body>
</html>
複製程式碼
flexible效果
綜合flexible 和 rem
根據以上的特點
flexible
把 根標籤字型大小改為 螢幕的十分之一rem
可以根據根標籤的字型大小改變而發生改變
得出以下解決方案
-
假定設計稿的寬度 是
640px
-
根標籤的字型大小為
64px
也就是1 rem = 64px
=>1px=1/64rem
-
原設計稿中的div大小為100px,字型大小為100px
-
將px單位修改為 rem單位
div{ width:100px; font-size:100px; } 修改為 div{ width:calc( 100rem / 64 ); font-size:calc( 100rem / 64 ); } 複製程式碼
-
將設計稿的寬度也抽象出去
div{ width:calc( 100rem / 十分之一的設計稿寬度 ); font-size:calc( 100rem / 十分之一的設計稿寬度 ); } 複製程式碼
完整程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>版心佈局</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
<script> (function flexible(window, document) { var docEl = document.documentElement; var dpr = window.devicePixelRatio || 1; function setBodyFontSize() { if (document.body) { document.body.style.fontSize = 12 * dpr + "px"; } else { document.addEventListener("DOMContentLoaded", setBodyFontSize); } } setBodyFontSize(); function setRemUnit() { var rem = docEl.clientWidth / 10; docEl.style.fontSize = rem + "px"; } setRemUnit(); window.addEventListener("resize", setRemUnit); window.addEventListener("pageshow", function (e) { if (e.persisted) { setRemUnit(); } }); if (dpr >= 2) { var fakeBody = document.createElement("body"); var testElement = document.createElement("div"); testElement.style.border = ".5px solid transparent"; fakeBody.appendChild(testElement); docEl.appendChild(fakeBody); if (testElement.offsetHeight === 1) { docEl.classList.add("hairlines"); } docEl.removeChild(fakeBody); } })(window, document); </script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div {
width: calc(100rem / 64);
height: calc(100rem / 64);
font-size: calc(100rem / 64);
background-color: aqua;
}
</style>
</head>
<body>
<div>
</div>
<script>
window.onload = function () {
setFont();
window.addEventListener("resize", function () {
setFont();
})
function setFont() {
var div = document.querySelector("div");
div.style.fontSize = document.querySelector("html").style.fontSize;
div.innerHTML = "html的字型大小為" + document.querySelector("html").style.fontSize;
}
}
</script>
</body>
</html>
複製程式碼
最終效果
小版心
小板心的做法其實也是流式佈局中的一種,只不過對最外層容器加了一個最大寬度的設定如
main{
max-width:540px;
}
複製程式碼
參考
小程式端
小程式端可以理解特殊的移動端,只不過小程式端不存在 rem
這個單位,取而代之的是 rpx
這個單位,翻譯就是響應式畫素,功能類似 rem
特點
小程式中不需要引入淘寶flexible
這個庫,因為內建的 rpx
單位就是實現了 rem + fleixible
功能。
小程式中,存在 螢幕的寬度 統一為 750 rpx
因此:存在以下關係。
螢幕寬度 | 換算關係 px 和 rpx |
---|---|
750 px | 1 px = 1 rpx |
375 px | 1px = 2 rpx |
any px | 1 px = any / 750 rpx |
程式碼
如 設計稿為 375px,其中存在一個view
寬度高度均為 100px ,字型大小 為 100px
view {
width: 200rpx;
height: 200rpx;
font-size: 200rpx;
background-color: aqua;
}
<view> 小程式rpx </view>
複製程式碼
vw 和 vh
在移動端中,還存在以下單位,也很好用,可以很方便解決問題。
單位 | 名稱 |
---|---|
vw | 100vw 等於 視口的寬度 |
vh | 100vh 等於 視口的高度 |
vMax | vw 和 vh 中的較大的那個 |
vMin | vw 和 vh 中的較小的那個 |
以上單位 在移動端中,或者在小程式中都支援。
設計稿為 375px
,存在一個大小為100px
的div
,字型大小也為100px
。
375px = 100 vw
那麼1 px = 100vw / 375
- 因此
100px = 100vw * 100 / 375
;
程式碼
注意 calc的語法比較嚴格 尤其注意空格
main {
background-color: pink;
width: calc(100vw * 100 / 375);
height: calc(100vw * 100 / 375);
font-size: calc(100vw * 100 / 375);
}
複製程式碼
響應式佈局
響應式的概念分為兩大類
- 一種是後端響應式
- 一種是前端響應式
後端響應式
後臺伺服器根據前端瀏覽器的User-Agent
來判斷來源請求是PC端還是移動端,然後伺服器動態返回PC端頁面或者移動端頁面。nginx中很容易就出現該功能。京東,天貓,淘寶也是這樣子的。
前端響應式
主要是指通過媒體查詢來實現。
前端寫好一套程式碼 html + css + javascript
,就可以冬天的根據螢幕的寬度來改變頁面的樣式
這種做法體驗不是最好,但是卻是最小的程式碼實現了 相容pc端和移動端。一般是對頁面要求不高或者小企業使用。
由於還要相容到pc端,所以一般做響應式頁面 不會用太高階的h5 css3 的技術。
案例
如 實現一個 大螢幕下 一行顯示3列,小螢幕下 一行顯示2列。
<!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;
box-sizing: border-box;
}
ul {
overflow: hidden;
}
li {
float: left;
height: 100px;
border: 1px solid #000;
background-color: pink;
}
/* 大螢幕 */
@media screen and (min-width:800px) {
li {
width: 33.33%;
}
}
/* 小螢幕 */
@media screen and (max-width:800px) {
li {
width: 50%;
background-color: lawngreen;
}
}
</style>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
</ul>
</body>
</html>
複製程式碼
效果
其他
業內要實現響應式佈局時,一般會使用 推特公司的 bootstrap 框架,好評度很高,而且還針對ie8 做了相容處理。