关于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>