TL;DR
这是一个常见且理想的特性,在 CSS 的历史上已被多次讨论,并且正在开发一个规范以使其成为可能。不幸的是,实现很少而且相距甚远,一些实现者不愿意为此工作。对于任何不平凡的布局来说,用 JavaScript 做这件事都是一个复杂的问题。这样的解决方案对于您的目的来说可能不够快,您将快速接近您期望从 PDF 到 HTML 转换器获得的那种标记。
背景
这里有两个问题:不规则的文本流和从页面的任意区域排除文本和其他内联元素。
这不是第一次讨论 CSS 的任一功能。特别是,在 1996 年,围绕不规则浮动形状的流动文本是 mentioned in a CSS level 1 working draft,而 Eric Meyer 的 ragged float demo 至少可以追溯到 2002 年。这是一个早就应该实现的功能!
2007 年 6 月,James Elmore 建议将 position 值添加到 float 属性,使元素可以在页面上任意定位,同时排除其他元素从下方流动。
SVG 1.2 最初为flowed text regions 指定了一个模型,并详细介绍了如何实现它。不幸的是,latest version of the spec(仍在开发中)通过指出以前的工作将被“SVG 1.2 Tiny textArea 功能的超集”取代,从而将其从水中吹了出来。
当前状态(2012 年 8 月修订)
最近,我们有 CSS Exclusions specification、proposal from Adobe 以及您在该视频中看到的内容。截至 2012 年 8 月,这些已在 IE 10 RTM 中实现,并在 WebKit 中慢慢推出,但为其他供应商工作的开发人员已就该提案表达了mixed feelings。*
Adobe 维护一个handy support matrix 以方便参考。
Hack咳嗽 “Polyfilling”?
使用 JavaScript 很难实现类似的效果,更难以有效地做到这一点。我可以想到两种非常幼稚的方法来为区域中的绝对定位元素腾出空间:
- 使用策略性插入的内联
spans 为元素“阻挡”空间;或
- 用
span 元素包围每个单词,并单独设置每个单词的样式,以便使用填充为排除的元素腾出空间。
我已经破解了a very broken demo 第二种方法的工作原理。这是可怕的,有缺陷的,而且很容易被打破。实际上,在回答这个问题后,我花了几个星期的时间为 Exclusions 规范编写 polyfill,但因为存在太多错误和性能问题而放弃了。
使用任何一种方法都会遇到无数问题:列、文本对齐、错误的子元素(尤其是浮动或定位元素!)、各种边缘条件、更改 HTML 时的可怕事情、断字——天哪,我不知道甚至想考虑连字符——当然,在考虑到这些事情之后,还有潜在的巨大性能问题。
性能问题可以有所改善;例如,我使用elementFromPoint 尝试直接获取包含第一个重叠单词的span,并且某些浏览器甚至支持caretPositionFromPoint,这也可能会有所帮助。我认为通过大量工作,您可以制作出非常适合静态内容的东西;但是让它足够快以至于你可以用鼠标拖动它?我的演示页面内容很少,并且没有解决您在真实网页上必须处理的任何令人费解的复杂问题。即使您可以解决所有这些问题,但要让它足够快以顺利拖动将是非常具有挑战性的。
* 我强烈希望供应商实施 CSS 排除。从 CSS 的早期开始,人们就一直在寻求这些功能,这是一个常见且合法的视觉设计目标,无论是在屏幕上还是在印刷品中。