使用top/left/margin和CSS3 translate两种方法实现标题居中的性能差异详解
要实现标题全屏居中(同时在垂直和水平方向居中),有若干种方法,包括使用弹性布局、表格单元、绝对定位、自动外边距和CSS3平移变换等。
你可能已经使用了这些方法,但很可能没有意识到性能上的差别,因为这涉及到浏览器渲染引擎的一些幕后的工作原理。
使用top/left和margin来居中
其中目前比较流行也比较容易理解的方法是使用绝对定位+外边距实现。也就是分两步来把元素居中:
1. 第一步通过top/left先把元素放在离视口左上角(坐标原点)50%视口宽和50%视口高的地方;
2. 第二步通过margin把元素反向偏移其自身宽高的50%。
html,body{background: #333;height:100%; width:100%;margin:0;padding:0;} h1 { margin-left: -200px; margin-top: -35px;/* h1元素边框的高度一半: (30px+20px*2)/2 */ color: white; width: 400px; height: 30px; text-align: center; position: absolute; left: 50%; top: 50%; padding: 20px 0; border: 1px solid #666; }
上述代码使用绝对定位,top: 50%, left: 50%完成第一步,margin-left和margin-top完成第二步。
注意标题元素宽度使用百分比,可在水平方向自适应屏幕宽度。最好设置下min-width,以免屏幕过小时,标题文本溢出。
这样的代码是可以工作的。但是吹毛求疵的话,代码的性能并不好。当然在这种简单用例下不太会被暴露出来。
但是如果你想给这个标题添加一些动画效果,比如上下晃动的话,那么就很有必要优化一下代码。
性能优化的版本
上面的第一步没有问题,第二步完成相对自身尺寸的偏移,可以使用CSS3变换中的translate(使用百分比取值时,以其边框border box尺寸为参照)来替代。
我们先给出代码,然后说明为什么要这样,有什么好处和坏处。
*{margin:0;padding:0;} html,body{background: #333;height:100%; width:100%;} h1 { -ms-transform: translate3d(-50%, -50%, 0); -webkit-transform: translate3d(-50%, -50%, 0); transform: translate3d(-50%, -50%, 0); color: white; width: 50%; text-align: center; position: absolute; left: 50%; top: 50%; }
要明白为什么这么优化,我们首先需要了解浏览器的渲染过程:
解析DOM Tree,创建一个或多个渲染层(layer)
将每个层独立地绘制进位图(bitmap)中(计算样式->布局->栅格化)
将层作为纹理(texture)上传至 GPU
复合(composite)多个层来生成最终的屏幕图像
每个层的样式出现调整后,要重新计算样式->重新布局(可能没有)->重新栅格化(可能没有)->重新组合
使用top/left只会创建一个层,而使用translate方法将促使浏览器(webkit)把h1元素提取出来放在GPU单独的渲染层中(RenderLayer),这样有3点好处:
1. 该元素任何合成属性(Composite Property)的变化将不会影响原有文档,不会导致原文档被重新布局(relayout或reflow),所谓重新布局就是重新计算位置和尺寸,这是前端性能的杀手。位置和角度就是典型的合成属性。
2. 该层将由GPU(Compositor Thread)负责渲染,从而节省CPU资源,不会阻塞主线程JS代码的执行。
3. 动画更为平滑,这是因为使用translate将可以以小于像素的单位(sub-pixel)来绘制,并在帧之间加入了blur(模糊)效果。
可能带来的负作用是额外的渲染层导致更多的线程间通信,如果过度使用,导致生成成百上千的渲染层,那反而会导致组合各层图像的成本迅速上升成为主要矛盾,且我们需要记住GPU也是有内存限制的。当然还有一个前提是translate方法得到了浏览器支持,这在移动端没有问题。
另外使用translate的3D版本和translate 2d版本的区别在于可以强迫在声明后就创建独立的渲染层,这样一旦动画开始,无需等待。
在线实例
这里有一个在线用例是居中标题区块的完整实现:
http://wow.techbrood.com/fiddle/6908
还有两个在线用例用来比较top/left和translate方法的性能(你需要学会使用Chrome DevTools):
http://wow.techbrood.com/fiddle/17737
http://wow.techbrood.com/fiddle/17739
最新评论
- 相关文章
Monaco Editor 编辑器拷贝粘贴功能调用和获取选中文本
有时候需要在monaco editor外部调用编辑器的内置功能比如希望在页面主工具栏实现一些快捷操作。button
HTML5 And Canvas 2D Specs Are Now Feature Complete, First HTML 5.1 Working Draft Published
We’ve been writing about HTML5 for quite a while, but, until today, the actual HTML5 specs and standards were still moving targets. Now, however, the...
React JSX语法简介
JSX是一种类似XML的标签语法,用来简化代码,我们可以不使用JSX,但了解并使用也没什么坏处:)在React中,JSX是一个使用 React.createElement() API的快捷方式...
函数式JavaScript编程基础概念:Curry和Partial Application
本文介绍JS函数式编程中的两个概念:柯里(Curry)和部分应用程序(Partial Application)。什么是应用程序(Application)将函数应用于其参数以产生返回值的过...
CSS3弹性布局弹性流(flex-flow)属性详解和实例
弹性布局是CSS3引入的强大的布局方式,用来替代以前Web开发人员使用的一些复杂而易错hacks方法(如使用float进行类似流式布局)。其中flex-flow是flex-direction...
深入理解JS和CSS3动画性能问题和技术选择
本文对比了JS及其框架和CSS3的动画性能,并深入剖析了其内在原因。技术结论大致如下:1. jQuery出于设计原因,在动画性能上表现最差2. CSS3由于把动画逻辑推给了...
通过实例深入理解HTML5/CSS3/SVG/WebGL的技术本质
HTTP/2背景和新特性简介
使用SVG和CSS3创建圆形进度条动画
圆形进度条是一个经典的控制面板元素,常用于显示任务进度,比如用户档案的完整程度,或者升级状态。有很多方法来实现圆形进度条,比如用JS, CSS3, Canvas, SVG...
计算WebGL中的uniforms变量使用数
在使用Three.js为人体模型加载皮肤材料时,启用了skinning:true的参数。有时候会导致GL编译错误,提示“too many uniforms”。下面的文章有助于理解错误原因和检...
深度贴图(depth map)概念简介和生成流程
Depth map 深度图是一张2D图片,每个像素都记录了从视点(viewpoint)到遮挡物表面(遮挡物就是阴影生成物体)的距离,这些像素对应的顶点对于观察者而言是“可...
Three.js入门教程1 - 基础知识和创建一个红色球体
[ TECHBROOD注:Three.js是一个主流的开源WebGL库,WebGL允许使用JavaScript直接操作GPU,在网页上实现3D效果。
Google的工程师Paul在网站aerotwist.com上...WebGL入门教程1 - 3D绘图基础知识
现代浏览器努力使得Web用户体验更为丰富,而WebGL正处于这样的技术生态系统的中心位置。其应用范围覆盖在线游戏、大数据可视化、计算机辅助设计、虚拟现实以及数...
Processing.js和P5.js的功能简介和区别
什么是ProcessingProcessing是关于数字艺术的编程语言,支持跨平台,语言本身是一个类Java语言,程序文件的后缀为.pde。
什么是Processing.js为了能让Proce... 更多...