简介
Web 是一个非常强大的文本平台,而 Adobe 在这一领域拥有丰富的经验和专业知识。因此,当 Adobe 寻找推动网络发展的方法时,进一步提升网络的文本功能似乎是一个显而易见的切入点。 网络通常假定文本采用单列垂直方向。虽然可以使文本环绕图形,甚至可以使用 CSS 将文本设置为多列格式,但仍然很难在网页上实现真正的杂志式布局。借助 CSS 区域和 CSS 排除,Adobe 正在努力将桌面出版的强大功能引入现代浏览器。例如,在下面的屏幕截图中,CSS 排除项用于使文本沿山体轮廓流动:
以下屏幕截图中的文档还使用了 CSS 排除项,使文本能够环绕图片中的形状,并使用 CSS 区域将文本格式化为多列并环绕醒目引文:
CSS 地区
在详细介绍 CSS 区域之前,我想先介绍一下如何在 Google Chrome 中启用区域。启用 CSS 区域后,您可以尝试本文中引用的一些示例,并创建自己的示例。
在 Google Chrome 中启用 CSS 区域
从 Chrome 20(确切地说是 20.0.1132.57 版)开始,CSS 区域通过 chrome://flags 界面启用。如需启用 CSS 区域,请按以下步骤操作:
- 在 Chrome 中打开新的标签页或窗口。
- 在地址栏中输入
chrome://flags。 - 使用在页面中查找(Ctrl/Command + F)功能,搜索“实验性 Web 平台功能”部分。
- 点击启用链接。
- 点击底部的立即重新启动按钮。
如需详细了解 Chrome 的 flag,请参阅我的博文关于 Chrome flag 的一切。
重新启动浏览器后,您就可以开始试用 CSS 区域了。
CSS 地区概览
CSS 区域允许语义标记的文本块自动流入“框”(当前元素)。下图展示了文本(流)和框(文本流入的区域)的分离:
我们来看一个实际的 CSS 区域用例。除了在 Adobe 担任开发者之外,我还是一位科幻作家。我经常在网上发布自己的作品,并采用知识共享许可。为了让作品能在尽可能多的设备和浏览器上正常显示,我经常使用一种非常简单的格式,如下所示:
通过使用 CSS 区域,我能够打造出更具视觉吸引力且功能更强大的体验,因为这样更易于浏览,阅读起来也更舒适:
为了进行演示,我在此原型中添加了显示 CSS 区域的功能。以下屏幕截图显示了这些区域的排列方式,它们看起来像是围绕着中心图形和引言的列:
您可以点击此处,体验此原型(以及查看源代码)。使用箭头键进行导航,然后按 Esc 键显示区域。您也可以点击此处查看早期原型。
创建命名流
让文本块在区域之间流动的 CSS 非常简单。以下代码段将名为“article”的命名流分配给 ID 为“content”的 div,并将同一“article”命名流分配给类为“region”的任何元素。结果是,“content”元素中包含的文本将自动流经具有“region”类的任何元素。
<!DOCTYPE html>
<html>
<head>
<style>
#content {
{ % mixin flow-into: article; % }
}
.region {
{ % mixin flow-from: article; % }
box-sizing: border-box;
position: absolute;
width: 200px;
height: 200px;
padding: 10px;
}
#box-a {
border: 1px solid red;
top: 10px;
left: 10px;
}
#box-b {
border: 1px solid green;
top: 210px;
left: 210px;
}
#box-c {
border: 1px solid blue;
top: 410px;
left: 410px;
}
</style>
</head>
<body>
<div id="box-a" class="region"></div>
<div id="box-b" class="region"></div>
<div id="box-c" class="region"></div>
<div id="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eleifend dapibus felis, a consectetur nisl aliquam at. Aliquam quam augue, molestie a scelerisque nec, accumsan non metus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin cursus euismod nisi, a egestas sem rhoncus eget. Mauris non tortor arcu. Pellentesque in odio at leo volutpat consequat....
</div>
</body>
</html>
结果如下所示:
请注意,“content”div 中的文本不包含任何有关其呈现方式的信息。换句话说,即使在流经各个区域时,它也可以保持完全语义完整。此外,由于区域只是元素,因此它们可以使用 CSS 进行定位和调整大小,就像任何其他元素一样,因此完全符合自适应设计原则。将元素指定为命名流的一部分,只是意味着指定的文本会自动流经这些元素。
CSS 对象模型
CSS 对象模型 (CSSOM) 定义了用于处理 CSS 的 JavaScript API。下面列出了与 CSS 区域相关的新 API:
document.webkitGetNamedFlows():一个函数,用于返回文档中可用的命名流集合。document.webkitGetNamedFlows().namedItem("article"):一个函数,用于返回对特定命名 flow 的引用。该实参对应于指定为flow-into和from-fromCSS 属性值的名称。如需获取对上述代码段中指定的命名流的引用,您需要传入字符串“article”。WebKitNamedFlow:一个具有以下属性和函数的命名 floe 的对象表示:firstEmptyRegionIndex:一个整数值,指向与命名流关联的第一个空区域的索引。请参阅下文中的getRegions(),了解如何获取区域集合。name:一个字符串值,表示流程的名称。overset:一个布尔值属性,其具体值可为:false(当指定流的内容适合关联的区域时)true:当内容无法容纳,需要更多区域来包含所有内容时。
getContent():一个函数,用于返回一个集合,其中包含对流入指定流的节点的引用。getRegions():一个函数,用于返回一个集合,其中包含对包含指定流内容的区域的引用。getRegionsByContentNode(node):一个函数,用于返回对包含指定节点的区域的引用。这对于查找包含命名锚点等内容的区域特别有用。
webkitregionoversetchange事件。每当关联内容的布局因任何原因(添加或移除内容、字体大小发生变化、区域形状发生变化等)发生变化且导致区域的webkitRegionOverset属性发生变化时,系统就会在WebkitNamedFlow上触发此事件。此事件对于监听粗略布局更改非常有用。这表明发生了重要事件,布局可能需要注意,例如:需要更多区域、某些区域可能为空等。webkitregionfragmentchange事件。在进行此编辑时未实现。每当关联内容的布局因任何原因发生变化时,都会在WebkitNamedFlow上触发此事件,这与webkitregionoversetchange类似,但无论webkitRegionOverset属性是否发生任何变化,都会触发此事件。此事件对于监听不一定会影响命名流的整个布局的精细布局更改非常有用,例如:内容从一个区域移至另一个区域,但整体内容仍适合所有区域。Element.webkitRegionOverset:元素在被分配flow-fromCSS 属性后会变为区域。这些元素具有webkitRegionOverset属性,如果它们是命名流的一部分,则该属性会指示流中的内容是否溢出区域。webkitRegionOverset 的可能值包括:- “overflow”(如果内容超出区域可容纳的范围)
- “fit”(如果内容在区域结束之前停止)
- “empty”(如果内容尚未到达该区域)
CSSOM 的一个主要用途是监听 webkitregionoversetchange 事件,并动态添加或移除区域,以适应不同数量的文本。例如,如果要设置格式的文本量不可预测(可能是用户生成的)、浏览器窗口大小发生变化或字体大小发生变化,则可能需要添加或移除区域,以适应文本流的变化。此外,如果您想将内容整理到页面中,则需要一种机制来动态修改 DOM 以及区域。
以下 JavaScript 代码段演示了如何使用 CSSOM 根据需要动态添加区域。请注意,为简单起见,它不处理移除区域或定义区域的大小和位置;它仅用于演示目的。
var flow = document.webkitGetNamedFlows().namedItem("article")
flow.addEventListener("webkitregionoversetchange", onLayoutUpdate);
function onLayoutUpdate(event) {
var flow = event.target;
// The content does not fit
if (flow.overset === true) {
addRegion();
} else {
regionLayoutComplete();
}
}
function addRegion() {
var region = document.createElement("div");
region.style = "flow-from: article";
document.body.appendChild(region);
}
function regionLayoutComplete() {
// Finish up your layout.
}
如需查看更多演示,请访问 CSS 区域示例页面。
CSS 页面模板
利用 CSSOM 可能是实现分页和自适应布局等功能的最强大、最灵活的方式,但 Adobe 长期从事文本和桌面排版工具的开发,深知设计师和开发者也希望有一种更简单的方式来获得相对通用的分页功能。因此,我们正在制定一项名为“CSS 页面模板”的提案,该提案允许完全以声明方式定义分页行为。
我们来看一个 CSS 页面模板的常见应用场景。以下代码段展示了如何使用 CSS 创建两个命名的流:“article-flow”和“timeline-flow”。此外,它还定义了第三个选择器“combined-articles”,其中将包含这两个信息流。只需在“combined-articles”选择器中添加 overflow-style 属性,即可指示内容应沿 x 轴(即水平方向)自动分页:
<style>
#article {
{ % mixin flow-into: article-flow; % }
}
#timeline {
{ % mixin flow-into: timeline-flow; % }
}
#combined-articles {
overflow-style: paged-x;
}
</style>
现在,我们已经定义了流并指定了所需的溢出行为,接下来可以创建页面模板本身了:
@template {
@slot left {
width: 35%;
float: left;
{ % mixin flow-from: article-flow; % }
}
@slot time {
width: 25%;
float: left;
{ % mixin flow-from: timeline-flow; % }
}
@slot right {
width: 35%;
float: left;
{ % mixin flow-from: article-flow; % }
}
}
页面模板使用新的“at”语法进行定义。在上面的代码段中,我们定义了三个槽,每个槽对应一列。“article-flow”中的文本将流入左侧和右侧的列,而“timeline-flow”中的文本将填充中间的列。结果可能如下所示:
请注意,文章文本(即左右两栏中的文本)是英文,而中间的时间轴是德文。此外,文档无需任何 JavaScript 代码即可水平分页。所有操作都是在 CSS 中以声明方式完成的。
CSS 页面模板仍处于提案阶段,但我们有一个原型,它使用 JavaScript“shim”(也称为 polyfill),以便您现在可以试用它们。
如需详细了解 CSS 区域,请参阅 html.adobe.com 上的 CSS 区域页面。
CSS 排除对象
为了实现真正的杂志式布局,仅能让文本在区域之间流动是不够的。高质量且视觉效果出色的桌面出版物有一个关键要素,那就是能够让文本围绕不规则图形和形状流动,或在不规则图形和形状内部流动。CSS Exclusions 将这种级别的制作质量带到了 Web。
以下屏幕截图来自 CSS 排除原型,显示了文本围绕与大型岩层轮廓匹配的路径动态流动:
下一个屏幕截图展示了相反的情况:文本在不规则形状的多边形内流动:
要实现文本围绕任意形状或在任意形状内流动,第一步是开发和优化所需的算法。Adobe 目前正在开发相关实现,这些实现将直接贡献给 WebKit。这些算法经过优化后,将成为构建其余 CSS 排除项的基础。
如需详细了解 CSS 排除,请参阅 html.adobe.com 上的 CSS 排除页面;如需详细了解 Adobe 在 CSS 排除底层技术方面的工作,请参阅 Hans Muller 的博文水平框:CSS 排除的多边形交集。
CSS 区域和 CSS 排除项的状态 (2012)
我第一次公开谈论 CSS 区域和 CSS 排除是在 2011 年 Google I/O 大会的 Adobe 开发者 Pod 上。当时,我是在我们自己的自定义原型浏览器中进行演示。反响非常热烈,但当旁观者发现我展示的功能在任何主流浏览器中都还无法使用时,他们明显感到失望。
今年 (2012) 我再次参加了 Google I/O 大会,这次是作为演示者,与我的同事 Vincent Hardy 和 Google 的 Alex Danilo 一起(您可以在此处观看演讲)。仅仅一年后,WebKit 中就已实现了大约 80% 的 CSS 区域规范,并且该规范已在最新版本的 Google Chrome 中提供(请注意,CSS 区域目前必须通过 chrome://flags 启用)。Chrome for Android 甚至已经初步支持 CSS 区域:
此外,CSS 区域和 CSS 排除项均已在 Internet Explorer 10 预览版中实现,并且目前已列入 Mozilla 的 2012 年 Firefox 路线图。Safari 的下一个主要版本应该支持 CSS 区域规范的大部分内容,后续更新应该包含其余内容。
下面是自 2011 年 4 月我们首次向 W3C 提出建议以来,我们在 CSS 区域和 CSS 排除方面取得的进展的详细时间表:
总结
Adobe 在文本、字体和桌面排版方面拥有丰富的经验,其 InDesign 等工具广为人知。虽然网络已经是一个非常强大的文本平台,但我们希望利用我们的知识和经验,进一步提升文本呈现效果。CSS 区域和 CSS 排除项可让内容保持语义结构,同时实现真正的杂志式布局,最终打造出更具表现力的网页。