問題:當前市場上手機屏幕寬度不盡相同,常見有320px(ipone5)、375px(ipone678)等等,而為了在不同寬度的手機屏幕上良好現顯示網頁,我們需要解決方案。
原理:當前前端解決手機屏幕自適應的手段極多,究其原理,主要分為兩大版塊:
一、使用百分比長度單位,當前百分比長度單位一般如下:vw、vh、vm、em、rem、%,優點:一套css代碼即可適應所有屏幕寬度不同的手機;
二、使用固定長度單位px,再使用js根據當前屏幕寬度與固定寬度計算比例,進行網頁縮放。優點:網頁寬度恆定,便於計算
實現:
一、使用百分比寬度單位實現移動端屏幕自適應
我們來聊聊這些百分比長度單位的定義及優缺點。
vw:相對於視口的寬度,視口被均分為100單位的vw;即將當前屏幕寬度均分為100份,1vw即為當前屏幕寬度的1%;優點:vw單位長度准確分明,常用此單位,推薦使用此單位。
vh:相對於視口的高度,視口被均分為100單位的vh;即將當前屏幕高度均分為100份,1vh即為當前屏幕高度的1%;基本不用此單位,它的優點vw都有,但是它有一個致命的缺點:手機屏幕高度分成100份后,不是便於計算的數字,譬如iphone5屏幕高568px,此時1vh=5.68px;iphone678屏幕高667px,此時1vh=6.67px;若設計稿一個div寬高皆為100px,你能口算出它的寬高為多少vh嗎?我們不可能帶着計算器寫代碼。
vm:相對於視口的寬度或高度,取決於哪個更小,視口寬度或高度中更小的那個被均分為100單位的vm;即將當前屏幕寬度或高度均分為100份,1vm即為當前屏幕寬度或高度的1%;它的優點vw都有,也曾見有人使用此單位,但我覺得vw比它更好。
em:相對長度單位。相對於當前對象內文本的字體尺寸。如當前對行內文本的字體尺寸未被人為設置,則相對於上一個父元素的默認字體尺寸。舉例而言,瀏覽器默認字體大小為16px,在css中設置
html{font-size:15px;}
body{font-size:14px;}
em將優先使用自身的字體大小,若自身沒有設置字體大小,將繼承上一個父元素的字體大小,此時沒有為當前標簽設置字體樣式,於是繼承body的字體大小,而不是繼承html的字體大小,即1em=14px;此單位若要用於屏幕自適應,需與vw配合使用設置父元素的字體大小。於css中進行字體設置譬如:font-size1:4vw;,方可實現屏幕自適應。基本不用此單位,它的優點rem都有,但它是優先使用自身的字體大小,其次繼承上一個父元素的字體大小,而我們在使用標簽時,經常需要給標簽設置字體樣式,將導致em的根元素字體尺寸不定,使用起來十分麻煩。
舉例如下所示:
在w3c等教學網站中,他們使用px單位作為em單位的根單位,但是使用px做根單位的em單位是無法實現移動端屏幕自適應的。在移動端中,不推薦將px作為em的根單位。
rem:相對長度單位,相對於根元素(即html元素)內文本的字體尺寸。rem繼承且只繼承html標簽的字體大小。同樣的,此單位若要用於屏幕自適應,需與vw配合使用設置根元素的字體大小。必須在css中進行字體設置:
html{font-size:4vw;}
,方可實現屏幕自適應。常用此單位,推薦使用此單位。看到這里,相信很多朋友都會感到疑惑,明明直接使用vw單位即可實現自適應,為何要使用vw單位進行設置后來使用rem單位呢?原因很簡單:便於計算。首先,設計師設計的移動端設計稿通常使用750px寬度(契合iphone678的屏幕寬度),前端工程師通常使用375px的網頁寬度(在所有手機屏幕寬度中,它是最方便計算的寬度)。此時,1vw=3.75px;而4vw=15px;8vw=30px;那么請問,哪個單位更便於計算?由於30px與375px相除並非整數,我推薦使用15px(即1rem=4vw)。
當然,這只是我的小技巧,rem單位與vw單位的優先度相差無幾,事實上,使用vw單位的人極多,也許比使用rem單位的人更多,全看各人喜好。
也有人使用px作為rem的根單位,再使用js進行單位縮放,不推薦這樣使用,又不是沒有rem單位和vw單位用,縮放單位個雞兒。
%:基本沒人用。原因:單純使用%無法確定div的高度,若使用%,那么必須搭配px等固定長度單位來確定高度,形如
.a{
width: 20%;
height: 20px;
}
這樣的方式,很容易導致圖片等變形。
二、使用固定長度單位px,再使用js根據當前屏幕寬度與固定寬度計算比例,進行網頁縮放,來實現移動端屏幕自適應
這個方法主要需要用到css3的兩個屬性:transform、 transform-origin。通過transform屬性的值scale可以進行網頁縮放,這是根本。另外必須允許網頁縮放,否則transform屬性會不起作用。
這個手段簡單來說,需要先定一個網頁寬度(譬如750px),再通過js獲取屏幕寬度,屏幕寬度/網頁寬度=縮放比例,然后通過js執行縮放(為標簽添加transform及transform-origin屬性)。話不多說,直接上代碼。
<html>
<head>
<meta content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<style> *{margin: 0;padding: 0;} #div1{width: 750px;height: 600px;background-color: red;} #div2{width: 375px;height: 300px;background-color: green;}
</style>
</head>
<body id="body">
<div id="div1">
<div id="div2"></div>
</div>
</body>
<script type="text/javascript">
//id 需要進行縮放的標簽id
function suofang(id) { var num = 750;//css中固定的網頁寬度
var oWidth = window.screen.width;//獲取當前手機屏幕寬度
var objId = document.getElementById(id);//獲取傳入的id標簽對象
rate = oWidth / num;//縮放比例 = 當前手機屏幕寬度/css中固定的網頁寬度
if (oWidth < 1920) { objId.style.transformOrigin = "left top 0px"; objId.style.transform = "scale(" + rate + ")"; /* IE 9 */ objId.style.msTransformOrigin = "left top 0px"; objId.style.msTransform = "scale(" + rate + ")"; /* Safari and Chrome */ objId.style.webkitTransformOrigin = "left top 0px"; objId.style.webkitTransform = "scale(" + rate + ")"; /* Firefox */ objId.style.mozTransformOrigin = "left top 0px"; objId.style.mozTransform = "scale(" + rate + ")"; /* Opera */ objId.style.oTransformOrigin = "left top 0px"; objId.style.oTransform = "scale(" + rate + ")"; } }; suofang("body");//執行縮放
</script>
</html>
話不再說,直接上效果:
事實上,有更簡便的方法來縮放網頁,即通過js操縱meta標簽中的initial-scale(即網頁初始縮放比例)屬性即可。話不多說,直接上代碼。
<html>
<head>
<meta content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<style> *{margin: 0;padding: 0;} #div1{width: 750px;height: 600px;background-color: red;} #div2{width: 375px;height: 300px;background-color: green;}
</style>
</head>
<body id="body">
<div id="div1">
<div id="div2"></div>
</div>
</body>
<script type="text/javascript">
//網頁縮放函數
function suofang() { var num = 750;//css中固定的網頁寬度
var oWidth = window.screen.width;//獲取當前手機屏幕寬度
rate = oWidth / num;//縮放比例 = 當前手機屏幕寬度/css中固定的網頁寬度
if (oWidth < 1920) { document.getElementsByTagName('meta')[name="viewport"].content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,width=device-width,height=device-height,initial-scale="+ rate+",maximum-scale=2.0,user-scalable=no";//修改meta的屬性
} }; suofang(); </script>
</html>
話不再說,直接上效果:
ps:此外,還可以使用媒體適配查詢的方法來進行自適應,不過媒體適配查詢這個方法一般用於pc端與移動端適應。我想應該沒人會這么蠢,單純為了解決移動端自適應而使用它,畢竟為不同寬度手機屏幕的同一個頁面的寫很多套css實在太蠢了。舉例如下:
@media screen and (min-width:1281px) and (max-width:1920px) and (orientation:portrait) {
html { font-size: 15px; }
}
@media screen and (min-width:320px) and (max-width:1280px) and (orientation:portrait) {
html { font-size: 73.24%; }
}