CSS 或 JS 中是否有一个选项可以强制行尾的单字符单词移动到下一个?

Is there an option in CSS or JS to force single-character words at the end of a line to move to the next one?

在创建响应式网页设计时,经常会出现单字母单词保留为段落行中最后一个单词的情况:

This is a
paragraph

我想移动这样一个单字母的单词如下:

This is
a paragraph

CSS中是否有内置的属性可以实现这种效果? 如果有none,在JavaScript中怎么办?

如果您想始终将 "a" 和 "paragraph" 放在一起,请在它们之间添加一个 "non-breaking-space":

<div style="width:100px;border:1px solid #333;padding:5px">
<p>
This is a&nbsp;paragraph
</p>
</div>

为了让单字母单词(如'a'或'I')与后面的单词在同一行,您可以将它们之间的space字符替换为不间断 space Unicode 字符 \u00A0.

这可以通过一点点 JavaScript 实现自动化。例如,此代码将 [space][letter][space] 替换为 [space][letter][non-breaking space]:

const modifySingleChars = str => str.replace(/ ([a-zA-Z]) /g,
    ' ' + '\u00A0');

要更改页面上的所有实例,首先收集正文中的所有文本节点(跳过 <script> 标签内的任何内容。

然后简单地遍历文本节点,进行适当的替换。

一个工作示例:

// form array of all text nodes in parentNode
function allTextNodes(parentNode) {
  let arr = [];
  if (!parentNode) {
    return arr;
  }

  let nodes = parentNode.childNodes;
  nodes.forEach(node => {
    if (node.nodeName === 'SCRIPT') {
      return;
    }
    if (node.nodeType === Node.TEXT_NODE) {
      arr.push(node);
    } else {
      arr = arr.concat(allTextNodes(node));
    }
  });
  return arr;
}

// convert [space][letter][space] to [space][letter][non-breaking space];
const modifySingleCharWords = str => str.replace(/ ([a-zA-Z]) /g,
  ' ' + '\u00A0');

function fixAllSingleCharWordsInBody() {
  let tNodes = allTextNodes(document.body);
  tNodes.forEach(tNode => {
    tNode.nodeValue = modifySingleCharWords(tNode.nodeValue);
  });
}
<body>
  <div id="wrapper" style="width:20rem">
    <h4>Prevent single character words at end of line</h4>
    <button type="button" onclick="fixAllSingleCharWordsInBody();">Fix All Words
  </button>
    <p>Lorem &nbsp;ipsum dolor i amet, consectetur a dipiscing elit, sed o eiusmod tempor incididunt u labore et dolore magna aliqua. <span>Nisl purus i mollis</span> nunc.
    </p>
    <p>In vitae turpis massa e elementum tempusus a sed. Eget mi proin e libero enim i faucibus. Quis lectus nulla a volutpat diam ut.
    </p>
    <p>Pharetra e ultrices neque ornare. Donec a tristique risus e feugiat in fermentum. Consectetur adipiscing e u aliquam purus sit amet.
    </p>
    <p>Vitae congue mauris rhoncus aenean e elit scelerisque mauris pellentesque. Mauris u eros i cursus turpis a tincidunt dui.
    </p>
    <p>At volutpat diam u venenatis tellus. Tellus integer feugiat scelerisque varius morbi i nunc faucibus at.</p>
    <script>
      const b = 'Do not modify anything inside a script tag';
    </script>
  </div>
</body>

从几年前我们有了 ES6 所以...

[...document.body.querySelectorAll('*')]
        .map(n => n.firstChild)
        .filter(n => (n != null && n.nodeType === Node.TEXT_NODE && !['SCRIPT', 'STYLE'].includes(n.parentNode.nodeName)))
        .forEach(el => {
            el.nodeValue = el.nodeValue.replace(/ ([a-zA-Z]) /g, ` \u00A0`)
        });

document.body可以换成任意节点,这里为了简单起见[​​=12=]