大小不固定的图片、多行文字的水平垂直居中

这篇文章发布于 2009年08月28日,星期五,01:11,归类于 CSS相关。 阅读 391201 次, 今日 69 次 98 条评论

 

作者添加于2017年12月31日:本文很老,仅供参考。

本文综述

想必写css的都知道如何让单行文字在高度固定的容器内垂直居中,但是您知道或者想过让行数不固定的文字在高度固定的容器内垂直居中呢?本文将会告诉你如何实现多行文字的垂直居中显示。

关于图片垂直居中显示,想必很多写css的人都研究过,或者说是搜寻过方法。淘宝团队似乎提供了一种不错的方法,用font-size解决IE下垂直居中的问题,是个好方法吗?是的,方法是不错,可是问题也很多:不支持img外标签的浮动,致使多图片排列时需添加额外标签;需要记住一些比例参数,上手较难;原理艰深,兼容性不稳定等。但是在我看来,这个方法不足够好!本文将提供两种更为新颖的方法,代码简洁,原理简单,上手容易,兼容性强,出错率低的方法。inline-block裸标签对齐法,以及透明图片拉伸对齐法

css是如此的精深,我相信后来人会有更加绝妙的方法。但是,本文提供的几种实现图片垂直居中方法,一定是目前最实用的几种方法。

一、大小不固定,多行文字的垂直居中

① 单行文字

可能很多人都知道如何让单行文字垂直居中显示,就是使用line-height,将line-height值与外部标签盒子的高度值设置成一致就可以了。例如如下css代码:

height:3em; line-height:3em; ……

显示结果如下图:

单行文本垂直居中对齐-鑫空间-鑫生活

② 多行文字

如何实现父容器高度固定,文字可能一行,两行或更多行的垂直居中对齐呢?
实现的关键是把文字当图片处理。用一个<span>标签将所有的文字封装起来,设置文字与图片相同的display属性值(inline-block属性),然后用处理图片垂直居中的方式处理文字的垂直居中即可。
核心css代码如下,
外部<div>标签:

div{display:table-cell; width:550px; height:1.14em; padding:0 0.1em; border:4px solid #beceeb; color:#069; font-size:10em; vertical-align:middle;}

内部<span>标签:

span{display:inline-block; font-size:0.1em; vertical-align:middle;}

下面这张是实例演示页面的效果截图:

行数不固定文字垂直居中对齐

有几点简要说明:

  1. 此例子用em做单位,如果您对em单位了解不够,把握不来的话,可以使用px做单位,值要换;
  2. 外部div不能使用浮动;
  3. 外部div高度和文字大小比例1.14为宜;
  4. 内部标签的vertical-align:middle可以省略,但是外部div高度和文字大小比例要修改,我自己试了一下,高度比字体1.5左右的样子;
  5. 系统原因,我没能够在IE8下测试。

实现的最终效果和JavaScript演示,您可以狠狠地点击这里去看看。

二、大小不固定,图片的水平垂直居中

① 透明gif图片+背景定位的方法

这里利用了background-position:center实现图片居中显示。这是个很实用也是很聪明的办法,对于维护控制成本都很不错。微软必应图片搜索的图片排列就是使用的这种方法。
方法的原理很简单,使用一个透明的gif图片做覆盖层,高宽拉伸至所需要的大小,然后给这个gif图片一个background-position:center声明。而background-image建议写在页面上,因为实际项目中,这肯定是个动态的URL地址,css文件似乎不支持动态URL地址。下面就是实例演示页面的效果截图。

透明图片背景居中定位效果

核心HTML代码为:

<img src="../image/pixel.gif" style="background-image:url(mm1.jpg);" />

其中此img标签已经设置了高宽和背景居中定位的属性。具体实现可以可以狠狠地点击这里进行参照。

② display:table-cell和文字大小控制居中

这个方法可以说就是本文综述部分提到的淘宝团队想出的图片垂直居中的方法。但是本文展示的这个方法的css代码又不是淘宝工程师们的原版代码,我对其做了一定的修改,把里面没有用可以剔除的hack都去掉了。

css代码部分:
<img>外部<div>标签:

div {display:table-cell; width:1em; height:1em; font-size:144px; width:144px; height:144px; font-size:118px; border:1px solid #beceeb; text-align:center; vertical-align:middle;}/*这里的大小是根据高宽上限128像素图片设置的*/

img标签:

img{vertical-align:middle;}

需要说明的:
1.原版的代码中有两个hack,一个是针对文字大小的,另外一个是针对block属性的;后经过我测试推敲后证实这两个hack都是多余的,而*display:block更是多余,因为IE6,IE7根本就不认识display:table-cell是谁!
2.这个通过文字大小控制IE下图片垂直居中是个很不错的方法,要比使用position:relative这类高消耗的css方法要好多了。但是这个方法不足之处在于:不支持<img>外标签的浮动,所以当多图片显示时需要再在外面嵌套一层标签——资源消耗多了!
3.高度:文字大小=1.14,这个比例我一直记着,但是后来我将这个比例的概念淡化了,原因在于多次遇到其他比例实现效果的情况。例如上面,就是1:1实现的。

这里附上效果截图:

table-cell下的水平垂直居中效果截图

图片和文字比不上直接的效果显示,所以建议您狠狠地点击这里

③ display:inline-block和文字大小控制居中

此方法的灵感来自于Google picasa相册的图片显示,代码相当简洁,是个成本很低,效果惊人的方法。适用于多图显示的情况。基本上用裸标签就实现了想要达到的效果。一般而言,图片阵列排列显示的时候,外面都有一个a标签的,起到链接的作用。而本处的方法就只要这一个<a>标签就足以实现图片垂直且居中的显示效果。其关键是将<a>标签默认的inline属性值设置为inline-block,这样<a>标签既支持宽度,又支持vertical-align:middle,配合<img>vertical-align:middle就可以实现图片的水平垂直居中显示了。
css代码:
<a>标签:

a{display:inline-block; width:1.2em; font-size:128px; text-align:center; vertical-align:middle;}

img标签:

img{vertical-align:middle;}

就这么简单,就实现了图片的垂直居中效果。下截图为证:

精简方法实现的水平垂直居中对齐

另外补充说明的:<img>外的标签需是<a>标签或<span>这类inline水平的标签,<div>标签也可以,但是css代码多些: display:inline-block;*display:inline; zoom:1; IE下要先变成inline属性,再转变成类似于inline-block的属性,原因讲起来又是一篇长长的文章,放着。

建议您狠狠地点击这里直接查看源代码

④ 透明图片拉伸对齐实现垂直居中显示

这个方法是自认为相当不错的一个方法,说实话,想到这个方法是自然而然的,经过试验发现真的很管用。对比淘宝团队的方法,发现优势很多,基本上淘宝的table-cell+font-size方法会带来的些问题都避免了。
非常简单,非常易懂,出错率低,上手方便,兼容性上佳!

原理简述:
一句话,将要显示的图片与一张透明的高度100%,宽度1像素的透明图片vertical-align:middle对齐。
其核心原理其实与利用font-size大小实现IE下图片垂直居中是一致的。将font-size设置得很大,目的是撑开IE下默认文字空间的高度,其性质类似于空格,然后通过vertical-align:middle属性让图片与这个高高的空白空格空间垂直居中对齐;而这里将这个看不见的文字空间实例成一张透明的gif图片,高度可以轻松设置为外部标签的高度,宽度压缩至最小,然后通过vertical-align:middle对齐,就实现效果了,由于影响布局的差不多就vertical-align:middle这一个属性,所以出现兼容性问题的可能性比table-cell的方法要低得多。

需要注意的:
1.<img>外容器宽度要大于要显示的图片的最大宽度+1像素;
2.<img>外容器的字体大小设为0px,也可以不设,但是两个<img>标签要连着写,避免空格;

以下是核心的一些代码:
HTML部分:

<li>
    <img loading="lazy" src="https://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" /><img src="../image/pixel.gif" />
</li>

css部分:

li{height:128px; width:150px; padding:13px 0; float:left; margin-right:10px; border:1px solid #beceeb; text-align:center; font-size:0;}
li .alpha_img{height:100%; width:1px; vertical-align:middle;}
li .alpha_img{height:100%; width:0; vertical-align:middle;}
li .show_img{vertical-align:middle;}

其实,只要有上面绿色部分的css代码就足够了。
简单的超乎想象。

要显示的图片后面跟了一个高度撑满容器,只有1px宽,宽度为0即可,透明的图片。这两个图片分别vertical-align:middle,就实现了要显示的图片与这个拉伸的透明图片的居中对齐了,由于透明图片是透明的,不可见的,宽度也只有1像素宽度也为0,所以看上去就是要显示的图片相对于容器垂直居中了。

另外,其实这里不一定是透明的图片,使用任意的图片都可以,所以您其实说不定可以减少一次http请求,使用任意的图片将其拉伸至高度为容器高,宽度1像素宽度0就可以了。

甚至,使用<span>标签,<div>标签也可以实现同样的效果。只要将<span>标签或<span>标签转换成inline-block表现或类似于inline-block表现就可以了。
我个人更推荐使用行内元素,例如<span><i>标签等,只要应用类似下面的CSS:

span{display:inline-block; height:100%; width:0; vertical-align:middle;}

相比图片而言,多了个display:inline-block,但是会少一次链接请求。效果图和上面的一样的,完美的水平垂直居中。原理也与图片一样,相信很容易理解的。

再提供一下实例页面的链接,狠狠地点击这里,实例页面的最后一种方法向您展示了这种新颖的图片垂直居中的方法。

最后,说句实在话,我知道这应该不算什么新颖的方法,在我之前想到这种方法的人肯定不在少数,但是留迹于网上的却没有,我是没有发现过。我不清楚是这些大牛的公司要求技术保密,还是自身不愿分享研究成果。我相信不是这样的,主要还是他们很忙碌,没有时间写这些东西。像我这样,”闲暇”的很,花十几个小时写一篇文章的估计不多,呵呵。

补充于2009-11-03 15:32
正如我经常挂在嘴边的,css博大精深,你需要花费精力去观察它,研究它。这里,我再提供一种我刚刚试验出来的一种新方法,实现大小不固定的图片水平垂直居中,综合来讲,比上面所有提供的方法还要优秀,且没有hack,兼容性上佳(支持IE6、IE7、Firefox、chrome、Safari浏览器-IE8未测(补充:我后来又测试了一下,结果在IE8浏览器和Opera浏览器下是不垂直居中的,所有此方法还是有待商榷的)。下为在IE7下的效果截图:

新方法实现垂直居中

此方法原理是,在IE下使用font-size使图片垂直居中显示,Firefox,chrome等现代浏览器使用line-height配合<img>本身的vertical-align属性使垂直居中显示,由于两者不冲突,所以没有hack就实现的效果。css代码简洁明了,关键是HTML代码非常清晰,一层外标签,里面就是img标签,我想很难再找出比这个方法更出色的让图片水平垂直居中的方法了。好吧,其实这个方法是有一点不完美的,就是opera浏览器下图片无法垂直居中显示,幸好国内而言,使用opera浏览器的比例很低,所以综合来讲这个方法是个非常优秀的图片水平垂直居中的方法。

以下为css代码部分:

.zxx_ul_image li{float:left; width:150px; height:150px; text-align:center; line-height:150px; font-size:125px;}
.zxx_ul_image li img{vertical-align:middle;}

.zxx_ul_image li{float:left; width:150px; height:150px; text-align:center; line-height:150px; *font-size:125px;}
.zxx_ul_image li:after{content:' '; vertical-align:middle;}
.zxx_ul_image li img{vertical-align:middle;}

可以看到,代码非常简洁易懂,HTML部分代码就不上了,您可以单击下面的demo,里面有HTML代码的展示以及效果的预览。

建议您狠狠地单击这里:独立的demo实例页面

(本篇完)

分享到:


发表评论(目前98 条评论)

  1. july_L说道:

    同问楼下的问题,下面我写的跟鑫哥最后一个很像
    http://jsbin.com/cayirogera/6/edit?html,css,js,output

    鑫哥最后一种方法的伪类好像是多余的
    http://jsbin.com/ceyihakete/4/edit

  2. 子顾说道:

    大小不固定,多行文字的垂直居中 的第 2点,多行文本那里,为什么我试验的时候,会是这样的效果?
    试验链接:http://jsbin.com/leliqe/2/edit?html,css,output 麻烦博主帮我看一下

  3. display:inline-block和文字大小控制居中说道:

    display:inline-block和文字大小控制居中 这个方法! width:1.2em; font-size:128px; 按照这样写总是效果不佳。 我将他们直接写成 width:150px;就完全没问题了!不太明白为什么

  4. 王木木说道:

    最后一个办法代码是很简洁,可是在chrome浏览器下就没有垂直居中诶~~~

  5. 北京前端开发说道:

    如果图片尺寸有大于盒子尺寸的,而且宽高哪个大都有可能的这种图片,怎么垂直水平居中,兼容ie78,用了express,ie8不ok

  6. xiaohui说道:

    在安卓手机下,全部失败,楼主试试,浏览器模拟手机安卓系统,

    在图片的大小可能超过外层容器的条件下,宣告全部失败

  7. 龚三说道:

    群主的博客看着真心爽啊!

  8. taotao说道:

    第四个方法,没有实现垂直居中呀,> <

  9. HM说道:

    旭哥,关于多行文字垂直居中的写法,在html5的文档声明下,貌似没有办法做到垂直居中,不知道在html5文档声明的环境下,如何改进写法来达到多行文字垂直居中的效果,望赐教,谢啦~

  10. 小强说道:

    最近发现学长这个好网站,学习了很多啊,膜拜。
    我的小疑问是对于多个span想要居中div

    有什么常用的方法。
    我一般都是设个absolute,然后margin-top (div.width-span.width)/2
    谢谢啦

  11. chen说道:

    这篇文章能解决图片和文字垂直居中的问题 但是如何解决图片等比例缩放且垂直居中呢?

  12. toyean说道:

    CSS的确不支持动态URL地址,不过有方法可以实现的。

  13. 黄浩林说道:

    想请教下,多行垂直居中,用padding不就可以实现吗?????与您在上文提到“将文本当做图片来处理”的方法,在实现过程中有什么差别呢????求教!

  14. della说道:

    多文字垂直居中,如果在 html5 中就会偏下

  15. jonwade说道:

    你好 你的页面被黑了吗 那个图片居中对齐的 微软的写法 pixel.gif的图片好像被人换了

  16. 前端观察站说道:

    很好,谢谢分享~~顶一个!

  17. Steven Wang说道:

    .zxx_ul_image li{float:left; width:150px; height:150px; text-align:center; line-height:150px; overflow: hidden; *font-size:125px;}
    .zxx_ul_image li:after{content:’ ‘; vertical-align:middle;}
    .zxx_ul_image li img{vertical-align:middle;}

    这个方案是当前最完美的一个方案了,主流浏览器基本上都支持
    这个方案其实也支持 Opera 浏览器,把文档类型声明为 XHTML 1.0 Strict 或 就可以了

    • Steven Wang说道:

      最后一句有 html 标签,提交时被被干掉了,补充一下:

      把文档类型声明为 XHTML 1.0 Strict 或用 html5 文档类型声明,就可以支持 Opera 浏览器了

    • 珲珲哥说道:

      测试了这个方法,没有绝对居中,有像素级的差距,父元素如果设置了背景色和边框,及内边距,就能很明显看出没有居中

  18. fsy0718说道:

    头部的文档申明对多行文字的垂直居中有影响,假如是html5的申明,那个方法将无效

  19. sharon说道:

    好像父容器是绝对定位的时候也无效呀!

  20. Marker说道:

    好吧。我又来啦。上面的回复删掉吧。唉。我想表达的是。我输入一个aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa怎么办。这个个DIV就会自动增宽。第一次我用了word-break:break-all。没问题。但是跟着就是输入一个英文单词。会强制断行。但是如果我用word-wrap:break-word的话。。这段字符又不起作用啦!如果一起用。。呵呵。也不行。我也矛盾啦。。。。。。。也就吃饱撑的输入aaaaaaaaaaaaaaaaaaaaaaaaa

  21. Marker说道:

    这个方案确实很完美啦!但是差了一点。当我这个DIV里输入的全是英文的时候。这个DIV就会自动增宽啦。我们要让英文强制断行。
    word-wrap:break-word

  22. 无名说道:

    感谢张鑫旭的分享和付出。

  23. 一路说道:

    还是鑫哥最后的方法比较省劲儿,但设置100%的不一定非是图片,只要是inline-block的元素都可以

  24. shooke说道:

    display:table-cell;这个属性万恶的ie6是不会理解你的用心的

  25. afei说道:

    其实,有个更好的办法;
    ie67:writing-mode:tb-lr;text-align:center;

    w3c+ie8/9:display:table-cell; vertical-align:midde;

  26. 老公公说道:

    博主的方法如果图超过容器大小就会有问题

  27. BlwooSky说道:

    博主,请问文章中的font-size:118px; 设置的是各HTML标签中的空白文本节点吗?这个只在IE6、7下有用吗?

  28. 火星-大象说道:

    要是给图片加一个strong标签包裹的标题了?淘宝那个多一层div的demo试用,非Trident内核浏览器成功了,Trident内核惨不忍睹~~其它几个没达到预期效果~

  29. Robin说道:

    感觉多行文字垂直居中的这个解决办法不是很理想,字体大小的计算的败笔,代码代码也有一些多,个人的见解:
    demo:
    外面一层div [ width:400px; height:300px;]
    里面一层div [ width:300px; height:200px;]
    给内外两层固定的width和height,然后给内层定义的样式 [position:relative; top:50%; left:50%; margin:-100px 0 0 -150px ]
    即把里面的div定位到中间后,再 – 对应的宽度高度的一半。
    欢迎讨论

  30. Rodey说道:

    怎么我在a标签中插入img标签后,按照你的方法是无法垂直居中的

  31. BlwooSky说道:

    你好,有个问题,我百思不得其解,vertical-align:middle,文档上说:middle 把此元素放置在父元素的中部。于是,我的问题就来了,你写的那个多行文字垂直居中里面,外层的div设置了该属性,为什么会对内部的span有影响?

  32. 周Ali说道:

    移动设备上的浏览器大多数对line-height设置单行文字垂直居中的效果都不是那么好的!

  33. ss说道:

    我操,博客主人帮助了不少码农啊。

  34. chuan说道:

    最后那个方法,font-size:125px不正确,height与font-size的比值大约是1.14

  35. 37°C说道:

    如果我的高度给1000px;你在试试这个是不是垂直居中的

  36. 37°C说道:

    font-size:10em; 这句话很猥琐,这个东西不兼容!障眼法啊 鑫哥

  37. 飞烟说道:

    你的多行文字居中那一块,不知道你发现一个问题没,如果里面的文字全是英文的话就出问题了,里面的文字不会断行,而div随着文字的多少自适应的改变宽度,而始终保持一行的文字垂直居中。

  38. 小气说道:

    很不错写的,我也是做前端的,有小一年了快,但是现在感觉很迷茫。希望鑫哥能指点指点。我的QQ75624839,谢谢了。

  39. 魏星博客说道:

    很不错,正好用到,谢谢!

  40. time说道:

    文中最后一种补充的方法,你在firebug下可以看到,img不是相对于父容器li垂直居中的,而是图片相对于图片之前垂直居中,这也是由于vertical-align:middle;实现的。

  41. black_angle说道:

    第二种方法的背景图片如果很大的话怎么处理,这样的样式可能只能显示背景图片的一部分。在网上找了下,说最新的样式里面加了background-size属性,但是目前大部分浏览器还没有支持。

  42. lucky说道:

    ③display:inline-block和文字大小控制居中:我只用了a img{ border:1px solid #66F; vertical-align:middle; margin:12px; padding:2px;} 而已,在浏览器上不会有错位,为什么你要加display:inline-block;这个属性呢?这个没影响啊

  43. css森林说道:

    方法② display:table-cell和文字大小控制居中,在ie7下明显的不居中,ie6下撑大Li高度再居中,何解?

  44. webtim说道:

    IE6跟IE7不兼容!不知道你行不行!希望你能把淘宝工程师的那个文件发给我下吗?就是有hack的那个!QQ5224032

  45. 叶子说道:

    table-cell的方法…在ie7中不居中…

  46. Kymo说道:

    博主的文章都是精品呀

  47. ithinc说道:

    最后一个方法,如果你给每个li加上border,你会发现vertical-align: middle不是沿父元素中部对齐的。

  48. cqx说道:

    不错的方法..
    不过在Opera中没有垂直居中..

  49. 不错喔会常来的

  50. chena说道:

    博客空间不错。加下我的Q:6281470.希望可以交流~