本頁面由 Cloud Translation API 翻譯而成。 首頁 Articles 開始使用 CSS 形狀 在自訂路徑中包裝內容 Razvan Caliman X 首頁 長期以來,網頁設計師都必須在矩形的限制範圍內進行設計。由於大多數創意嘗試採用非矩形版面配置的結果都令人失望,因此網站上的大部分內容仍侷限於簡單的方塊。不過,這項情況即將改變,因為 Chrome 37 以上版本將推出 CSS 形狀功能。有了 CSS 形狀,網頁設計師就能將內容包裝在自訂路徑 (例如圓形、橢圓形和多邊形) 中,擺脫矩形的限制。 您可以手動定義形狀,也可以從圖片推斷出形狀。 讓我們來看一個非常簡單的例子。 也許您一開始浮動含有透明部分的圖片時,也像我一樣天真地認為內容會展開並填滿空白區塊,但最後卻發現元素周圍仍有矩形的展開形狀,這讓您感到失望。您可以使用 CSS 形狀解決這個問題。 <img class="element" src="image.png" /> <p>Lorem ipsum…</p> <style> .element{ shape-outside: url(image.png); shape-image-threshold: 0.5; float: left; } </style> shape-outside: url(image.png) CSS 宣告會告訴瀏覽器從圖片中擷取形狀。 shape-image-threshold 屬性會定義用來建立形狀的像素最小不透明度。其值必須介於 0.0 (完全透明) 和 1.0 (完全不透明) 之間。因此,shape-image-threshold: 0.5 表示只有不透明度為 50% 以上的像素會用來建立形狀。 float 屬性在此處扮演關鍵角色。雖然 shape-outside 屬性可定義內容會套用的區域形狀,但如果沒有浮動,您就不會看到形狀的效果。 元素在 float 值的另一側有浮動區域。舉例來說,如果含有咖啡杯圖片的元素浮動至左側,浮動區域就會建立在咖啡杯的右側。雖然您可以設計出兩側都有空白的圖片,但內容只會在浮動屬性指定的對角形狀 (左或右) 上左右對齊,不會同時在兩側對齊。 日後,您可以在不浮動元素上使用 shape-outside,這要歸功於 CSS 排除項目的引入。 手動建立形狀 除了從圖片中擷取形狀,您也可以手動編碼。您可以選擇幾個函式值來建立形狀:circle()、ellipse()、inset() 和 polygon()。每個形狀函式都會接受一組座標,並與建立座標系統的參考方塊配對。我們稍後會進一步說明參考資料方塊。 circle() 函式 圓形形狀值的完整符號為 circle(r at cx cy),其中 r 是圓形的半徑,cx 和 cy 則是 X 軸和 Y 軸上圓心座標。圓心座標為選用項目。如果省略這些值,系統會使用元素的中心 (對角線的交會點) 做為預設值。 .element{ shape-outside: circle(50%); width: 300px; height: 300px; float: left; } 在上述範例中,內容會環繞圓形路徑外側。單一引數 50% 會指定圓形的半徑,在這個特定情況下,等同於元素寬度或高度的一半。變更元素的尺寸會影響圓形圖形的半徑。以下是 CSS 圖形如何回應式的基本範例。 在繼續之前,請先注意一點:CSS 形狀只會影響元素周圍浮動區域的形狀。如果元素有背景,則不會遭到形狀裁剪。如要達到這種效果,您必須使用 CSS 遮罩的屬性,也就是 clip-path 或 mask-image。clip-path 屬性非常實用,因為它遵循 CSS 形狀的符號,因此您可以重複使用值。 本文件中的插圖會使用裁剪功能來突顯形狀,協助您瞭解效果。 回到圓形。 使用百分比表示圓形半徑時,系統實際上會使用稍微複雜的公式來計算這個值:sqrt(width^2 + height^2) / sqrt(2)。瞭解這一點很有幫助,因為這有助於您想像,如果元素的尺寸不相等,產生的圓形會是什麼形狀。 所有 CSS 單位類型都可以用於形狀函式座標,包括 px、em、rem、vw、vh 等。您可以根據需求選擇彈性或固定的版本。 您可以為圓心座標設定明確的值,藉此調整圓形的位置。 .element{ shape-outside: circle(50% at 0 0); } 這會將圓形中心置於座標系統的原點。什麼是座標系統?這就是我們要介紹參考方塊的地方。 CSS 形狀的參考方塊 參考方塊是元素周圍的虛擬方塊,用於建立用來繪製及定位形狀的座標系統。座標系統的起點位於左上角,X 軸指向右側,Y 軸指向下方。 請注意,shape-outside 會變更內容會套入其中的浮動區域形狀。浮動區域會延伸至 margin 屬性定義的方塊外緣。這稱為 margin-box,如果未明確提及任何形狀,則為形狀的預設參考方塊。 以下兩個 CSS 宣告的結果相同: .element{ shape-outside: circle(50% at 0 0); /* identical to: */ shape-outside: circle(50% at 0 0) margin-box; } 我們尚未為元素設定邊界。此時,您可以放心假設座標系統的起點和圓形中心位於元素內容區域的左上角。設定邊界後,這項設定會變更: .element{ shape-outside: circle(50% at 0 0) margin-box; margin: 100px; } 座標系統的起點現在位於元素內容區域之外 (向上 100 像素和向左 100 像素),圓形中心也是如此。計算出的圓半徑值也會增加,以反映 margin-box 參考方塊建立的座標系統表面增加的情形。 您可以選擇幾個參考框選項:`margin-box`、`border-box`、`padding-box` 和 `content-box`。這些名稱暗示了各自的邊界。我們先前已說明 `margin-box`。`border-box` 受元素邊框外緣的限制,`padding-box` 受元素邊框間距的限制,而 `content-box` 則與元素內內容使用的實際表面面積相同。 在 shape-outside 宣告中,一次只能使用一個參照方塊。每個參考方塊都會以不同的方式影響形狀,有時甚至難以察覺。另一篇文章則會深入探討 CSS 形狀的參照方塊,協助您瞭解相關資訊。 ellipse() 函式 橢圓形看起來像被壓扁的圓形。這些屬性定義為 ellipse(rx ry at cx cy),其中 rx 和 ry 是 X 軸和 Y 軸上橢圓形的半徑,而 cx 和 cy 則是橢圓形中心的座標。 .element{ shape-outside: ellipse(150px 300px at 50% 50%); width: 300px; height: 600px; } 系統會根據座標系統的維度計算百分比值。這裡不需要使用奇怪的數學方法,您可以省略橢圓形中心的座標,系統會根據座標系統的中心推斷這些座標。 您也可以使用關鍵字定義 X 軸和 Y 軸上的半徑:farthest-side 會產生半徑,等於橢圓形中心與參考方塊最遠邊緣之間的距離;closest-side 則代表相反的情況,會使用中心與邊緣之間最短的距離。 .element{ shape-outside: ellipse(closest-side farthest-side at 50% 50%); /* identical to: */ shape-outside: ellipse(150px 300px at 50% 50%); width: 300px; height: 600px; } 當元素的尺寸 (或參考方塊) 可能以無法預測的方式變更,但您希望橢圓形圖形能夠調整時,這可能會很實用。 circle() 形狀函式中的半徑也可以使用相同的 farthest-side 和 closest-side 關鍵字。 polygon() 函式 如果您覺得圓形和橢圓形的限制太多,可以使用多邊形形狀函式,選擇更多選項。格式為 polygon(x1 y1, x2 y2, ...),您可以為多邊形的每個頂點 (點) 指定一組 x y 座標。指定多邊形的最小組合數量為三個,也就是一個三角形。 .element{ shape-outside: polygon(0 0, 0 300px, 300px 600px); width: 300px; height: 600px; } 頂點會放置在座標系統中。對於回應式多邊形,您可以為部分或所有座標使用百分比值。 .element{ /* polygon responsive to font-size*/ shape-outside: polygon(0 0, 0 100%, 100% 100%); width: 20em; height: 40em; } 從 SVG 匯入的選用 fill-rule 參數會指示瀏覽器如何在遇到自相交路徑或封閉形狀時,判斷多邊形的「內部性」。Joni Trythall 非常詳細地說明 SVG 中的fill-rule 屬性運作方式。如果未定義,fill-rule 的預設值為 nonzero。 .element{ shape-outside: polygon(0 0, 0 100%, 100% 100%); /* identical to: */ shape-outside: polygon(nonzero, 0 0, 0 100%, 100% 100%); } inset() 函式 inset() 形狀函式可讓您建立矩形形狀,用於包裝內容。考量到 CSS Shapes 最初的設計目的是讓網頁內容不受簡單方塊的限制,這可能聽起來有違常理。很有可能。我還沒有發現 inset() 的用途,是浮動和邊距或 polygon() 無法達成的。不過,inset() 的矩形形狀運算式比 polygon() 更易讀。 內嵌形狀函式的完整符號為 inset(top right bottom left border-radius)。前四個位置引數是從元素邊緣向內的偏移量。最後一個引數是矩形形狀的邊框半徑。這項屬性是選用的,因此您可以省略。這會遵循您在 CSS 中已使用的 border-radius 速記符號。 .element{ shape-outside: inset(100px 100px 100px 100px); /* yields a rectangular shape which is 100px inset on all sides */ float: left; } 根據參考方塊建立形狀 如果您未為 shape-outside 屬性指定形狀函式,可以讓瀏覽器從元素的參照方塊衍生出形狀。預設的參考方塊為 margin-box。目前沒有任何特殊情況,浮點數就是這樣運作。不過,您可以透過這項技巧重複使用元素的幾何圖形。讓我們來看看 border-radius 屬性。 如果您使用它來圓滑浮動元素的邊角,您會看到裁剪效果,但浮動區域仍會是矩形。新增 shape-outside: border-box,將其包圍在 border-radius 建立的輪廓周圍。 .element{ border-radius: 50%; shape-outside: border-box; float: left; } 當然,您也可以以這種方式使用所有參考資料方塊。以下是衍生形狀的另一種用途:偏移的引文。 只要使用浮動和邊界屬性,就能達到偏移的引文效果。但這需要您在 HTML 樹狀結構中將引號元素置於要算繪的點。 以下是如何在保留相同的拉用引文效果的同時,增加彈性: .pull-quote{ shape-outside: content-box; margin-top: 200px; float: left; } 我們明確設定形狀座標系統的 content-box 參考框。在這種情況下,引文中內容的數量會決定外部內容的換行形狀。無論在 HTML 樹狀結構中的哪個位置,這裡都會使用 margin-top 屬性來定位 (偏移) 引文。 形狀邊界 您會發現,將內容包圍在形狀周圍,可能會讓內容與元素過於靠近。您可以使用 shape-margin 屬性,在形狀周圍加入間距。 .element{ shape-outside: circle(40%); shape-margin: 1em; float: left; } 效果與使用一般 margin 屬性時類似,但 shape-margin 只會影響 shape-outside 值周圍的空間。只有在座標系統中有足夠空間時,才會在形狀周圍加上間距。因此,在上述範例中,圓形半徑設為 40%,而非 50%。如果半徑設為 50%,圓形會佔用座標系統中的所有空間,導致 shape-margin 的效果無法顯示。請注意,形狀最終會受限於元素的 margin-box (元素加上周圍的 margin)。如果形狀較大且溢出,系統會將其裁剪為 margin-box,最後會變成矩形。 請注意,shape-margin 只接受單一正值。沒有長寫法。圓形的形狀邊框頂端是什麼? 為形狀製作動畫 您可以將 CSS 圖形與許多其他 CSS 功能 (例如轉場效果和動畫) 混合使用。不過,我必須強調,如果在使用者閱讀時文字版面配置有所變動,他們會覺得非常困擾。如果您決定要為形狀製作動畫,請務必仔細評估使用者體驗。 只要 circle() 和 ellipse() 形狀的半徑和中心已定義為瀏覽器可插補的值,您就可以為這些形狀製作動畫。從 circle(30%) 變更為 circle(50%) 是可行的。不過,如果在 circle(closest-side) 和 circle(farthest-side) 之間加入動畫,瀏覽器會發生壅塞。 .element{ shape-outside: circle(30%); transition: shape-outside 1s; float: left; } .element:hover{ shape-outside: circle(50%); } 您可以在製作 polygon() 形狀的動畫時,獲得更多有趣的效果。請注意,兩個動畫狀態之間的多邊形必須有相同的頂點數。如果您新增或移除頂點,瀏覽器就無法進行插補。 其中一個訣竅是新增所需的頂點數量上限,並在您希望形狀的邊緣較少的動畫狀態中,將這些頂點叢集在一起。 .element{ /* four vertices (looks like rectangle) */ shape-outside: polygon(0 0, 100% 0, 100% 100%, 0 100%); transition: shape-outside 1s; } .element:hover{ /* four vertices, but second and third overlap (looks like triangle) */ shape-outside: polygon(0 0, 100% 50%, 100% 50%, 0 100%); } 在形狀內換行顯示內容 CSS 形狀規格的初始草稿包含 shape-inside 屬性,可讓您在形狀內包裝內容。甚至在 Chrome 和 WebKit 中也曾經實作過。不過,如果要將任意位置的內容包裝在自訂路徑中,就必須花費更多心力和時間進行研究,才能涵蓋所有可能的情況並避免發生錯誤。因此,shape-inside 屬性已延後至 CSS 形狀第 2 級,且已撤銷相關實作。 不過,只要稍微調整一下,您還是可以讓內容在自訂形狀中換行。這個技巧是使用兩個浮動元素搭配 shape-outside,並將其放在容器的兩側。折衷之道是,您必須使用一或兩個沒有語意意義的空元素,但可做為支柱,營造出內部有形狀的錯覺。 <div> <div class='left-shape'></div> <div class='right-shape'></div> Lorem ipsum... </div> 容器頂端的 .left-shape 和 .right-shape 支柱元素位置非常重要,因為它們會浮動至左側和右側,以便夾在內容兩側。 .left-shape{ shape-outside: polygon(0 0, ...); float: left; width: 50%; height: 100%; } .right-shape{ shape-outside: polygon(50% 0, ...); float: right; width: 50%; height: 100%; } 這項樣式會讓兩個浮動支柱占用元素內的所有空間,但 shape-outside 屬性會為其餘內容劃出空間。 如果瀏覽器不支援 CSS 形狀,則會將所有內容向下推,產生難看的效果。因此,請務必以漸進式強化的方式使用這項功能。 在先前的形狀動畫範例中,您會發現文字的移動可能會造成困擾。並非所有用途都需要使用動畫形狀。不過,您可以為與 CSS 形狀互動的其他屬性設定動畫,在適當情況下加入效果。 在 CSS 形狀的 愛麗絲夢遊仙境 示範中,我們使用捲動位置來變更內容的上邊界。文字會擠在兩個浮動元素之間。當它向下移動時,必須根據兩個浮動元素的 shape-outside 重新排版。這會讓文字看起來像是進入兔子洞,增添了說故事的體驗。是否有點過度?不一定。但看起來很酷。 由於文字版面配置是由瀏覽器原生完成,因此效能會比使用 JavaScript 解決方案來得好。不過,變更捲動畫面上的 margin-top 會觸發許多重新排版和繪製事件,可能會明顯降低效能。請謹慎使用!不過,使用 CSS 圖形時,如果不加上動畫效果,效能不會受到明顯影響。 漸進增強 一開始,請假設瀏覽器不支援 CSS 形狀,然後在偵測到這項功能時,再進行相關設定。Modernizr 是執行功能偵測的絕佳解決方案,而且在「非核心偵測」部分中,還有 CSS 形狀的測試。 部分瀏覽器會透過 @supports 規則在 CSS 中提供功能偵測功能,不需要外部程式庫。Google Chrome 也支援 CSS 形狀,並可解讀 @supports 規則。以下是逐步提升的使用方式: .element{ /* styles for all browsers */ } @supports (shape-outside: circle(50%)){ /* styles only for browsers which support CSS Shapes */ .element{ shape-outside: circle(50%); } } Lea Verou 已進一步說明如何使用 CSS @supports 規則。 從 CSS 排除條件中排除歧義 我們現在稱為 CSS 形狀的內容,在規格早期曾被稱為 CSS 排除和形狀。名稱的轉換可能看似微不足道,但其實非常重要。CSS 排除項目現在是個別規格,可讓您在任意位置包裝元素,而不需要浮動屬性。假設您要將內容包裝在絕對定位元素周圍,這就是 CSS 排除條件的用途。CSS 形狀只會定義內容會包裝在哪個路徑上。 因此,雖然形狀和排除條件不盡相同,但兩者確實相輔相成。目前瀏覽器支援 CSS 形狀,但 CSS 排除條件尚未實作形狀互動功能。 使用 CSS 形狀的工具 您可以在傳統圖像製作工具中建立路徑,但在撰寫本文時,沒有任何工具會匯出 CSS 形狀值所需的語法。即使他們有,這麼做也不太實際。 CSS 形狀應在瀏覽器中使用,以便對網頁上的其他元素做出反應。這項功能可讓你以視覺化方式,瞭解編輯形狀對周圍內容的影響。您可以使用以下幾個工具協助處理這個工作流程: Brackets:Brackets 專用的 CSS 形狀編輯器擴充功能會使用程式碼編輯器的即時預覽模式,重疊互動式編輯器,以便編輯形狀值。 Google Chrome:CSS Shapes Editor 擴充功能 (適用於 Google Chrome) 可擴充瀏覽器的開發人員工具,提供用於建立及編輯形狀的控制項。會在所選元素上方放置互動式編輯器。 Google Chrome 中的檢查器內建了形狀醒目顯示功能。將滑鼠游標懸停在含有 shape-outside 屬性的元素上,該元素就會亮起,以便說明形狀。 從圖片建立形狀:如果您想產生圖片,並讓瀏覽器從中擷取形狀,Rebecca Hauck 撰寫了一份不錯的 Photoshop 教學文章。 Polyfill:Google Chrome 是第一個推出 CSS 形狀的大型瀏覽器。這項功能即將支援 Apple 的 iOS 8 和 Safari 8。其他瀏覽器供應商日後可能會考慮採用。在此之前,您可以使用 CSS Shapes polyfill 提供基本支援。 結論 在網頁中,內容多半會侷限在簡單的方塊中,CSS Shapes 可讓您以生動的方式建立版面配置,彌補網頁和平面設計之間的忠實度差距。當然,形狀也可能遭到濫用,造成干擾。不過,如果運用得當,形狀就能提升內容呈現效果,並以使用者獨特的方式吸引他們的注意力。 我將提供其他人製作的作品集給您參考,其中大多是平面印刷品,可讓您瞭解非矩形版面配置的實用用途。希望這篇文章能激勵您嘗試 CSS 形狀,並實驗新的設計構想。 感謝陳怡如、Alan Stearns 和 Zoltan Horvath 審查本文並提供寶貴意見。