Home > Article > Web Front-end > Interpret horizontal and vertical centering of CSS layout_html/css_WEB-ITnose
Horizontally and vertically centering an element is something we often encounter in our work and is also an important part of CSS layout. This article will talk about CSS horizontal and vertical centering. Some methods. Since we at Souche no longer need to worry about lower versions of IE in our daily work, the method posted in this article does not take IE into consideration. If you have compatibility needs, you can refer to this article: http://www. cnblogs.com/Dudy/p/4085292.html
Let’s take a look at a picture first. This was released by Alibaba’s teacher @Han Dongwinter during the cssConf conference last year:
As shown in the figure, CSS layout can be divided into several large parts:
All CSS layouts actually revolve around these layout modules, as well as horizontal and vertical centering.
1. Horizontal and vertical centering of text
DEMO link
Code:
<div class='wrap'> 水平垂直居中水平垂直居中</div>
html,body{ margin: 0;}.wrap{ line-height: 400px; text-align:center; height: 400px; font-size: 36px; background-color: #ccc;}
This method is only suitable for horizontal and vertical centering of a single line of text
2. Use the horizontal and vertical centering of the box model
The box model we generally talk about is a block-level box Of the box models, only the block-level box model is used more. The block-level box is composed of content-box, padding-box, border-box, and margin-box respectively, as shown below:
In other words, the distance between the horizontal and vertical sides of any sub-box and the outermost box can be controlled, so there is the following centering method:
DEMO link
Code:
<div class="wrap"> <div class="content"></div></div>
@wrapWidth : 400px;.wrap{ margin-left: auto; margin-right: auto; margin-top: 20px; width: @wrapWidth; height: @wrapWidth; background-color: #ccc;}.content{ @contentWidth : 100px; width: @contentWidth; height: @contentWidth; padding: (@wrapWidth - @contentWidth) / 2; background-color: #333; background-clip:content-box;}
can also be calculated dynamically using calc() of css3:
DEMO Link
<div class="wrap"> <div class="content"></div></div>
.wrap{ margin-top: 20px; margin-left: auto; margin-right: auto; width: 400px; height: 400px; background-color: #ccc; .content{ padding: -webkit-calc(~"(100% - 100px) / 2"); padding: calc(~"(100% - 100px) / 2"); width: 100px; height: 100px; background-color: #333; background-clip: content-box; }}
Note that I used a ~"" writing method in calc. This is a syntax in less, which tells less that this is not compiled by less. If it is mutated by less, If so, the parameter of the CSS calc function is not 100% - 100px, but 0%.
DEMO link
Code:
<div class="wrap"> <div class="ele"></div></div>
.wrap{ @wrapHeight : 400px; @contenHeight : 100px; overflow: hidden; width: 100%; height: @wrapHeight; background-color: #ccc; .ele{ margin-left: auto; margin-right: auto; margin-top: (@wrapHeight - @contenHeight) / 2; width: 100px; height: @contenHeight; background-color: #333; color: #fff; }}
To use margin padding we need to know the width of the element, which is not quite right Flexible, but CSS3 has created an attribute value with fit-content, which can dynamically calculate the width of elements. DEMO link
Using the box model for layout will not cause reflow. Whether it is compatible or not, using the box model for layout is A layout idea, in fact, it can achieve many layouts that can only be achieved by visual formatting. This is another topic and will not be discussed here.
3. Horizontal and vertical centering in the context of absolute layout
The principle is very simple, that is, use left: 50% to place the left side of the box first The midpoint of the parent container, and then offset the box to the left by 50% of the box's own width. There are three specific implementations:
DEMO link
<div class="wrap"> <div class="ele margin">水平垂直居中水平垂直<br>居中水平垂直居中水平<br>垂直居中水平垂直居<br>中水平垂直居中</div></div><div class="wrap"> <div class="ele translate">水平垂直居中水平垂直<br>居中水平垂直居中水平<br>垂直居中水平垂直居<br>中水平垂直居中</div></div><div class="wrap"> <div class="ele relative"> <div class="ele-inner">水平垂直居中水平垂直<br>居中水平垂直居中水平<br>垂直居中水平垂直居<br>中水平垂直居中</div> </div></div>
.wrap{ position: relative; width: 100%; height: 200px; border:1px solid; background-color: #ccc; .ele{ position: absolute; left: 50%; top: 50%; background-color: #333; &.margin{ width: 160px; height: 100px; margin-left: -80px; margin-top: -50px; } &.translate{ -webkit-transform:translate3d(-50%, -50%, 0); transform:translate3d(-50%, -50%, 0); } .ele-inner{ position: relative; left: -50%; top: -50%; width: 100%; height: 100%; background-color: #333; } &.relative{ width: 150px; height: 100px; background-color: transparent; } }}
The above three Among the methods, both the margin method and the relative method need to know the width and height of the element (the relative method only knows the height), which is suitable for fixed layouts, while the transform method does not need to know the width and height of the element
text-aign:center cannot directly act on absolute elements, but row-level absolute elements that do not have left equivalent values will be affected by text. You can refer to Teacher Zhang This article
DEMO link
Code:
<div class="wrap"> <div class="ele"></div></div>
.wrap{ text-align: center; width: 100%; height: 400px; background-color: #ccc; font-size: 0;}.ele{ position: absolute; margin-left: -(100px / 2); margin-top: (400px - 100px) / 2; width: 100px; height: 100px; display: inline-block; background-color: #333;}
A brief explanation, first of all, text-align:center works on text rather than absolute element. However, when the absolute element is inline-block, it will be affected by the text. Then you may ask if there is no text here. I can only tell you that there is an anonymous text node below. The details will not be expanded here. You can refer to the standard and then understand this sentence:
If the inline box contains no glyphs at all, it is considered to contain a strut (an invisible glyph of zero width) with the A and D of the element's first available font
Then the anonymous text is centered due to the influence of text-align:center. At this time, the left side of the absolute box is aligned with the midpoint of the parent container. So you still need to pull back 50%. The margin-left is used here. You can also pull it back in other ways. Then there is the vertical alignment. The vertical direction cannot be affected by the properties of the manipulated text, so I use margin-top here to offset it.
DEMO link
Code:
<div class="wrap"> <div class="ele"></div></div>
html,body{ width: 100%; height: 100%; margin: 0;}.wrap{ position: relative; width: 100%; height: 100%; background-color: #ccc; .ele{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; margin: auto; width: 100px; height: 100px; background-color: #333; }}
The principle of this layout can be found in the standard The following explanation:
There is such a sentence in w3c.org:
The constraint that determines the used values for these elements is: 'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = width of containing block
这句话说的是absolute性质的盒子,它的包含块的宽度等于它的盒模型的宽度 + left + right值,包含块的高度同理,盒模型包括margin-box、border-box、padding-box、content-box,而在这个居中方法中,.ele的left + right值是0,width是定值,width所在盒子包括了除了margin-box外的那三个box,margin都是auto值,按照上面那个公式,margin-left + margin-right的值应该等于包含块的宽度 - left的值 - right的值 - width的值,也就是说margin-left + margin-right的值等于除了width所占宽度外的剩下宽度,拥有剩下宽度后,就是平分其宽度,以让左右两边相等,达到居中,标准中给出了答案:
If none of the three is 'auto': If both 'margin-left' and 'margin-right' are 'auto', solve the equation under the extra constraint that the two margins get equal values, unless this would make them negative, in which case when direction of the containing block is 'ltr' ('rtl'), set 'margin-left' ('margin-right') to zero and solve for 'margin-right' ('margin-left')
结合原文中的上下文,这句话主要说的是如果left、right和width都不为auto,同时margin-left和margin-right都是auto,除非特别情况,它们俩就是相等的,而这个例子中不在特殊情况之列,因此两者平分,此时达到了水平居中。而对于,垂直方向的margin的auto值的计算,我没有找到相关规范,还望知道的大神予以指点。
这种方法能简单的做到居中,但是必须有width和height值
DEMO链接
代码:
<div class="wrap"> <p> <img src="http://nec.netease.com/img/s/1.jpg" alt="" /> <img src="http://nec.netease.com/img/s/1.jpg" alt="" /> </p> </div>
html,body{ width: 100%; height: 100%; margin: 0;}.wrap{ position:relative; width: 100%; height: 100%; p{ position:absolute; left:50%; top:50%; } img{ &:nth-child(1){ position:static; visibility:hidden; } &:nth-child(2){ position:absolute; right:50%; bottom:50%; } }}
这种方法主要是利用了一个图片进行占位,以让父容器获得高宽,从而让进行-50%偏移的图片能有一个参照容器作百分比计算。优点是可以不知道图片的大小,随便放张尺寸不超过父容器的图片上去都能做到居中。另外,兼容性好,如果是不使用nth-child选择器的花,IE6都是能顺利兼容的
四. float布局上下文下的水平垂直居中
DEMO链接
代码:
<div class="wrap"> <div class="ele"> <div class="ele-inner">居中居中居中居中居中居中<br>居中居中居中居中居中居中居中居中居<br>中居中居中居中居中居中居中居中居中居<br>中居中居中居中居中居中居中</div> </div></div>
.wrap{ float: left; width: 100%; height: 400px; background-color: #ccc; .ele{ float: left; position: relative; left: 50%; top: 50%; } .ele-inner{ position: relative; left: -50%; -webkit-transform : translate3d(0, -50%, 0); transform : translate3d(0, -50%, 0); background-color: #333; color: #fff; }}
这种方法的原理,首先是利用float属性将需要居中的元素的父元素.ele的宽度收缩,然后left:50%将.ele的左边和水平中线对齐,这个时候还没居中,还需要将其往回拉自身宽度的50%,于是.ele-inner便是真正需要水平居中的元素,我给它一个position:relative,将其往回拉自身宽度50%就行了。对于垂直方向,依然是先将.ele top:50%到垂直方向中点,但是这时给.ele-inner top:50%是不起作用的,因为如果没给父元素明确高度的话,这个50%是计算不出来的,因此,就有了transform : translate3d(0, -50%, 0)。
这种方法的好处是元素可以不定宽,任何时候都可以做到居中
我当时在w3cplus的站上发现这个方法后,当时觉得这个方法很好,兼容性好,又还可以不定宽,但当我用了一段时间后,发现了一个问题:
就是当居中元素的父元素left:50%时,如果元素宽度足够大,会超出外面的容器,而如果外面的容器又正好是overflow:auto的话,那就会在外面产生滚动条,问题DEMO链接 在这里 ,后来我找到了一个办法: DEMO链接 ,基本思想就是利用元素超出父元素的左边不会产生滚动条的特性,有点奇淫技巧,但是能解决问题,有兴趣的可以看看
DEMO链接
代码:
<div class="wrap"> <div class="placeholder"></div> <div class='content'></div></div>
.wrap{ float: left; width: 100%; height: 400px; background-color: #ccc; @contentHeight : 100px; .placeholder{ float: left; width: 100%; height: 50%; /*居中元素.content高度一半*/ margin-bottom: -(@contentHeight / 2); } .content{ position: relative; left: 50%; transform:translate3d(-50%, 0, 0); clear: both; /*演示用,实际不需要定宽*/ max-width: 100px; height: @contentHeight; background-color: #333; }}
这种方法是先让占位元素.placeholder占据50%高度,然后给一个居中元素高度一半的负的margin-bottom,然后下面的元素只要跟着摆放就能垂直居中了。水平方向就是利用translate做偏移,这个没什么好说的,你也可以换成其他办法。
这种方法就是各种固定死,首先最外层的父容器需要一个固定高度,以让.placeholder的height:50%有效,然后,margin-bottom也需要固定死,而且得需要知道居中元素高度。单纯就水平方向来说,这个方法比较适合需要兼容低版本IE的固定式布局的项目,因为兼容性好。
五.BFC布局上下文下的水平垂直居中
BFC的全称是块级排版上下文,这里有篇 文章 对齐进行了简单的介绍,BFC布局上下文下的布局其实就是利用盒模型本身进行的布局,前面在利用盒模型布局的那一节中已经讲过了,这里就不重复了
六.IFC布局上下文下的水平垂直居中
IFC又是个什么概念呢,你可以看看 官方文档 ,也可以简单的理解为 display为inline性质的行级元素的布局。
DEMO链接
代码:
<div class="wrap"> <div class='placeholder'><!--占位元素,用来作为居中元素的参照物--></div> <div class="ele"></div></div>
.wrap{ width: 100%; height: 400px; /* min-height: 400px; */ text-align:center; font-size: 0; background-color: #ccc; .placeholder, .ele{ vertical-align: middle; display: inline-block; } .placeholder{ overflow: hidden; width: 0; min-height: inherit; height: inherit; } .ele{ width: 100px; height: 100px; background-color: #333; }}
行级元素会受到text-align和vertical-align的影响,关于vertical-align,不太好理解,我多贴几篇文章: @灵感idea 的 , 张鑫旭的 , MDN上的 , css-trick上的 ,以及 官方文档 ,这里首先是用text-center让inline-block水平居中,然后给一个vertical-align:middle,但是仅仅给vertical-align:middle是不够的,因为此时它还没有vertical-align对齐的参照物,所以就给了一个占位的inline-block,它的高度是100%。
这个方法对于居中元素不需要定宽高,而且元素根据vertical-align值的不同不仅仅可以实现居中,还可以将其放在上面下面等。缺点是父元素需定高
DEMO链接
代码:
<div class="wrap"> <div class="ele">居中居中居中居中居中居中<br>居中居中居中居中居中居中居中<br>居中居中居中居中居中居中居中居中<br>居中居中居中居中居中居中居中居中</div></div>
.wrap{ text-align: center; line-height: 400px; width: 100%; height: 400px; background-color: #ccc; font-size: 0; .ele{ line-height: normal; vertical-align: middle; display: inline-block; background-color: #333; font-size: 18px; color: #fff; }}
这个方法,首先是水平方向,text-align:center就行了,至于垂直方向,起作用的就是父容器的一个line-height和居中元素的vertical-align:middle,为什么这两个属性可以让一个inline-block垂直居中呢,这里重点是父容器在其下面产生了一个隐匿的文本节点,这个我在上面 text-align:center + absolute 那个方法的讲解中说到过了,然后这个这个隐匿文本节点会因line-height属性的作用而拥有了一个父容器一样高的行高,此时元素有了一个vertical-align对齐的参照物,再给其vertical-align:middle值就能垂直对齐了。
使用这个方法,居中元素无需定宽高,但缺点是得给父容器一个固定的行高才行。
DEMO链接
代码:
<div class="wrap"> <div class="ele"></div></div>
.wrap{ text-align: center; font-size: 400px * 0.873;/*约为高度的0.873*/ margin-left: auto; margin-right: auto; width: 400px; height: 400px; background-color: #ccc; .ele{ vertical-align: middle; width: 100px; height: 100px; display: inline-block; background-color: #333; }}
这个方法来自淘宝,基本原理还是让隐匿文本节点所占据的行高等于父容器的高度,然后给居中元素一个vertical-align:middle对齐的一个参照。只是这里把定义line-height值换成了定义font-size值,让font-siz足够大从而让其行高等于父容器高度。为了证明这个font-size的作用,我把居中元素换成文本
DEMO链接
代码:
<div class="wrap"> a</div>
.wrap{ text-align: center; font-size: 400px * 0.873;/*约为高度的0.873*/ margin-left: auto; margin-right: auto; width: 400px; height: 400px; background-color: #ccc;}
效果:
可以看到字母a垂直居中了,这个字母a就对应那个隐匿文本节点
七.FFC布局上下文下的水平垂直居中
DEMO链接
代码:
<div class="wrap"> <div class="ele"> 居中居中居中居中居中居中居中<br> 居中居中居中居中居中居中居中<br> 居中居中居中居中居中居中居中<br> 居中居中居中居中居中居中居中<br> 居中居中居中居中居中居中居中 </div></div>
html,body{ width: 100%; height: 100%;}.wrap{ display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; background-color: #ccc; .ele{ background-color: #333; }}
flexbox是个很强大的布局模块,也就三个属性就搞定居中了,而且不论父容器还是居中元素都可以不定宽高。参考链接: 图解CSS3 Flexbox属性
八.table布局上下文下的水平垂直居中
DEMO链接
代码:
<div class='wrap'> <div class='ele'> <div class="ele-inner">居中居中居中居中居中居中居中居中<br>居中居中居中居中居中居中居中居中<br>居中居中居中居中居中居中居中居中居中居中</div> </div></div>
.wrap{ width: 100%; height: 300px; display: table; background-color: #ccc;}.ele{ text-align:center; vertical-align: middle; display:table-cell;} .ele-inner{ display: inline-block; background-color: #333;}
原理就是把div模拟成表格(换成真正的表格标签也是可以的),然后给那几个属性就成了,这个没什么好讲的,不懂的去翻翻手册就明白了,然后@于江水写的一篇 table那些事 还不错
九.CSS grid布局上下文下的水平垂直居中
CSS3 grid layout是IE搞出来的一个布局模块,目前貌似还只有IE0和IE11支持,我没有研究过其居中的方法,有兴趣的可以看看 大漠老师的介绍文章
十.其它未知归属的水平垂直居中方法
DEMO链接
代码:
<button> <div> 居中居中居中居中居中居中<br> 居中居中居中居中居中居中<br> 居中居中居中居中居中居中<br> 居中居中居中居中居中居中<br> </div> </button>
button{ width: 100%; height: 400px; background-color: #cccccc; border-width:0; &:focus{ outline:none; } div{ display: inline-block; font-size: 18px; background-color: #333; color: #fff; }}
这种方法属于奇淫技巧,利用button标签天生外挂的这一技能对其里面的元素进行居中。
原文 http://f2e.souche.com/blog/jie-du-cssbu-ju-zhi-shui-ping-chui-zhi-ju-zhong/