CSS3中的px、em、rem

最近在实习单位写一个自适应网站,要求适应主流手机端。页面很简单,我负责的有4个页面,一天就搞定了,用的@media query方法。但是发现公司有个人用的rem单位来适配不一样的分辨率,导致我们的页面用了不同的方法,从而无法合并在一起(网页由header、content、footer组成,我做的content。最后解决办法是我自己又把foot和head重写了...)。

一、介绍一下css3中的长度单位。

css3中的长度单位有13个:px,em,pt,ex,pc,in,mm,cm,ch,rem,vw,vh,vm;

px:像素(Pixel),相对于设备的长度单位,像素是相对于显示器屏幕分辨率而言的。譬如,WONDOWS的用户所使用的分辨率一般是96像素/英寸。而MAC的用户所使用的分辨率一般是72像素/英寸。 pt:点(Point),标准的绝对长度单位,一般用于印刷业。一英寸=72pt(点)=96px(像素)。 em:相对长度单位,是一个比率。相对于当前对象内文本的字体尺寸。如当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体(html)尺寸。结合CSS继承关系使用,具有灵活性。 rem:CSS3 长度单位 rem ,相对于根元素(即html元素)font-size计算值的倍数 ex:相对长度单位。相对于字符“x”的高度。此高度通常为字体尺寸的一半。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。 pc:派卡(Pica),绝对长度单位。相当于我国新四号铅字的尺寸。 in:英寸(Inch),绝对长度单位。 mm:毫米(Millimeter),绝对长度单位。 cm:厘米(Centimeter),绝对长度单位。 [其中:1in = 2.54cm = 25.4 mm = 72pt = 6pc] ch:CSS3 长度单位 ch ,通常是数字“0”的宽度。 vw:CSS3 长度单位 vw,相对于视口的宽度。视口被均分为100单位的vw。 vh:CSS3 长度单位 vh ,相对于视口的高度。视口被均分为100单位的vh。 vm:CSS3 长度单位 vm ,对于视口的宽度或高度,总是相对于小的那个。视口的宽度或高度被均分为100单位的vm。

下面着重介绍px、em、rem。

二、PX为单位

在Web页面初期制作中,我们都是使用“px”来设置我们的文本,因为他比较稳定和精确。但是这种方法存在一个问题,当用户在在不同设备浏览器中浏览我们制作的Web页面,或者在浏览器放大、缩小时,这时会使用我们的Web页面布局被打破。这样对于网站友好度而言,是一个大问题。因此,这时就提出了使用“em”来定义Web页面的字体。

三、em为单位

em是一个相对值,这种技术需要一个参考点,一般都是以的“font-size”为基准。比如说我们使用“1em”等于“10px”来改变默认值“1em=16px”,这样一来,我们设置字体大小相当于“14px”时,只需要将其值设置为“1.4em”。

body {font-size: 62.5%;/*10 ÷ 16 × 100% = 62.5%*/}
h1 {font-size: 2.4em; /*2.4em × 10 = 24px */}
p{font-size: 1.4em; /*1.4em × 10 = 14px */}
li{font-size: 1.4em; /*1.4 × ? = 14px ? */}

为什么“li”的“1.4em”是不是“14px”将是一个问号呢?在使用“em”作单位时,一定需要知道其父元素的设置,因为“em”就是一个相对值,而且是一个相对于父元素的值,其真正的计算公式是:

1 ÷ 父元素的font-size × 需要转换的像素值 = em值

这样的情况下“1.4em”可以是“14px”,也可以是“20px”,是一个不确定值。所以用em作为长度单位,需要根据父元素的字体大小以及需求文档来进行设计。

根据base pixel size来进行px和em转换可以用PX to EM工具。

四、rem为单位

在W3C官网上是这样描述rem的——“font size of the root element” 。CSS3的出现,引进了一些新的单位,包括我们今天所说的rem。

前面说了“em”是相对于其父元素来设置字体大小的,这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小,在我们多次使用时,就会带来无法预知的错误风险。而rem是相对于根元素,这样就意味着,我们只需要在根元素确定一个参考值,在根元素中设置多大的字体,这完全可以根据您自己的需要,大家也可以上面给的一个工具。

我在根元素中定义了一个基本字体大小为62.5%(也就是10px。设置这个值主要方便计算,如果没有设置,将是以“16px”为基准 )。从上面的计算结果,我们使用“rem”就像使用“px”一样的方便,而且同时解决了“px”和“em”两者不同之处。

五、rem用于web app

不得不说rem是web app的最合适的选择,没有之一(不服来揍我啊<( ̄ˇ ̄)/)。

讲到web app又不得不讲到自适应等问题,之前写过一篇布局有关的文章,大家可以参考一下。下面几个是曾经一些web app用过的方法,来比较一下:

1、流式布局

目前一些web app如亚马逊、携程等,都是采用的流式布局的技术实现的,他们在页面布局的时候都是通过百分比来定义宽度,但是高度大都是用px来固定住,所以在大屏幕的手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度还是和原来一样,实际显示非常的不协调,这就是流式布局的最致命的缺点,往往只有几个尺寸的手机下看到的效果是令人满意的,其实很多视觉设计师应该无法接受这种效果,因为他们的设计图在大屏幕手机下看到的效果相当于是被横向拉长来一样。

2、固定宽度做法

早期有些网站把页面设置成320的宽度,超出部分留白,这样做视觉,前端都挺开心,视觉在也不用被流式布局限制自己的设计灵感了,前端也不用在搞坑爹的流式布局。但是这种解决方案也是存在一些问题,例如在大屏幕手机下两边是留白的,还有一个就是大屏幕手机下看起来页面会特别小,操作的按钮也很小,手机淘宝首页起初是这么做的,但近期改版了,采用了rem。

3、响应式做法

响应式这种方式在国内很少有大型企业的复杂性的网站在移动端用这种方法去做,主要原因是工作大,维护性难,所以一般都是中小型的门户或者博客类站点会采用响应式的方法从web page到web app直接一步到位,因为这样反而可以节约成本,不用再专门为自己的网站做一个web app的版本。

4、设置viewport进行缩放

天猫的web app的首页就是采用这种方式去做的,以320宽度为基准,进行缩放,最大缩放为320*1.3 = 416,基本缩放到416都就可以兼容iphone6 plus的屏幕了,这个方法简单粗暴,又高效。它和用rem的方法都非常高效。

5、用rem

这时候谈到rem就不一样了,它能等比例适配所有屏幕(牛哄哄的感觉)!当你设置了html即根元素的字体之后,你可以对所有的网页中的元素用rem,这样单位不仅统一,当缩放或放大的时候,不会有任何不协调的问题。

举个例子:

html{font-size:20px;}
.btn {
        width: 6rem;
        height: 3rem;
        line-height: 3rem;
        font-size: 1.2rem;
        display: inline-block;
        background: #06c;
        color: #fff;
        border-radius: .5rem;
        text-decoration: none;
        text-align: center;
}

上面代码结果按钮如下图:

20160428092700

为什么6rem等于60px。如果这个时候我们的.btn的样式不变,我们再改变html的font-size的值,看看按钮发生上面变化:

html{font-size:40px;}

结果如下

20160428092832

上面的width,height变成了上面结果的两倍,我们只改变了html的font-size,但.btn样式的width,height的rem设置的属性不变的情况下就改变了按钮在web中的大小。

其实从上面两个案例中我们就可以计算出1px多少rem: 第一个例子: 120px = 6rem * 20px(根元素设置大值) 第二个例子: 240px = 6rem * 40px(根元素设置大值) 推算出: 10px = 1rem 在根元素(font-size = 10px的时候); 20px = 1rem 在根元素(font-size = 20px的时候); 40px = 1rem 在根元素(font-size = 40px的时候);

在上面两个例子中我们发现第一个按钮是等比例放大到第二个按钮,html中font-size的改变就会导致按钮的大小发生改变,我们并不需要改变先前给按钮设置的宽度和高度,其实这就是我们最想看到的。

我们知道改变html的font-size可以等比改变所有用了rem单位的元素,所以大家可以通过chrome浏览器的调试工具去切换上面的按钮,在不同设备下的展示效果,或者通过缩放浏览器的宽度来查看效果,我们可以看到不管在任何分辨率下,按钮大小都是按照等比例进行切换。在进行页面布局的时候,你也会发现,页面的所有元素都不需要进行任何改变,布局也不会随着设备的变化或者分辨率的变化而发生变化。

到这里肯定有很多人会问我,怎么计算出不同分辨率下font-size的值?

首先假设我的页面设计稿是按照640的标准尺寸的前提下,(当然这个尺寸肯定不一定是640,可以是320,或者480,又或是375)来看一组表格:

1434335347158935

上面的表格蓝色一列是以640的宽度去切的,怎么计算不同宽度下font-site的值,大家看表格上面的数值变化应该能明白。举个例子:384/640 = 0.6,384是640的0.6倍,所以384页面宽度下的font-size也等于它的0.6倍,这时384的font-size就等于12px(我设置的html的font-size为20px,20x0.6=12)。在不同设备的宽度计算方式以此类推。

一般我们在做web app都会先统计自己网站有哪些主流的屏幕设备,然后去针对那些设备去做media query设置也可以实现适配,例如下面这样:

html {
        font-size : 20px;
    }
    @media only screen and (min-width: 401px){
        html {
            font-size: 25px !important;
        }
    }
    @media only screen and (min-width: 428px){
        html {
            font-size: 26.75px !important;
        }
    }
    @media only screen and (min-width: 481px){
        html {
            font-size: 30px !important; 
        }
    }
    @media only screen and (min-width: 569px){
        html {
            font-size: 35px !important; 
        }
    }
    @media only screen and (min-width: 641px){
        html {
            font-size: 40px !important; 
        }
    }

上面的做的设置显然是不能所有设备全适配。目前国内使用了rem技术的网站,我介绍两个,手机淘宝(淘宝native app的首页是内嵌的web app首页)和DX。

通过JS去动态计算根元素的font-size,这样的好处是所有设备分辨率都能兼容适配(页面以什么大小来切,代码中的640就换成什么):

<script>        
	(function (doc, win) {    
	    var docEl = doc.documentElement,    
	    resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',    
	    recalc = function () {    
	    var clientWidth = docEl.clientWidth;    
	    if (!clientWidth) return;    
	    docEl.style.fontSize = 20 * (clientWidth / 640) + 'px';    
	};    
	if (!doc.addEventListener) return;    
	win.addEventListener(resizeEvt, recalc, false);    
	doc.addEventListener('DOMContentLoaded', recalc, false);    
	})(document, window);    
</script>

六、浏览器的兼容性

兼容性还算不错:Mozilla Firefox 3.6+、Safari 5+(ios Safari 4.1+)、Chrome 6+、IE9+(IE6-8就别想了)和Opera 11.6+。安卓手机端的98%以上都支持,极小部分不支持,所以可以忽略了。

总结

在Web中使用什么单位来定义页面的字体大小,取决于需求,需求决定设计。rem在移动端可以做到适配不同的手机分辨率,如果保持整体缩放,没有设计上的差异可以不需要用到“media query”。

不过使用单位设置字体,可不能完全不考虑IE了,如果你想使用这个REM,但也想兼容IE下的效果,可你可考虑“px”和“rem”一起使用,用"px"来实现IE6-8下的效果,然后使用“Rem”来实现代主流浏览器的效果。就让IE6-8不能随文字的改变而改变吧,谁让这个Ie6-8这么老呢?(而且还是老不死的)

标签: ,   |  
时间: 2016年04月28日上午10:00  |  
作者:
LEAVE A REPLY
loading
正在赶回来……