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

Christian Cantrell
Christian Cantrell

簡介

網路是文字的強大平台,Adobe 在這方面擁有豐富的經驗和專業知識。因此,當 Adobe 尋找推動網路發展的方法時,進一步提升網路的文字功能似乎是我們顯而易見的起點。網頁通常會假設文字為單欄、垂直方向。雖然可以讓文字圍繞圖片,甚至使用 CSS 將文字格式化為多欄,但要在網頁上實現真正的雜誌式版面配置仍非常困難。Adobe 透過 CSS 區域和 CSS 排除,率先將桌上出版功能帶入新式瀏覽器。舉例來說,在下方的螢幕截圖中,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. 使用在網頁中尋找功能 (Ctrl/Command + F),搜尋「實驗性網路平台功能」部分。
  4. 按一下「啟用」連結。
  5. 點按底部的「立即重新啟動」按鈕。

如要進一步瞭解 Chrome 旗標,請參閱網誌文章「Chrome 旗標功能簡介」。

重新啟動瀏覽器後,即可開始試用 CSS 區域。

CSS 區域總覽

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

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

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

未套用樣式的人類遺產專案範例
未套用樣式的真人語音舊版專案範例

使用 CSS 區域後,我能打造更具視覺吸引力且更實用的體驗,因為瀏覽更輕鬆,閱讀也更舒適:

Human Legacy Project 顯示區域
Human Legacy Project with Regions.

為了示範,我在這個原型中加入了顯示 CSS 區域的功能。下方螢幕截圖顯示區域的排列方式,看起來就像是圍繞著中央圖片和引文的欄:

Human Legacy Project 顯示區域
Human Legacy Project 顯示區域

您可以在這裡試用這個原型 (以及查看原始碼)。使用方向鍵瀏覽,然後按下 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-into 和 from-from CSS 屬性的值。如要取得上方程式碼片段中指定具名流程的參照,請傳入字串「article」。
  • WebKitNamedFlow:具名 floe 的物件表示法,具有下列屬性和函式:
    • firstEmptyRegionIndex:整數值,指向與命名流程相關聯的第一個空白區域索引。請參閱下方的 getRegions(),瞭解如何取得區域集合。
    • name:字串值,代表流程名稱。
    • overset:布林值屬性,可能如下:
      • 當具名流程的內容符合相關聯區域時,false
      • true:內容不適合,且需要更多區域才能容納所有內容。
    • getContent():這個函式會傳回一個集合,其中包含流入指定流程的節點參照。
    • getRegions():這個函式會傳回一個集合,其中包含對應區域的參照,這些區域會保留命名流程的內容。
    • getRegionsByContentNode(node):這個函式會傳回包含指定節點的區域參照。這項功能特別適合用來尋找包含具名錨點等項目的區域。
  • webkitregionoversetchange 事件。每當相關內容的版面配置因任何原因 (新增或移除內容、字型大小變更、區域形狀變更等) 發生變更,且導致區域的 webkitRegionOverset 屬性變更時,系統就會在 WebkitNamedFlow 上觸發這個事件。這個事件適合用於監聽粗略的版面配置變更。這表示發生了重要事件,版面配置可能需要處理,例如:需要更多區域、某些區域可能空白等。
  • webkitregionfragmentchange 事件。編輯時尚未實作。每當相關聯內容的版面配置因任何原因而變更時,系統就會在 WebkitNamedFlow 上觸發此事件,類似於 webkitregionoversetchange,但無論 webkitRegionOverset 屬性是否有任何變更。這個事件可用於監聽不一定會影響命名流程整體版面配置的精細版面配置變更,例如:內容從一個區域移至另一個區域,但整體內容仍適合所有區域。
  • Element.webkitRegionOverset:元素獲派 flow-from CSS 屬性後,就會變成區域。這些元素具有 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 則將這種製作品質帶到網頁上。

下方螢幕截圖來自 CSS Exclusions 原型,顯示文字沿著大型岩層輪廓的路徑動態流動:

CSS 排除條件實際應用範例
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 中提供 (請注意,目前必須透過 chrome://flags 啟用 CSS 區域)。Android 版 Google Chrome 甚至已初步支援 CSS 區域:

Android 版 Google Chrome 的區域
Android 版 Google Chrome 的區域

此外,CSS 區域和 CSS 排除項目都已在 Internet Explorer 10 預先發布版中實作,目前也列在 Mozilla 的 2012 年 Firefox 藍圖中。Safari 的下一個主要版本應支援大部分的 CSS 區域規格,後續更新則會包含其餘部分。

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

區域和排除進度
區域和排除進度

結論

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