HTML中的“空白符”,你真的懂了吗?

这几天由于某项任务,暂时转型了成为了前端码农(实际上就是个写初级CSS的屌丝)。在这期间,我有一个需求大致是这样的:

我有一个父类容器,比如div,这个div的宽度是固定的。我现在要在这个div中插入5个img,这5个img等宽。同时伴随这5个img的当然还有四个间隙,这四个间隙也是等宽的。

当然,需要根据百分比宽度进行简单适配。
是不是觉得很简单呢?呵呵,别说专业的前端工程师,我这种半吊子都觉得简单。
根据PSD效果图,我量出了对应的百分比尺寸,于是写出来如下的HTMLCSS代码:

// HTML 文件
<div class="parent">
    <img class="element" src="http://xxxxxxx.com/shshshshs.png" />
    <img class="element" src="http://xxxxxxx.com/shshshshs.png" />
    <img class="element" src="http://xxxxxxx.com/shshshshs.png" />
    <img class="element" src="http://xxxxxxx.com/shshshshs.png" />
    <img class="element" src="http://xxxxxxx.com/shshshshs.png" />
</div>

// css 文件
.parent {
    width:x%;
}

.parent img {
    width:y%;
    height:auto;
    margin-left:k%;
}

.parent img:first-child {
    margin-left:0;
}

这段代码相当简洁明了吧,我通过量好的百分比,对各个图片和之间的间距进行了控制,基本上业界大多数也是这么做的吧。

按理说事情到这基本就结束了,毕竟img是个行内可替换元素,会自动布局在一行之内,当然前提是父容器宽度足够的前提下。不过既然我都身体力行的量过了,那自然不应该出现问题。

但是,卧槽,你越担心的事就越会发生。整个界面出现了非常奇葩的现象:

这是正常情况:
[图<-><-><-><->图] 

这是实际情况:
[图<-><-><-><->]
图]

卧槽,竟然宽度不够,换行了。尝试了很长时间,后来发现,将.parent img中添加float:left就可以完美解决,但这什么原因呢?

原因

经过一番探索研究,我发现,这是由于空白符inline类型的元素造成的影响。

  • 首先,img元素是一种行内可替代元素,效果基本可以理解为inline-block
  • 第二,我们在HTML的时候,为了在编辑器内写的美观,常常会使用回车,而回车在HTML中会被识别为空白符。

    比如
    <img src = "xxxx" />(空白符)
    <img src = "xxxx" />
    
  • 第三,空白符具备宽度(和font-size有关),不具备高度。

所以,表面上我们根据设计好的图片进行了精准的测量,构造了完全匹配父类宽度的元素和间距,但是实际上却由于空白符所具备的宽度而产生了偏差。

用一张图来表示拥有空白符后的效果:

[(空白)<->图(空白)<->图(空白)<->
图<->]

为什么float可以解决这个问题

A floated box is shifted to the left or right until its outer edge touches the containing block edge or the outer edge of another float

看到这个关于float的定义了吗?float要么依赖前一个(或者后一个)float元素的边界,要么就依赖于父元素的边界。而一个空白符,既不是包含块(父容器)的边界,也不是另一个float元素,因此不受影响,也不会对其余float元素有影响。

所以,当你对.parent img启用float:left之后,效果就成了下图所示:

[float<->float<->float<->float<->float]
[空白符]

这次我们测量的宽度正好匹配完全,所以将空白符自然而然的挤到了下一行。还记得我们前面说过空白符不具备高度吗?因此,这个空白符压根没起作用!

文中的 [] 代表父容器,<-> 代表间隔。

其余方案

  1. 将父容器的font-size设置为0
  2. 避免换行,写出 这样的代码。
  3. 启用HTML压缩。

最后:感谢美团大神FTR和淘宝大神YWJ对本菜比的指导。