Adamwu1992 / adamwu1992.github.io

My Blog
2 stars 0 forks source link

未知宽高元素的垂直水平居中 #1

Open Adamwu1992 opened 6 years ago

Adamwu1992 commented 6 years ago

table

最关键的部分是设置table的text-align为center实现单元格内容水平居中,因为垂直居中是td的天然属性。

<table class="wrapper">
        <tr>
            <td>
                <div class="inner">hello world</div>
            </td>
        </tr>
    </table>

.wrapper{
width: 200px;
height: 200px;
background: #92b922;
margin: 10px;
text-align: center;    
}
.inner {
padding: 20px;
background: #de3168;
display: inline-block;
}

table-cell

上一种方法缺点在于需要包裹许多不必要的元素,利用table-cell属性也可以模拟td的垂直居中,而且不需要额外添加元素。

<div class="wapper wapper1">
        <div class="inner inner1"></div>
    </div>
.wapper {
            width: 200px;
            height: 200px;
            background: #92b922;
            margin: 10px;
        }
        .inner {
            padding: 20px;
            background: #de3168;
        }

        .wapper1 {
            display: table-cell;
            vertical-align: middle;
            text-align: center;
        }
        .inner1 {
            display: inline-block; 
        }

这种方法的缺点是,table-cell这个属性只有IE8及以上的浏览器才支持,遇到IE8以下的没有办法只能用回第一种table方法。

flex布局

这是我最喜欢用的方式,非常简洁,当然也需要考虑的felx布局的兼容问题。

<div class="wapper wapper3">
        <div class="inner inner3"></div>
    </div>

.wapper {
            width: 200px;
            height: 200px;
            background: #92b922;
            margin: 10px;
        }
        .inner {
            padding: 20px;
            background: #de3168;
        }
        .wapper3 {
            display: flex;
            justify-content: center;
            align-items: center;
        }

absolute布局

这种方法需要用到transform属性,IE10以下的全都不支持,所以同样有兼容性的问题。

<div class="wapper wrapper2">
        <div class="inner inner2"></div>
    </div>

.wapper {
            width: 200px;
            height: 200px;
            background: #92b922;
            margin: 10px;
        }
        .inner {
            padding: 20px;
            background: #de3168;
        }
        .wrapper2 {
            position: relative;
        }
        .inner2 {
            position: absolute;
            left:50%; 
            top:50%; 
            -webkit-transform:translate(-50%,-50%); 
            transform:translate(-50%,-50%);
        }

vertical-align

水平居中总是用text-align为center来实现,这个在绝大部分浏览器都是直接支持的。垂直居中需要用到vertical-align为middle来实现,对于vertical-align需要了解以下几点:

.wapper { width: 200px; height: 200px; background: #92b922; margin: 10px; } .inner { padding: 20px; background: #de3168; } .wapper4 { text-align: center; font-size: 0; } .wapper4::after, .wapper4 span { display:inline-block; width:0; height:100%; vertical-align:middle; content:''; } .inner4 { display:inline-block; vertical-align:middle; }


由于::after在IE8之前的浏览器不被支持,所以需要在低版本浏览器中手动添加一个span对象撑高line box,将after伪类或者span的宽度设置为0,同时,最重要的一点是**父元素的font-size也要设置为0**。
这是因为line level的元素之间存在white-space,当我们子容器的宽度撑满父容器时,由于white-space的存在,after伪类或者span就会被顶到下一行,这样就不属于同一个line box了。而white-space的宽度时根据字体大小来的,所以设置字体为0就可以解决这个问题了。
Adamwu1992 commented 6 years ago

offset

offsetWidth & offsetHeight

元素的宽高(width/height)+ 内边距(padding)+ 边框(border)+ 滚动条宽度。

offsetTop & offsetLeft

如果是相对于body的定位,offsetTop指的是:目标元素的border的外框到html元素padding的外框; 如果存在特定的offsetParentoffsetTop指的是:目标元素border的外框到parent元素padding的外框。

client

clientWidth & clientHeight

元素的宽高(width/height)+ 内边距(padding)。

clientTop & clientLeft

目标元素padding的外框到margin的外框,可以理解为border的宽度,如果有滚动条也包含其宽度。

scroll

scrollWidth & scrollHeight

元素的宽高(width/height)+ 内边距(padding)+ 内容溢出宽高。如果内容没有溢出,scrollWidth和clientWidth相等。

scrollTop & scrollLeft

元素滚动条的位置,可读写。

Adamwu1992 commented 6 years ago

硬件加速

现代浏览器大多可以用GPU来加速页面渲染,在GPU的众多特性中,它可以储存一定数量的纹理(一个矩形的像素点集合)并且高效地操作这些纹理(比如进行特定的移动、缩放和旋转操作)。这些特性在实现一个流畅的动画时特别有用。浏览器不会在动画的每一帧都绘制一次,而是生成DOM元素的快照,并作为GPU纹理(也被叫做层)存储起来。之后浏览器只需要告诉GPU去转换指定的纹理来实现DOM元素的动画效果。这就叫做GPU合成,也经常被称作『硬件加速』。

由于使用GPU加速的动画效果不会频繁的触发repaint,所以会大大减少CPU的压力,不会在动画过程中掉帧,移动端native应用很好里的利用里GPU的渲染能力,所以流畅程度往往超出web应用很多。 但是,如果要利用GPU渲染,就会在内存中储存需要渲染的图层(纹理),如果一个页面上有太多元素使用里GPU加速会过多的占用内存。 所以需要找到一个平衡点,在必要的动画中触发GPU加速,并且避免意料之外的图层的形成。

触发条件

transform和transform3d的区别就是,当元素具有3d变化属性时,会自动创建一个图层,之后这个元素的所有动画效果都在这个图层内渲染,不会触发repaint;而transform作为一个连续的动画属性时,会在开始和结束的时候触发repaint,此时应该时创建图层的过程,中间的动画都是在图层中渲染。

.ball-running {
            animation: run-around-smooth 4s infinite; 
        }
@keyframes run-around-smooth {
            0% {
                transform: translate(0, 0);
            }

            25% {
                transform: translate(400px, 0);
            }

            50% {
                transform: translate(400px, 400px);
            }

            100% {
                transform: translate(0, 400px);
            }
        }

上面的动画在Chrome中运行时,如果打开开发者工具中的Rendering - Paint Flashing,会发现只有在开始动画的瞬间会在元素上出现绿色框框(表示该区域内重绘了)