關於css中的單位
大家都知道在css中的單位,一般都包括有px,%,em等單位,另外css3新增加一個單位rem。
其中px,%等單位平時在傳統布局當中使用的比較頻繁,大家也比較熟悉,不過px單位在進行自適應布局的過程當中則會有些力不從心,大部分的解決方案是使用%為單位配合@media媒介查詢來進行自適應布局。不過還有另外一個css3新添加的單位也同樣可以拿來進行自適應布局,在我看來這種方法也更加方便直觀。
em和rem
首先先介紹一下em,這個單位是根據其父元素的字體大小來進行計算的,即1em為其父元素的字體大小,例如父元素的字體大小為12px則其子元素的1em為12px,2em則為24px。但是因為其只能針對父元素來進行計算,使用起來因為涉及到大量的運算,很不方便,因此平時使用不是很多。
css3針對這種情況在css3的規范下推出了一個新的單位rem,rem的使用方式和em類似,只不過em是基於其父元素的字體大小來進行計算,而rem則是針對根元素即HTML這個標簽的字體大小來進行計算,在這種情況下假如html的字體大小為12px則在頁面中左右元素的1個rem即為12px,2rem為24px。
用rem進行自適應布局--------簡單的自動適配所有屏幕
使用rem進行自適應布局的關鍵就是給html賦值一個動態的font-size,在這里我們可以在頁面dom加載完畢之后使用js獲取到頁面寬度(高度也可以),然后將其除以一個固定的定量,比如20,然后將結果賦給html的font-size,這樣我們就得到了一個會根據頁面寬度的變化而不斷變化的值,這個值即是1rem。代碼如下:
//頁面大小出現變化的時候再次獲取新的font-size值 $(window).resize(function(){
setHtmlFontSize(20);
}) //初始化執行 setHtmlFontSize(20);
//動態設置html元素的font-size的方法 function setHtmlFontSize(num){ //頁面的寬度,其中17為頁面默認的導航條的寬度 var _w=document.documentElement.clientWidth-17;
$('html').css('fontSize',_w/num); }
例
舉個例子,我們先用js獲取頁面的寬度,除以20進行計算之后,把這個值賦給html的font-size,得到一個根據頁面寬度變化而變化的單位1rem,這個時候假如我們拿到的設計稿的寬度是640px,將其除以20,這樣我們就得到在頁面寬度為640px的情況下1rem即為32px,如果設計稿中的banner圖部分的寬度是320px,而高度則是160px,這個部分需要進行自適應,那么我們就可以給這個banner圖寬度為320/32=10rem,而高度為160/32=5rem。這樣賦值之后假如頁面的寬度就是640px,那banner的尺寸為320px160px,寬度是屏幕尺寸的一半,高度為1/4,這個時候假如屏幕變寬為1280px,那這個時候頁面中1rem所代表的尺寸就變成了1280/20=64px,banner的尺寸變成了相應的640px320px,寬度依然是屏幕尺寸的一半,高度為1/4.這樣就非常簡單的實現了自適應的布局賦值。
通過這種動態的設定html的font-size的值之后,我們可以很輕易的給頁面上任何地方,例如padding,width,height,margin設置大小,並且這個大小都是自適應的。
關於calc()
在進行自適應布局的時候有時候會碰到需要有給固定寬高的地方,比如一個div寬度為屏幕尺寸的一半,但是有10px的padding,那在這種情況下假如我們直接給寬度50%,或者計算完之后的rem單位,再給padding,.因為盒模型的關系導致其寬度為50%+20px。但是又因為50%是一個不固定的值,導致很難計算出一個具體的值,在這種情況下我們就可以使用css3中的一個計算方法,calc(),可以設置
div{width:calc(50% - 20px);}
這樣設置之后得到的結果就是計算之后的結果,任何需要給具體的值的地方都可以使用calc來進行計算,不過需要主要目前此方法只能進行+ - * /的四則運算,並且在計算符號前后都需要有一個空格。當然上面的50%也可以換成計算之后的rem單位。
通過這些在方法在進行自適應布局的時候就可以更加的得心應手了~~
結論
使用rem單位以及calc()方法在進行自適應布局非常強大,可以配合媒介查詢,可以非常靈活的控制各種元素的自適應。
<!DOCTYPE HTML>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no" />
<script>
;(function(psdWidth,dividendFontSize,maxRootFontSize){
// 為了代碼更短
var d = document
var de = d.documentElement
var w = window
var on = 'addEventListener'
var gbcr = 'getBoundingClientRect'
var ps = 'pageshow'
var head = d.head || d.getElementsByTagName('HEAD')[0]
var style = d.createElement('STYLE') // 采用拼css的形式,而不是直接用document.documentElement.style.fontSize的形式的原因是,拼css可以通過加入!important獲得最高優先級,http://jsbin.com/dopupudago/2/edit?html,js,output
var resizeEventThrottleTimer
// 移除任何text-size-adjust對字體大小的改變效果
var textSizeAdjustCSS = 'text-size-adjust:100%;'
var textSizeAdjustCSSAll =
'-webkit-'+textSizeAdjustCSS
+'-moz-'+textSizeAdjustCSS
+'-ms-'+textSizeAdjustCSS
+'-o-'+textSizeAdjustCSS
+textSizeAdjustCSS
var hasGbcr = gbcr in de
var lastRootFontSize = null // 上一次設置的html的font-size
function setRem(){
var rootFontSize = Math.min(
(
hasGbcr?
de[gbcr]().width // document.documentElement.getBoundingClientRect() iOS4.0+ 安卓2.0+ https://developer.mozilla.org/zh-CN/docs/Web/API/Element.getBoundingClientRect
:w.innerWidth
)
/(psdWidth/dividendFontSize)
,maxRootFontSize
)
// alert('2 iW_'+w.innerWidth+' sw_'+w.screen.width+' dpr_'+devicePixelRatio+' or_'+w.orientation+' gbcrw_'+d.documentElement.getBoundingClientRect().width)
if(rootFontSize != lastRootFontSize){
// return
style.innerHTML =
'html{'
+ 'font-size:'+rootFontSize+'px!important;' // 20=320/16 // 取16為默認html的font-size是因為瀏覽器都默認為16,不會導致抖動
+ textSizeAdjustCSSAll
+'}'
lastRootFontSize = rootFontSize
}
}
// 在一定延時內稀釋setRem的調用
function trySetRem(){
clearTimeout(resizeEventThrottleTimer)
resizeEventThrottleTimer = setTimeout(setRem,500)
}
psdWidth = psdWidth || 320
dividendFontSize = dividendFontSize || 16
maxRootFontSize = maxRootFontSize || 32
head.appendChild(style)
d[on]('DOMContentLoaded',setRem,false)
// 安卓在頁面剛載入時w.screen.width不一定正確,特別是從一個未設置viewport meta的頁面跳轉過來時,需要多調整幾次。見圖:“show/2.3.6_從一個未設置viewport的頁面跳轉過來時,起初innerWidth和screen.width都是不對的.png”,於是在pageshow或onload事件觸發時再設置一次
if('on'+ps in w){
w[on](ps,function(e){
if(e.persisted){
trySetRem()
}
},false)
}else{
w[on]('load',trySetRem,false)
}
w[on]('resize',trySetRem,false)
setRem()
})(
320, // 設置設計稿基准寬度
16, // 設置開發時的被除數(見HOW TO USE第4步) 在設計稿基准寬度為320時最好設置為16(在在設計稿基准寬度為其他值時等比放大,如640時設置為32等)。因為瀏覽器默認的值就是16,這樣代碼失效或尚未起效時,不會有布局問題
32 // 設置最大根元素font-size,請注意這是一個css像素值,而非物理像素值。它的作用是,當用戶用非常寬的屏幕(pad、pc)訪問頁面時,不至於使得根元素的font-size超過這個值,使得布局非常難看。見圖“show/wide_max_rem.jpg”
)
</script>
<title>rem</title>
<style>
html,body{margin: 0;padding: 0;}
</style>
</head>
<body>
<div id="debug">
</div>
<div id="wrapper">
<!-- content text -->
<p style="
font-size:1rem
/*通過 font-size:16px; 除以16計算出來*/
">一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十</p>
<!-- icon -->
<img src="up.png" alt="向上" style="position:fixed;
bottom:0.625rem;right:0.625rem;width:3rem;height:3rem;
/*通過 bottom:10px;right:10px;width:48px;height:48px; 各除以16計算出來*/
">
<!-- photo -->
<img src="p1.jpg" alt="向上" style="margin:0 auto;display:block;
width:18.75rem;height:12.5rem;
/*通過 width:300px;height:200px; 各除以16計算出來*/
">
</div>
<script>
</script>
</body>
</html>
