不可忽略的空格(white-space)

5,807 阅读3分钟

问题描述

富文本编辑器中需要实现一个可编辑的导航树,在上线运行时客户反馈其设置的导航树的空格不起作用。具体问题如下所示:

空格bug

由此可以看到HTML文本节点与渲染展示的内容不同,造成了用户直观感受到的输入空格不起作用。

问题原因

空格之所以被忽略是因为浏览器对HTML文本中空格的处理规则:文本的前部和后部的空格会被忽略,内部的连续空格只会算作一个,也就是说浏览器默认会忽略空格的存在。也就是说下面的代码是等价的:

<p>  hello  word  </p>
<p>  hello  word</p>
<p>hello  word  </p>
<p>  hello word  </p>
<p>hello word</p>

最终的渲染结果都是:

hello word

解决方案

使用&nbsp;或者&#160;

针对空格HTML中可以使用转译字符,也就是使用&nbsp;或者&#160;,如下是针对问题的修改:

解决问题

如上所示这时就可以展示空格了。但是这时候需要注意一点时在使用react的时候直接使用&nbsp;替换空格做为文本内容时,&nbsp;会原样输出的,如下所示:

react使用 产生问题

这是因为react将变量的内容完全当成文本输出了,而不是采用转译渲染,这时我们需要如下的操作可满足需求:

render () {
    const title = '😄&nbsp;&nbsp;&nbsp;&nbsp; 测试置&nbsp;&nbsp;&nbsp;&nbsp;顶文件夹'
    return (<a styleName="node_title" dangerouslySetInnerHTML={{__html: title}}></a>)
}

但使用dangerouslySetInnerHTML已经是不被推荐的方式,因为这会有潜在的被攻击的缺陷存在。可以使用Unicode非破坏的空格字符:

render () {
    const title = '😄      测试置         顶文件夹'
    return (<a styleName="node_title">
        {
            title.replace(/\s/g, '\u00a0')
        }
    </a>)
}

这样就可以实现展示空格了。

使用pre标签

HTML <pre>元素表示预定义格式文本。在该元素中的文本通常按照原文件中的编排,以等宽字体的形式展现出来,文本中的空白符(比如空格和换行符)都会显示出来。

如上是MDN中对<pre>标签的说明,如此我们可以对需要输出多个空格的内容使用<pre>标签进行包裹:

pre标签

使用csswhite-space属性

如下所示是csswhite-space属性的各个值对空格等处理规则。

white-space

csswhite-space属性各个值:

  • normal: 连续的空白符会被合并,换行符会被当作空白符来处理。
  • nowrap: 和normal一样,连续的空白符会被合并。但文本内的换行无效。
  • pre: 连续的空白符会被保留。在遇到换行符或者
    元素时才会换行。
  • pre-wrap: 连续的空白符会被保留。在遇到换行符或者
    元素,或者需要为了填充「行框盒子(line boxes)」时才会换行。
  • pre-line: 连续的空白符会被合并。在遇到换行符或者
    元素,或者需要为了填充「行框盒子(line boxes)」时会换行。
  • break-spaces: 与pre-wrap的行为相同,除了:(任何保留的空白序列总是占用空间,包括在行尾; 每个保留的空格字符后都存在换行机会,包括空格字符之间; 这样保留的空间占用空间而不会挂起,从而影响盒子的固有尺寸(最小内容大小和最大内容大小)。

white-space解决