84669 person learning
152542 person learning
20005 person learning
5487 person learning
7821 person learning
359900 person learning
3350 person learning
180660 person learning
48569 person learning
18603 person learning
40936 person learning
1549 person learning
1183 person learning
32909 person learning
子容器小于父容器的情况,我知道如何垂直居中。
但是当子容器的高度超过父容器的时候,我如何让子容器相对于父容器垂直居中?
PS: 补充一句,子容器宽度是百分比,动态的。父容器的宽度是100%。
效果如图, 让红色部分相对于绿色部分垂直居中:
认证高级PHP讲师
更新:出文章啦,还有表格参考哟http://blog.segmentfault.com/humphry/1190000000381042
相信每一个前端都或多或少总结过居中吧。这里是居中的最麻烦最不好处理的一个情形:子元素溢出。
我们在解决这个问题之前,先回顾一下,子元素不溢出父元素的时候,我们常见的CSS居中方案。以及为何在子元素溢出的时候,问题变得棘手。
首先我们确定计算流程:
H外 = H内 + 2 * H补 ;
子容器溢不溢出,这个流程都不会变。
我们可以看到,要做到计算,我们必须拿到两个值,一个是H外,一个是H内。
在到了需要JS计算的时刻,这些值都可以通过CSSOM来取得,而使用jQuery具体的做法如@怡红公子所说,就不多说了。
而CSS布局的核心在于,在父容器高宽不固定的时候,如何让浏览器帮我们计算?
我们必须保证浏览器解析到相应的样式时,能够拿到H外和H内。
这个方案已经滥了。
.outer{ position: relative; overflow: hidden ; } .inner{ position : absolute; top: 50%; height: 20px; margin: -10px; }
我们不相信浏览器,使用手算,将子元素挪去自身高度的50%。这个方案也可以支持子元素高度溢出的情形。
优点:
缺陷:
position:absolute;
.outer { height: 300px; line-height: 300px; }
如果内容只有一行文字,很简单。line-height作用于line-box,把line-box撑到和父容器一样高,文字节点默认对齐于line-box的baseline。
内部容器,则需要作为行内元素呈递:
.inner { display: inline-block; }
:before
这个方案是可以改进,以适应溢出情形的,在中间增加一层足够高(你来定义一个高度,比如10000px)的容器,用负margin方法垂直居中于外层,然后用line-height=height方法让内部居中于中间层。实现比较复杂,也结合了两种方案的优点,和……缺点。个人觉得还不如直接使用负margin方案来得爽快些。
.outer{ position: relative; height: 100px ; overflow: hidden ; } .inner{ margin-top : auto; margin-bottom : auto; position : absolute; top: 0; bottom: 0; height: 20px; }
这个的原理写在CSS2.1中:
‘top’ + ‘margin-top’ + ‘border-top-width’ + ‘padding-top’ + ‘height’ + ‘padding-bottom’ + ‘border-bottom-width’ + ‘margin-bottom’ + ‘bottom’ = 包含块的高度
在其他值不是auto的时候,margin-top和margin-bottom是可以根据上式算出的,原理类似于水平居中。看到没有,这个包含块高度算式就复现了我们需要的计算过程。
子元素高度溢出父容器时,这个方案依然可行。
这是CSS2.1范畴内适用面最广的垂直居中方式。能够涵盖溢出的情形。
见图片垂直居中tabel_cell
display:tabel-cell
这个方案不符合楼主的要求,就不多说了。
见居中百分比宽高的元素
.inner{ position : absolute; top: 50%; transform: translate(-50%, -50%); }
这里其实是负margin的改版,仅仅是用translate替换了负margin,因为translate是针对容器本身的。
优点
缺点
.inner{ -webkit-transform:translate(-50%, -50%); -moz-transform:translate(-50%, -50%); -ms-transform:translate(-50%, -50%); -o-tranform:translate(-50%, -50%); transform:translate(-50%, -50%); }
.inner{ background-image : url() ; background-size: cover ; height: 100% ; display: block ; }
如果是一个图片,可以用background-size:cover或background-size:contain来做到简单的居中。若不需要拉伸,也可以使用background-position-y:center来做。
background-size:cover
background-size:contain
background-position-y:center
为何不把这个方案放在CSS2.1中呢,因为只有在CSS3中,背景才可以相对容器变化大小,比如等于容器高度:
.inner{ background-size: auto 100% ; }
或者等于容器宽度
.inner{ background-size: 100% auto ; }
缺点:
很抱歉,我还没有试验出flexbox在子元素溢出时也能保持居中的解决方案……最好的结果是子元素被拉伸(= =#)。有人有过实例吗?
其实在这里讨论的居中方案暗含了一个条件:父容器overflow:hidden,父容器本身就有BFC……其实前端排版中的垂直居中还不止于此,父容器可以被撑高是另外一种情形,不过偏离LZ的问题太远,这里不再多说。
overflow:hidden
如果超过部分上下正好是一样的话,直接用line-height: 子容器高度(单行情况)或者display:inline-table;vertical-algin:middle;(对应其它情况)保证在子容器居中就可以保证相对于父容器居中了吧。另外,如果不兼容过时的浏览器的话,可以试试CSS3的一些东西,做垂直居中还是非常简单方便的:http://zh.learnlayout.com/flexbox.html
line-height: 子容器高度
display:inline-table;vertical-algin:middle;
如果超过部分上下不一样的话我暂时只能想到用JavaScript计算差值然后给margin的方法呢。(示例是jQuery的语法,语义版,father是红色方框,子容器的内容需要再包括在一个标签内):
margin
father
var father = $('.father'), child = father.children(), grandfather = father.parent(); var marginTop = grandfather.offset().top - father.offset().top + (grandfather.height() - child.height())/2; child.css('margin-top', marginTop+'px');
额,之前好像没看清楚题目,谢谢 @Humphry 提醒。如果只是容器要垂直居中的话可以用JavaScript计算两者高度相减除以2,并给与margin-top,或者直接使用CSS3的calc()计算margin-top的值就好了,关于这个你可以看看这个:http://www.qianduan.net/calc-at-at-at-page-intelligent-layout.html
margin-top
calc()
var father = $('.father'), child = father.children(); var marginTop = (father.height() - child.height())/2; child.css('margin-top', marginTop+'px');
这个实现比较简单,希望能解答你的问题,我是这么理解的。
http://jsfiddle.net/BNnXN/
更新:出文章啦,还有表格参考哟http://blog.segmentfault.com/humphry/1190000000381042
相信每一个前端都或多或少总结过居中吧。这里是居中的最麻烦最不好处理的一个情形:子元素溢出。
我们在解决这个问题之前,先回顾一下,子元素不溢出父元素的时候,我们常见的CSS居中方案。以及为何在子元素溢出的时候,问题变得棘手。
思路
首先我们确定计算流程:
子容器溢不溢出,这个流程都不会变。
我们可以看到,要做到计算,我们必须拿到两个值,一个是H外,一个是H内。
在到了需要JS计算的时刻,这些值都可以通过CSSOM来取得,而使用jQuery具体的做法如@怡红公子所说,就不多说了。
而CSS布局的核心在于,在父容器高宽不固定的时候,如何让浏览器帮我们计算?
我们必须保证浏览器解析到相应的样式时,能够拿到H外和H内。
CSS2.1
子元素负margin方案
这个方案已经滥了。
我们不相信浏览器,使用手算,将子元素挪去自身高度的50%。这个方案也可以支持子元素高度溢出的情形。
优点:
缺陷:
position:absolute;
,子元素对外层高度、宽度塌陷,不能撑宽父容器了。父容器 line-height = height 单行方案
如果内容只有一行文字,很简单。line-height作用于line-box,把line-box撑到和父容器一样高,文字节点默认对齐于line-box的baseline。
内部容器,则需要作为行内元素呈递:
优点:
缺陷:
:before
伪元素。具体方案见CSS小工具,同时inline-box之间的空格间隙需要被考虑在内,见去除inline-block元素间间距的N种方法。这个方案是可以改进,以适应溢出情形的,在中间增加一层足够高(你来定义一个高度,比如10000px)的容器,用负margin方法垂直居中于外层,然后用line-height=height方法让内部居中于中间层。实现比较复杂,也结合了两种方案的优点,和……缺点。个人觉得还不如直接使用负margin方案来得爽快些。
子元素margin:auto方案
这个的原理写在CSS2.1中:
‘top’ + ‘margin-top’ + ‘border-top-width’ + ‘padding-top’ + ‘height’ + ‘padding-bottom’ + ‘border-bottom-width’ + ‘margin-bottom’ + ‘bottom’ = 包含块的高度
在其他值不是auto的时候,margin-top和margin-bottom是可以根据上式算出的,原理类似于水平居中。看到没有,这个包含块高度算式就复现了我们需要的计算过程。
子元素高度溢出父容器时,这个方案依然可行。
优点:
缺陷:
position:absolute;
,子元素对外层高度、宽度塌陷,不能撑宽父容器了。这是CSS2.1范畴内适用面最广的垂直居中方式。能够涵盖溢出的情形。
display:table-cell + vertical-align方案
见图片垂直居中tabel_cell
优点:
缺陷:
display:tabel-cell
本身让很多属性无效display:tabel-cell
IE6和IE7不支持这个方案不符合楼主的要求,就不多说了。
CSS3
-50% 的 translate方案
见居中百分比宽高的元素
这里其实是负margin的改版,仅仅是用translate替换了负margin,因为translate是针对容器本身的。
优点
缺点
background方案
如果是一个图片,可以用
background-size:cover
或background-size:contain
来做到简单的居中。若不需要拉伸,也可以使用background-position-y:center
来做。为何不把这个方案放在CSS2.1中呢,因为只有在CSS3中,背景才可以相对容器变化大小,比如等于容器高度:
或者等于容器宽度
优点:
缺点:
flexbox方案
很抱歉,我还没有试验出flexbox在子元素溢出时也能保持居中的解决方案……最好的结果是子元素被拉伸(= =#)。有人有过实例吗?
其实在这里讨论的居中方案暗含了一个条件:父容器
overflow:hidden
,父容器本身就有BFC……其实前端排版中的垂直居中还不止于此,父容器可以被撑高是另外一种情形,不过偏离LZ的问题太远,这里不再多说。如果超过部分上下正好是一样的话,直接用
line-height: 子容器高度
(单行情况)或者display:inline-table;vertical-algin:middle;
(对应其它情况)保证在子容器居中就可以保证相对于父容器居中了吧。另外,如果不兼容过时的浏览器的话,可以试试CSS3的一些东西,做垂直居中还是非常简单方便的:http://zh.learnlayout.com/flexbox.html如果超过部分上下不一样的话我暂时只能想到用JavaScript计算差值然后给
margin
的方法呢。(示例是jQuery的语法,语义版,father
是红色方框,子容器的内容需要再包括在一个标签内):额,之前好像没看清楚题目,谢谢 @Humphry 提醒。如果只是容器要垂直居中的话可以用JavaScript计算两者高度相减除以2,并给与
margin-top
,或者直接使用CSS3的calc()
计算margin-top
的值就好了,关于这个你可以看看这个:http://www.qianduan.net/calc-at-at-at-page-intelligent-layout.html这个实现比较简单,希望能解答你的问题,我是这么理解的。
http://jsfiddle.net/BNnXN/