【问题标题】:Changing text alignment for each line in multi-line text更改多行文本中每一行的文本对齐方式
【发布时间】:2015-09-04 15:23:13
【问题描述】:

在旧报纸中,文章标题如果超过三行,通常会像这样(picture)

|RACKET KINGPINS       |
|    ARE ROUNDED UP    |
|       IN BOMB KILLING|

即第一行的对齐方式是左对齐,第二居中,第三右对齐。同样,对于跨越两行的标题,第一个将左对齐,第二个右对齐。对于单行,标题将居中。

我一直在尝试为我正在研究的主题模仿这个,但问题是,我如何将线条彼此分开?每个帖子的标题当然不包含任何实际的硬编码换行符,而是根据宽度限制自动换行,所以我不能只寻找换行符来分割 DOM 的innerHTML

那么你会怎么做呢?

(如果不清楚,我欢迎 JavaScript 解决方案)

【问题讨论】:

  • “在旧报纸上” ...他们事先知道换行符在哪里。实现这一点并不难。但是,如果您希望这种情况动态发生,则会出现一些问题 - 其中第一个问题显然是,对于正常流动的文本,换行符甚至不会发生,就像您在小示例中所使用的那样,因为第一行还有足够的空间让“ARE”也出现在该行……
  • [contd.] ...所以你要么必须事先插入换行符,要么在这些“组”单词之间有不间断的空格,否则你不会得到 首先以特定方式在三行中分配单词。您当然可以尝试使用 JavaScript 创建类似的内容——例如,尝试将文本拆分为长度大致相等的三部分,仅基于纯字符数,或者考虑字符对应的更复杂的解决方案。字宽也是如此。
  • 好的,如果我要实现这样的东西,我会先在空白处分割文本,然后放置每个“单词”(加上可选的尾随标点符号,如逗号或句点)到它自己的span 元素中(通过JS,或者已经在服务器端)。然后(在浏览器中)循环遍历所有这些元素,并将当前元素的 .offsetTop 值与前一个元素的值进行比较——如果它们不同,则当前元素显然在下一行。收集了哪些单词在一个“行”上的信息后,很容易将它们放入其他容器元素中 […]
  • […],每行一个容器,并对其应用不同的文本对齐值。甚至可以更进一步,使用.offsetWidth 测量每个单词的实际宽度,并尝试应用一些高级数学来查看是否可以找到更理想的单词在行上的分布(这样你就不会' t 结束让我们说两行“长”行,第三行只有一个词)。此外,如果要超过三行,还可以对中间的行应用不同的 padding-left 值,这样居中的文本就不会使它们看起来都相似……
  • 谢谢,可以这样解决!如果没有其他人这样做,可能会输入我的解决方案并将其添加为答案。

标签: javascript html css dom text-align


【解决方案1】:

您可以尝试循环遍历所有字符,在每个循环中,将当前字符选择为一个范围对象,从中可以使用范围对象的getBoundingClientRect()方法获取字符rect的bottom。这是我们检测每行结束字符的方式。以下是检测结束字符的标志:

  1. 如果我们使用普通换行,所有行都应该在某个空格字符处中断。特殊之处在于,在这种情况下,结尾空格字符将具有 rect(从 getBoundingClientRect() 获取),topbottom 都是 0
  2. 如果我们使用像word-break:break-all 这样的换行,结束字符可能是其他字符(不是空格字符)。在这种情况下,我们将检测到结束字符之后的下一个字符,下一个字符的 bottom 与结束字符的 bottom 不同。

所以它确实相当复杂。事实上,起初我以为我们只有一个案例(第二个案例),但如果我们忽略第一个案例,我们会得到意想不到的结果。所以首先我们需要检查第一种情况,然后是第二种情况。现在检测每行中的结束字符有助于我们将整个文本分成单独的行。然后我们可以将每一行包装在一个div 元素中,并设置适当的样式(以对齐每一行中的文本)。

这是演示的代码:

HTML

<h3>Original column</h3>
<div class='o-column'>racket kingpins are rounded up in bomb killing</div>
<h3>Column after adjusted</h3>
<div class='column'>racket kingpins are rounded up in bomb killing</div>

CSS

.column, .o-column {
  width:300px;  
  border:1px solid black;
  margin-bottom:5px;
  text-transform:uppercase;
  padding:5px;    
  font-size:30px;
  font-family:'Arial';
  word-wrap:break-word;
}

JS

console.clear();
var column = document.querySelector('.column');
var ends = [];
var range = document.createRange();
range.selectNodeContents(column);
var lines = [];
var lastBottom = null;
//if the innerHTML has some \n character, there will be some unexpected
//behavior, all the \n characters should be removed first.
column.innerHTML = column.innerHTML.replace(/\n/g,'');
var len = column.innerHTML.length;
for(var i = 0; i < len; i++){    
  //set range for current character
  range.setStart(column.childNodes[0],i);
  range.setEnd(column.childNodes[0],i+1);
  var rect = range.getBoundingClientRect();    
  if((rect.bottom == 0 && rect.top == 0) ||
    rect.bottom != lastBottom && lastBottom != null || i == len-1){
    var line = document.createElement('div');
    var lineStart = ends.length ? ends[ends.length - 1] + 1 : 0;
    line.innerHTML = column.innerHTML.substring(lineStart, i == len - 1 ? len : i);
    lines.push(line);
    ends.push(rect.bottom ? i - 1 : i);    
  }
  if(rect.bottom != 0) lastBottom = rect.bottom;
  else lastBottom = null;
  if(ends.length > 3) break;
}

var n = lines.length;
//we align each line only if there are less than 4 lines
if(n < 4 && n > 0){
  column.innerHTML = "";    
  for(var i = 0; i < n; i++){
    column.appendChild(lines[i]);
  }
  if(n == 1) lines[0].style.textAlign = 'center';
  else {        
    lines[0].style.textAlign = 'left';        
    lines[n-1].style.textAlign = 'right';
    if(n == 3) lines[1].style.textAlign = 'center';
  }
}

Demo.

【讨论】:

    【解决方案2】:

    没有 JavaScript,你就做不到。

    这是 HTML/CSS 的限制之一。如果您需要可以控制文本的精确位置和大小的打印功能,请使用 PDF。

    如果没有 JavaScript,您无法预测一个段落是否会跨越多行以及多行,这仅仅是因为用户:

    • 可能没有安装相同的字体,

    • 或者可能已将文本配置为在他的浏览器中显示得更大。

    您可以改为:

    1. 手动添加换行符,在大多数情况下,每行的宽度都会低于容器的宽度,

    2. 禁止换行 (white-space: nowrap;) 和:

    3. 根据需要对齐三行。

    使用 JavaScript,您可以通过 counting the actual number of lines 确定在何处放置换行符,然后逐个字符地减少文本,直到得到两行,然后是一行,这样找到准确的可以插入换行符的位置。

    我认为它已经够骇人听闻了,但是,这只是我的看法。另一方面,您可能会关心一旦加载页面后对用户配置的更改(例如仅文本缩放,就像在旧浏览器中使用的那样)可能会破坏布局。

    【讨论】:

    • 不知道,因为您的回答是正确的,因为这无法做到——至少不是以合理的方式——使用当前的 CSS,它需要额外的 JS。
    • 你实际上可以做一个缩进,做一些比简单缩进更高级的事情,你需要比我提供的例子多一点编程。
    • 我没有投票给你,所以我不能说。我确实遇到了一种计算行数的好方法,尽管我不知道是否可以这样拆分它们:link
    • @Marcus:这就是我在回答中所说的 JavaScript hack。
    • 你可以使用javascript来解决答案,所以你可以,不是hack,只是代码。
    【解决方案3】:

    您可以创建一个函数将explode 字符串转换为javascript 中的字符数组,然后根据需要操作该数组。

    您可以通过在分解字符串之前对字符串使用 pr 制作的“自动换行”功能来简化他的操作,这样标题将自动根据您的最大宽度规范预先适当地插入 \n 字符。

    然后在爆炸之后,您只需通过将它们插入数组中的\n 断点将它们包装在 div 中,并根据需要使用 css 类将它们排列起来。

    然后将implode数组变回字符串...

    【讨论】:

      猜你喜欢
      • 2018-09-03
      • 2021-09-21
      • 1970-01-01
      • 2023-03-24
      • 2016-01-22
      • 2012-05-02
      • 1970-01-01
      • 2023-03-12
      • 2015-12-29
      相关资源
      最近更新 更多