防止/解决浏览器将行间的'\n'转换为空格(针对中文字符)

19

将换行符转换为空格对英文有意义,例如以下 HTML:

<p>
This is
a sentence.
</p>
我们在浏览器中将换行符转换为空格后得到以下结果:
This is a sentence.

这对英语很好,但对于中文字符就不好了,因为我们在中文中不使用空格来分隔单词。这里有一个例子(中文句子的意思与“这是一个句子”相同):

<p>
这是
一句话。
</p>

我在Chrome、Safari和IE上得到了以下结果...

这是 一句话。

...但我想要的是没有额外空格的以下内容:

这是一句话。

我不知道为什么在当前行的最后一个字符和下一行的第一个字符都是中文字符时,浏览器为什么不忽略换行符(我认为这样更合理)。或者说他们提供了这种机制,但需要特殊处理?

顺便说一句,在Vim中,使用“J”来连接行时,如果两行的最后一个字符和第一个字符都是中文字符,则不会添加空格。但对于英文,则会添加空格。因此,我猜Vim对此进行了特殊处理。

更新:

虽然我认为这是浏览器的问题,但我必须接受这个现实。因此,目前我会预处理我的Markdown文本以连接中文行,然后再生成HTML。以下是我在Ruby中执行此操作的方式,完整代码还包括处理中文标点符号,可在 gist 上找到。

#encoding: UTF-8

# Requires ruby 1.9.x, and assume using UTF-8 encoding

class String
  # The regular expression trick to match CJK characters comes from
  # https://dev59.com/P2445IYBdhLWcg3w0ddD#4681577
  def join_chinese
    gsub(/(\p{Han})\n(\p{Han})/m, '\1\2')
  end
end

你可以编写一个脚本,从目录中的所有HTML文件中生成没有换行符的新文件。每当您要发布文件到Web时,请运行该脚本,并发布生成的文件。 - Gravity
我知道这可以很容易地通过脚本解决。但我认为浏览器应该处理这个问题,以使大多数人的生活更加轻松。正如您所看到的,Vim已经实现了这一点,在LaTeX中我们也可以禁止换行符转换为空格。 - cyfdecyf
4个回答

12
浏览器将换行视为空格,因为规范是这样规定的,自从HTML 2.0以来就是这样。实际上,HTML 2.0比后来的规范要温和得多;它说:“在除了预格式文本之外的所有情况下,HTML用户代理应该将任何变化中的行尾视为单词空格。”(换行符的常规表示),而较新的规范则更加强调(将其描述为HTML中发生的事情)。
背景是HTML和Web是针对主要的西欧语言开发的;这反映在原始规范和早期实现的许多特性中。只有缓慢地进行了国际化。
解析规则不太可能会改变。更有可能的是对语言或字符属性呈现的敏感性。这意味着换行仍然被视为空格(DOM字符串将包含Ascii空格字符),但像这样的字符串“这是一句话。”将被呈现,就好像没有空格一样。这似乎是HTML 4.01规范所指的(空白字符)。这段文字有点混乱,但我认为它试图说明行为将取决于内容语言,可以由浏览器推断或在标记中声明。

但是浏览器目前还没有这样的功能。声明内容语言,例如<html lang=zh>是一个好的原则,但实际上影响很小——在渲染方面,它可能会影响浏览器选择默认字体(但有多少作者让浏览器使用他们的默认字体?)。如果空格字符恰巧在浏览器为指定语言的默认字体中更宽,甚至可能导致增加间距。

根据CSS3 Text草案,您可以使用text-spacing属性。值none“关闭所有文本间距特性。所有全角字符都将设置为全角字形。”不幸的是,目前没有任何浏览器支持这个属性。


5

有一种解决这个问题的方法(经典解决方案)。为了限制(当前)浏览器将换行符解释为空格,您需要将字体大小设置为0。

对于子元素,您需要再次将字体大小设置为其初始值。因此,对于您的代码,一个示例可能是:

<p class="nowhitespace">
  <span>这是</span>
  <span>一句话。</span>
</p>

CSS中可能包含以下代码:
.nowhitespace { font-size: 0; }
.nowhitespace > span { font-size: 16px; }

1
谢谢,这真的很有效。但是这个技巧的一个问题是我必须用span标签包裹每一行包含中文文本的内容。为了让事情变得更复杂,如果一行的开头/结尾是英文单词,那么我就不应该关闭/打开span标签。 - cyfdecyf
是的,我知道 - 所以总体而言,您仍然需要包括一个修改行的函数,就像您上面写的那个一样。我为设计目的想出了这个解决方法,其中空格破坏了布局。 - Florian Rappl

3

目前我所知的实现该效果最简短的方法是在开标签后断行。但您不想在源代码中插入额外的标签。如果有一些什么标签什么都不做,那就太好了。事实上,确实存在这样的标签,即注释标签。

<p>
这是<!--
-->一句话。
</p>

这将给你以下结果。
这是一句话。

灵感来源: 没有额外的空间


-3

您可以使用<pre>标签来格式化文本,并且您也可以更改其样式。预格式化文本将按照换行符的字面意义进行渲染并显示为新行。

如果您不想使用<pre>

换行符也被视为空格。当您插入一个换行符时,它将把下一行视为前一行的一部分,并简单地用一个空格替换该换行符。

您必须在HTML中明确声明换行符,只需使用<br>即可。


我的问题是,在处理中文字符时,换行符不应被视为空格。但浏览器对中文字符没有特殊处理。 - cyfdecyf
好的,它并没有。据我所知,目前没有HTML标签或CSS元素来解决这个问题,我怀疑当前浏览器中是否存在这样的功能。 :( - user613857

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接