书写html换行产生空白符的坑及解决办法(持续更新)

4,860 阅读4分钟

前言

在我们书写html代码的时候,为了便于阅读,标签与标签之间常用空格、换行隔开,但是在IE8以后的浏览器包括现在的Chrome、opera等浏览器中,把节点与节点之间的空白符(即空格和换行)也视为文本节点。因为这个原因而产生出很多坑。下面盘点一下笔者碰到的。

  1. 最开始是实现li标签行内排列的时候碰上的
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <style type="text/css" media="screen">
    *
    {
        margin: 0;
        padding: 0;
    }
        html
        {
            font-size: 62.5%;
        }
        nav
        {
            width: 100%;
            line-height: 3rem;
            background-color: blue;
            padding: 0 1.5rem;
        }
        ul
        {
            text-align: left;
        }
        li
        {
            display: inline-block;
            background-color: red;
            padding: 0 1.5rem;
        }
    </style>
</head>
<body>
    <nav>
        <ul>
            <li>登录</li>
            <li>关于</li>
            <li>注册</li>
            <li>帮助</li>
            <li>退出</li>
        </ul>
    </nav>
</body>
</html>

结果是这个样子的:

这是因为在li换行的时候会产生一个空白符,并把它视为一个文本节点,且具有宽度。

2.第二次是用原生JS获取子节点时候
 在JS中获取子节点有以下几种方法:  

  • firstElementChild
  • firstChild
  • childNodes
  • children

我们通过一个例子来分析这几种方法的区别(获取div下的p标签)

输出结果是这样的:

#text就是因换行而产生的文本节点。

从上面这个例子可以看出firstElementChild和Children比较针对,只会返回指定元素里面的元素节点,文本节点和属性节点都不予理会,但firstElementChildren 在ie9以前不兼容,会返回undefined。

而firstChild、childNodes就厉害了,事无巨细,无论是元素、文本、属性啥都给你获取过来,所以上面那个例子里获取到的是空白符,所以使用这俩的时候要小心一些,最好使用Children来获取比较保险。

3.有一题面试题是这样的:使两个div,一行显示,宽度比例为40%、60%,要给出尽可能多的方案,其中一个方案就是

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        #one {
            background-color: blue;
            width: 60%;
        }
        #two {
            background-color: red;
            width: 40%;
        }
        div {
            display: inline-block;
            height: 100px;
        }
    </style>
</head>
<body>
    <div id="one"></div><div id="two"></div>
</body>
</html>

用display: inline-block实现就一定要注意标签之间的空白符,如果不消除掉空白符,就会因宽度不够把第二个div挤到下一行去
注:另一个方案就是弹性布局,一个flex:2,另一个flex:3,欢迎在评论区中补充~
......

解决办法:

1.写html代码时,把所有li标签写在一行里,从根本上消除空白符,但是这样影响代码阅读,不易于后期维护。

<body>
    <nav>
        <ul>
            <li>登录</li><li>哈哈</li><li>嘿嘿</li><li>帮助</li><li>退出</li>
        </ul>
    </nav>
</body>

2.这是一个很有意思的方式,就是li标签不闭合,让其自动补全,也是可以清除空白。

<body>
    <nav>
        <ul>
            <li>登录
            <li>哈哈
            <li>嘿嘿
            <li>帮助
            <li>退出
        </ul>
    </nav>
</body>

3.还可以给li标签一个负边距来抵消空白符的宽度,但是有一个缺点,就是空白符作为文本节点,其大小跟父节点ul标签有关,而ul标签又跟浏览器有关,所以负边距的大小不好确定。(一般是3像素)

margin-left:-3px;

4.既然空白符大小跟ul标签有关,那我们可以把ul标签的字体大小设置为0,再给li标签设置实际字体大小,这样就可以使空白符的大小为0。

<style>
    ul {font-size:0;}
    li {font-size : 1.2rem;}
</style>

5.css4草案中有一个新增属性:white-space-collapsing,也可以解决这个问题,但是现在几乎没有浏览器支持,让我们展望未来吧。