为什么Text.splitText()会影响布局? [英] Why does Text.splitText() affect layout?

查看:154
本文介绍了为什么Text.splitText()会影响布局?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



 < p> laborum beatae est nihil,non hic ab,deserunt repellat quas。 Est molestiae ipsum minus nesciunt tempore voluptate laboriosam< / p> 

DOM明智的结构是:

  HTMLParagraphElement 
Text [laborum beatae est nihil ...]

现在我们将它拆分(使用 Text.splitText())两次,以分隔deserunt repellat quas。Est片段。结构变成:

  HTMLParagraphElement 
文本[请输入您的邮箱地址]
Text [deserunt排斥准备。 Est]
Text [molestiae ipsum minus nesciunt ...]

虽然此操作会影响DOM ,它从来没有改变它的元素级别(文本!==元素),所以我预计没有视觉变化。 然而 splitText() / code>也会影响布局,在所有测试过的浏览器(Chrome 60,Firefox 55,Edge 14 - 都在Windows 10 OS上)触发重新布局和重新绘制。当我们调用 ParagraphElement.normalize()时,会发生同样的情况,将Text节点的数量减少为1;再次触发重新布局和重绘。



这有一个令人讨厌的副作用,可以在



切换 font-kerning none 也没有帮助。



更新:问题已在Blink tracker上注册 解决方案

关于重新布局/ repaint,可以预期,因为文本节点也是DOM节点...不是DOM元素,但浏览器必须重新考虑布局,即使您希望它仍然保留同样的,他们可能不得不移动。也许是因为字距问题。



现在,为什么拆分文本会导致一些移动?我期望的是因为浏览器分别绘制文本部分。两个相邻的字母通常有一个空格,可以根据字母减小字体,例如以WA为例,W的结尾高于A的开头,即 kerning (Thx Ismael Miguel)。当文本节点分开绘制时,每个人都必须在下一次开始之前完成,因此它可以在这些字母之间创建更大的空间,因为它可以防止任何字距变化。



对不起,字母之间的空格确实有一个名字,但我忘了...



。 body {font-size:40px;} div> span {border:1px solid black;}

< div>< span> AW< / span> - 在同一个DOM节点中< / div>< div>< span>< span> A< / span>< span> W< / span>< / span> - 在两个不同的节点< / div>< div>< span>< span class =one> A< / span>< span class =two> W< / span><跨度> - 在两个不同的节点中,彩色< / div>

如何防止这种行为,最简单的解决方案是使用等宽字体。这可能并不总是美学上可行的。 Kerning是嵌入在字体文件中的信息,从这些信息中剥离字体似乎是防止闪烁的最可靠的方法。此外,设置CSS属性 font-kerning 时可以提供帮助to none



另一种方法是在文本后面或前面添加绝对元素以模仿事实将部分文本包含到元素中,但这完全取决于最终目标。



再看一下 CSS-Tricks有一篇关于文本渲染的好文章,它也可以帮助字体翻译。



编辑:当写这个答案时,我忽略了文本是合理的事实。虽然我的回答解释了为什么在将文本节点切割为多个文本节点时可能发生某种闪烁,但这并不意味着浏览器在计算对齐空格时出现问题。


Let's say we have a paragraph in our page, with a single block of text.

<p>laborum beatae est nihil, non hic ab, deserunt repellat quas. Est molestiae ipsum minus nesciunt tempore voluptate laboriosam</p>

DOM-wise, the structure is:

HTMLParagraphElement
  Text [laborum beatae est nihil...]

Now we split it (with Text.splitText()) twice, to separate "deserunt repellat quas. Est" fragment. The structure becomes:

HTMLParagraphElement
  Text [laborum beatae est nihil...]
  Text [deserunt repellat quas. Est]
  Text [ molestiae ipsum minus nesciunt...]

While this operation affects DOM, it never changes it on the Element level (Text !== Element), so I expected no visual changes.

Yet splitText() affects layout as well, triggering both relayout and repaint in all the tested browsers (Chrome 60, Firefox 55, Edge 14 - all on Windows 10 OS). The same happens when we call ParagraphElement.normalize(), reducing the number of Text nodes back to 1; again both relayout and repaint are triggered.

There is a nasty side-effect of this, which can be seen in this demo. If you check the words near 'quas. Est', you see they actually change positions!

It's clearly visible in Firefox, and is far more subtle (yet also distinguishable) in Chrome. To my amusement, no such "word dance" occurred in Edge.

The reason why this is important is shown in this demo of (kind of) shimmed selection engine. This particular version won't work in Firefox (no support for caretRangeFromPoint yet - argh!), but even with "point2dom" rewired onto caretPositionFromPoint the highlighted text is repositioned there - as much in Chrome, or even worse. Again, it seems to work well in Edge.

So, in fact, I'm mostly interested in both understanding the reasons and finding the workarounds.

Here's the animated gif showing how the first demo plays in Chrome (I just trigger a click in interval)

The tremble IS subtle here, but still can be observed on all the words. I'm especially puzzled by why i in molestiae shakes, as surrounding letters seems to stay where they are.

And it gets worse (far worse) with less common fonts and more text, like in selection demo.

Switching to font-family:monospace didn't solve this, but made it seemingly worse:

Switching font-kerning to none didn't help either.

UPDATE: The issue is registered on the Blink tracker.

解决方案

About the relayout/repaint it is to be expected, as the text nodes are DOM nodes too... Not DOM elements, but the browsers do have to reconsider the layout even if you would expect it to stay the same, they may have to move. Maybe because of kerning.

Now, why splitting text causes some moving? What I'd expect is because the browsers draw the text parts separately. Two neighbouring letters usually have a space that may be reduced by the font depending on the letters, take "WA" for example, the end of the W is above the start of the A, that is called kerning (Thx Ismael Miguel). When text nodes are drawn separately, each one has to finish before the next starts, so it may create a bigger space between those letters as it prevents any kerning.

Sorry, the space between letters does have a name but I forgot...

.one {
  background-color: #FF9999;
}

.two {
  background-color: #99FF99;
}

body {
  font-size: 40px;
}

div>span {
  border: 1px solid black;
}

<div><span>AW</span> - in the same DOM node.</div>
<div><span><span>A</span><span>W</span></span> - in two different nodes</div>
<div><span><span class="one">A</span><span class="two">W</span></span> - in two different nodes, colored</div>

As to how to prevent this behaviour, the most easy solution is to use a monospace font. This might not always be aesthetically feasible. Kerning is an information embedded in the font files, stripping a font from this information seems to be the most robust way to prevent flicker from it. ALso, the CSS property font-kerning could help when set to none.

Another way is to add absolute elements behind or in front of the text to mimic the fact of surrounding a part of text into an element, but that is all depending on the end goal.

Looking a bit further CSS-Tricks have a nice article about text-rendering and it could also help on font-kerning.

EDIT: When writing this answer, I had overlooked the fact that the text was justified. While my answer explains why a certain flicker could happen when cutting a text node into multiple ones, it by no mean explains why the browsers seem to have problems calculating the justified spaces.

这篇关于为什么Text.splitText()会影响布局?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆