提供類似雜誌的網路版面配置,以及 CSS 區域和排除條件

Christian Cantrell
Christian Cantrell

簡介

網際網路是文字的強大平台,Adobe 在這個領域擁有豐富的經驗和專業知識。因此,當 Adobe 尋求協助網路進步的方法時,進一步提升網路的文字功能似乎是我們可以著手的明顯起點。網頁通常會假設文字為單欄、直向。雖然可以讓文字在圖片周圍流動,甚至可以使用 CSS 將文字格式化為多欄,但要讓網頁版面配置看起來像雜誌,仍然非常困難。透過 CSS 區域CSS 排除項目,Adobe 正致力於將桌面出版功能帶入新式瀏覽器。舉例來說,在下方螢幕截圖中,CSS 排除條件用於沿著山脈輪廓流動文字:

CSS 排除條件運作示例
CSS 排除條件實際運作範例

下方螢幕截圖中的文件也使用 CSS 排除條件,讓文字在圖片中的形狀周圍換行,並使用 CSS 區域將文字格式化為欄,並圍繞引文:

CSS 區域實際運作示例
CSS 區域運作示例

CSS 區域

在深入探討 CSS 區域的詳細資訊之前,我想先說明如何在 Google Chrome 中啟用區域。啟用 CSS 區域後,您可以試用本文中提到的部分範例,並自行建立範例。

在 Google Chrome 中啟用 CSS 區域

自 Chrome 20 版起 (具體來說是 20.0.1132.57 版),CSS 區域功能會透過 chrome://flags 介面啟用。如要啟用 CSS 區域,請按照下列步驟操作:

  1. 在 Chrome 中開啟新分頁或視窗。
  2. 在位置列中輸入 chrome://flags
  3. 使用「在頁面中尋找」功能 (Control/Command + F),然後搜尋「實驗性 Web 平台功能」部分。
  4. 按一下「啟用」連結。
  5. 按一下底部的「立即重新啟動」按鈕。

如要進一步瞭解 Chrome 的旗標,請參閱我的網誌文章「Chrome 旗標總覽」。

重新啟動瀏覽器後,您可以開始嘗試使用 CSS 區域。

CSS 區域總覽

CSS 區域可讓一整段語義標記文字自動流入「方塊」(目前為元素)。下圖說明文字 (流程) 和方塊 (文字流入的區域) 的分隔方式:

內容流入定義的區域
內容流入定義的區域

讓我們來看看實際的 CSS 區域用途。除了是 Adobe 的開發人員,我也是科幻小說作家。我經常在網路上以創用 CC 授權發布作品,為了讓作品在盡可能多的裝置和瀏覽器上運作,我經常使用類似以下的極簡格式:

未設定樣式的 Human 舊版專案範例
未樣式化的舊版專案範例

使用 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-intofrom-from CSS 屬性值的名稱。如要取得對上方程式碼片段中指定名稱流量的參照,請傳入字串「article」。
  • WebKitNamedFlow:命名 floe 的物件表示法,具有下列屬性和函式:
    • firstEmptyRegionIndex:整數值,指向與命名資料流相關聯的第一個空白區域的索引。請參閱下方的 getRegions(),瞭解如何取得區域集合。
    • name:包含工作流程名稱的字串值。
    • overset:布林值屬性,如下所示:
      • false 當命名流程的內容可放入相關區域時
      • true 當內容不符合要求,且需要更多區域才能容納所有內容時。
    • getContent():這個函式會傳回集合,其中包含流入命名資料流的節點參照。
    • getRegions():這個函式會傳回集合,其中包含參照區域的參照,這些區域會保留命名流程的內容。
    • getRegionsByContentNode(node):會傳回包含指定節點的區域參照的函式。這項功能特別適合用來查找含有命名錨點等內容的區域。
  • webkitregionoversetchange 事件。只要相關聯內容的版面配置因任何原因而變更 (例如新增或移除內容、字型大小變更、區域形狀變更等),就會在 WebkitNamedFlow 上觸發此事件,導致區域的 webkitRegionOverset 屬性變更。這個事件可用於監聽粗略版版面配置變更。這表示發生了重要事件,版面配置可能需要調整,例如:需要更多區域、部分區域可能為空白等。
  • webkitregionfragmentchange 事件。在本次編輯時未實作。每當相關聯內容的版面配置因任何原因而變更時,就會在 WebkitNamedFlow 上觸發此事件,類似於 webkitregionoversetchange,但不受 webkitRegionOverset 屬性變更的影響。這個事件可用於監聽精細的版面配置變更,這些變更不一定會影響命名流程的整個版面配置,例如:內容從一個區域移至另一個區域,但整體內容仍可放入所有區域。
  • Element.webkitRegionOverset:元素在指派 flow-from CSS 屬性後,就會成為區域。這些元素具有 webkitRegionOverset 屬性,如果屬性是已命名流程的一部分,則會指出流程中的內容是否溢出區域。可能的 webkitRegionOverset 值如下:
    • 如果內容多於區域可容納的內容,則會「溢位」
    • 如果內容在區域結束前停止,則為「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 Regions 範例頁面

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 區域的一般資訊,請參閱 CSS 區域頁面 (位於 html.adobe.com)。

CSS 排除條件

為了打造真正的雜誌式版面配置,您必須能夠在各區域中流動文字。要製作高品質且視覺效果出色的排版內容,關鍵在於讓文字能夠在不規則圖形和形狀的周圍或內部流動。CSS 排除條件可為網站帶來這種製作水準。

下方螢幕截圖來自 CSS 排除條件原型設計,顯示文字會動態地流動在與大型岩層輪廓相符的路徑上:

CSS 排除條件運作示例
CSS 排除條件實際運作範例

下圖顯示相反的情況:文字會在不規則形狀的多邊形內流動:

文字流入不規則形狀的多邊形
文字流入不規則形狀的多邊形

如要讓文字在任意形狀內或周圍流動,第一步是開發並最佳化所需的演算法。Adobe 目前正在實作,並將直接提供給 WebKit。這些演算法經過最佳化後,就會成為 CSS 排除條件建立的基礎。

如要進一步瞭解 CSS 排除條件,請參閱 html.adobe.com 上的 CSS 排除條件頁面。如要進一步瞭解 Adobe 在 CSS 排除條件基礎技術方面的工作,請參閱 Hans Muller 的網誌文章「水平方塊:CSS 排除條件的多邊形交集」。

CSS 區域和 CSS 排除條件目前的狀態

我第一次公開討論 CSS 區域和 CSS 排除條件,是在 2011 年 Google I/O 的 Adobe Developer Pod 中。當時,我正在使用自訂原型瀏覽器進行示範。觀眾反應非常熱烈,但當他們發現我展示的功能尚未在任何主要瀏覽器中推出時,明顯感到失望。

今年 (2012 年) 我再次參加 Google I/O,這次我和同事 Vincent Hardy 以及 Google 的 Alex Danilo 一起擔任講者 (你可以在這裡觀看簡報)。僅僅一年後,WebKit 就已實作約 80% 的 CSS Regions 規格,並已納入最新版的 Google Chrome (請注意,目前必須透過 chrome://flags 啟用 CSS Regions)。Chrome 適用於 Android 的初步支援功能也已推出:

Android 版 Chrome 的區域
Android 版 Chrome 的地區設定

此外,CSS 區域和 CSS 排除條件已在 Internet Explorer 10 預覽版中實作,目前也列在 Mozilla 的 2012 年 Firefox 路線圖中。Safari 的下一個主要版本應支援大部分 CSS 區域規格,後續更新則應納入其餘規格。

自 2011 年 4 月向 W3C 提出 CSS 區域和 CSS 排除項目的初步提案以來,我們在 CSS 區域和 CSS 排除項目方面取得了哪些進展,請參閱下方詳細時間表:

區域和排除條件進度
區域和排除條件進度

結論

Adobe 在文字、字型和一般桌面出版方面擁有豐富經驗,並透過 InDesign 等工具提供相關服務。雖然網路已經是相當強大的文字平台,但我們希望運用自身的知識和經驗,進一步提升文字呈現方式。CSS 區域和 CSS 排除項目可讓內容保留語意結構,同時提供真正的雜誌式版面配置,最終打造更具表達力的網頁。