- 原文地址:An Introduction to CSS Shapes
- 原文作者:Tania Rascia
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:xilihuasi
- 校對者:ElizurHz, Moonliujk
CSS Shapes 簡介
CSS Shapes 允許我們通過定義文字內容可以環繞的幾何形狀、影象和漸變,來建立有趣且獨特的佈局。本次教程會教你如何使用它們。
在 CSS Shapes 問世之前,為網頁設計文字自由環繞的雜誌式佈局幾乎是不可能的。相反,網頁設計佈局傳統上一直用網格、盒子和直線構造。
CSS Shapes 允許我們定義文字環繞的幾何形狀。這些形狀可以是圓、橢圓、簡單或複雜的多邊形,甚至影象和漸變。Shapes 的一些實際設計應用可能是圓形頭像周圍顯示圓形環繞文字,全屏背景圖片的簡單部位上面展示文字,以及在文章中顯示首字下沉。
現在 CSS Shapes 已經獲得了現代瀏覽器的廣泛支援,值得一看的是它們提供的靈活性和功能,以確定它們在你的下一個設計專案中是否能派上用場。
注意:截至攥寫本文時,CSS Shapes 支援 Firefox、Chrome、Safari 和 Opera,以及 iOS Safari 和 Chrome for Android 等移動瀏覽器。Shapes 不支援 IE,對 Microsoft Edge 的支援正在考慮中。
CSS Shapes 初探
CSS Shapes 的當前實現是 CSS Shapes Module Level 1,它主要包含 [shape-outside](https://tympanus.net/codrops/css_reference/shape-outside/)
屬性。shape-outside
定義了文字環繞的形狀。
考慮到有 shape-outside
屬性,你可能會想到還有一個相應的 shape-inside
屬性,它包含形狀內的文字。shape-inside
屬性可能會在將來實現,目前它只是 CSS Shapes Module Level 2裡面的一個草案,並沒有被任何瀏覽器實現。
在本文中,我們將演示如何使用 資料型別,並使用形狀函式值設定它,以及使用半透明 URL 或漸變設定形狀。
基本的形狀函式
我們可以通過將下列函式值應用於 shape-outside
屬性來定義 CSS 中的各種基本形狀:
circle()
ellipse()
inset()
polygon()
要給元素設定 shape-outside
屬性,該元素必須是浮動的並且已設定寬高。讓我們逐個來看四個基本形狀,並演示它們的使用方法。
圓
我們將從 circle()
函式開始。設想如下場景,有一個圓形的作者頭像,我們想讓頭像左浮動並且作者的描述文字環繞它。僅對頭像元素使用 border-radius: 50%
不足以使文字呈圓形;文字仍將把頭像當成矩形元素。
通過圓形,我們可以演示文字如何按圓形環繞。
首先我們在一個普通的 div
上建立 circle
樣式,並且寫幾段文字。(我使用 Bob Ross 語錄作為 Lorem Ipsum 文字。)
<div class="circle"></div>
<p>Example text...</p>
複製程式碼
在 circle
樣式中,我們設定元素左浮動,設定等值的 height
和 width
,並且設定 shape-outside
為 circle()
。
.circle {
float: left;
height: 200px;
width: 200px;
shape-outside: circle();
}
複製程式碼
如果我們訪問頁面,會看到如下場景。
如你所見,文字圍繞圓形環繞,但是我們並沒有看到任何形狀。使用開發工具審查元素,我們可以看到已經設定好的實際形狀。
此時,你可能會認為,給元素 background
設定顏色或者圖片就能看到形狀了。我們來試一下。
.circle {
float: left;
height: 200px;
width: 200px;
shape-outside: circle();
background: linear-gradient(to top right, #FDB171, #FD987D);
}
複製程式碼
不幸的是,給 circle
設定 background
後會顯示一個矩形,這是我們一直試圖避免的事情。
我們可以清晰地看到文字在它周圍環繞,但元素本身沒有形狀。如果我們想要真實地顯示形狀函式,需要使用 clip-path
屬性。clip-path
採用許多和 shape-outside
相同的值,因此我們可以給它同樣的 circle()
值。
.circle {
float: left;
height: 200px;
width: 200px;
shape-outside: circle();
clip-path: circle();
background: linear-gradient(to top right, #FDB171, #FD987D);
}
複製程式碼
在本文剩下的部分,我將使用
clip-path
幫助我們辨認形狀。
circle()
函式接收可選的 radius 引數。在本例中,預設 radius 是 50%
或者 100px
。使用 circle(50%)
或者 circle(100px)
都將產生和我們已經完成樣例的同樣結果。
你可能注意到文字剛好和形狀貼合。我們可以使用 shape-margin
屬性給形狀新增 margin,單位可以是 px
、em
、%
和其他標準的 CSS 測量單位。
.circle {
float: left;
height: 200px;
width: 200px;
shape-outside: circle(25%);
shape-margin: 1rem;
clip-path: circle(25%);
background: linear-gradient(to top right, #FDB171, #FD987D);
}
複製程式碼
這裡有個 circle
radius 設定 25%
並且使用 shape-margin
的例子。
除了 radius,形狀函式可以使用 at
定位。預設位置是圓心,因此 circle()
也可以被顯式設定為 circle(50% at 50% 50%)
或 circle(100px at 100px 100px)
,兩個值分別是水平和垂直位置。
為了搞清楚 position 的作用,我們可以設定水平位置值為 0
來創造一個完美的半圓。
circle(50% at 0 50%);
複製程式碼
該座標定位系統稱為引用框。
稍後,我們將學習如何使用影象代替形狀或者漸變。現在,我們將繼續進行下一個形狀函式。
橢圓
ellipse()
和 circle()
函式類似,只是它會創造橢圓。為了演示,我們建立一個 ellipse
元素和樣式。
<div class="ellipse"></div>
<p>Example text...</p>
複製程式碼
.ellipse {
float: left;
shape-outside: ellipse();
clip-path: ellipse();
width: 150px;
height: 300px;
background: linear-gradient(to top right, #F17BB7, #AD84E3);
}
複製程式碼
這次,我們設定不同的 height
和 width
建立一個垂直拉長的橢圓。
ellipse()
和 circle()
的區別在於橢圓有兩個半徑 —— _r_x
和 _r_y
,或者 X 軸半徑和 Y 軸半徑。因此,上面的例子也可以寫成:
ellipse(75px 150px);
複製程式碼
circles 和 ellipses 的位置引數是一樣的。除了是測量單位,半徑也包括 farthest-side
和 closest-side
的選項。
closest-side
代表引用框的中心到最近側的長度,相反,farthest-side
代表引用框中心到最遠側的長度。這意味著如果未設定預設值以外的位置,則這兩個值無效。
這裡演示了在 ellipse()
上翻轉 closest-side
和 farthest-side
的區別,它的 X 和 Y 軸的偏移量是 25%
。
ellipse(farthest-side closest-side at 25% 25%)
複製程式碼
ellipse(farthest-side closest-side at 25% 25%)
複製程式碼
內嵌
目前為止我們只處理了圓形,但是我們可以使用 inset()
函式定義內嵌矩形。
<div class="inset"></div>
<p>Example text...</p>
複製程式碼
.inset {
float: left;
shape-outside: inset(75px);
clip-path: inset(75px);
width: 300px;
height: 300px;
background: linear-gradient(#58C2ED, #1B85DC);
}
複製程式碼
在本例中,我們創造了一個 300px
的正方形,每條邊內嵌 75px
。這將給我們留下 150px
周圍有 75px
空間。
我們可以看到矩形是內嵌的,文字忽略了內嵌區域。
inset()
形狀也可以使用 round
引數接收 border-radius
,並且文字會識別圓角,就像本例中所有邊都是 25px
內嵌和 75px
圓角。
inset(25px round 75px)
複製程式碼
像 padding
或 margin
簡寫,inset 值以順時針方式(inset(25px 25px 25px 25px)
)接收 top
right
bottom
left
,並且只傳一個值將使四條邊都相同(inset(25px)
)。
多邊形
形狀函式最有趣和靈活的是 polygon()
,它可以採用一系列 x
和 y
點來製作任何複雜形狀。陣列裡的每個元素代表 _x_i _y_i,將被寫成 polygon(x1 y1, x2 y2, x3 y3...)
等等。
我們可以為多邊形設定的點集數量最少為 3,這將建立一個三角形。
<div class="polygon"></div>
<p>Example text...</p>
複製程式碼
.polygon {
float: left;
shape-outside: polygon(0 0, 0 300px, 200px 300px);
clip-path: polygon(0 0, 0 300px, 200px 300px);
height: 300px;
width: 300px;
background: linear-gradient(to top right, #86F7CC, #67D7F5);
}
複製程式碼
在這個形狀中,第一個點是 0 0
,div
中最左上角的點。第二個點是 0 300px
,它是 div
中最左下角的點。第三個也就是最後一個點是 200px 300px
,它在 X 軸的 2/3 處並且也在底部。最終的形狀是這樣:
polygon()
形狀函式的一個有趣用法是文字內容可以在兩個或以上形狀中環繞。因為 polygon()
形狀是如此靈活和動態,這給我們製作真正獨特的雜誌式佈局提供了一個最好機會。在本例中,我們將把文字放在兩個多邊形中。
<div class="left"></div>
<div class="right"></div>
<p>Example text...</p>
複製程式碼
.left {
float: left;
shape-outside: polygon(0 0, 0 300px, 200px 300px);
clip-path: polygon(0 0, 0 300px, 200px 300px);
background: linear-gradient(to top right, #67D7F5, #86F7CC);
height: 300px;
width: 300px;
}
.right {
float: right;
shape-outside: polygon(200px 300px, 300px 300px, 300px 0, 0 0);
clip-path: polygon(200px 300px, 300px 300px, 300px 0, 0 0);
background: linear-gradient(to bottom left, #67D7F5, #86F7CC);
height: 300px;
width: 300px;
}
複製程式碼
顯然,想要手動創造你自己的複雜形狀是非常困難的。幸運的是,你可以用一些工具來建立多邊形。Firefox 有一個內建的形狀編輯器,你可以在 Inspector 中通過點選多邊形使用。
目前,Chrome 有一些你可以使用的擴充套件程式,比如 CSS Shapes Editor。
多邊形可以用來剪下影象或其他元素周圍的形狀。在另一個例子中,我們可以通過在大字母周圍繪製多邊形來建立首字下沉。
<div class="letter">R</div>
<p>Example text...</p>
複製程式碼
.letter {
float: left;
font-size: 400px;
font-family: Georgia;
line-height: .8;
margin-top: 20px;
margin-right: 20px;
shape-outside: polygon(5px 14px, 233px 20px, 246px 133px, 189px 167px, 308px 304px, 0px 306px) content-box;
clip-path: polygon(5px 14px, 233px 20px, 246px 133px, 189px 167px, 308px 304px, 0px 306px);
}
複製程式碼
URLs
CSS Shapes 一個令人激動的特性是你不必每次都通過形狀函式明確定義;你也可以使用半透明影象的 url 來定義形狀,這樣文字就會自動環繞它。
重要的是要注意影象使用必須要相容 CORS,否則你將會遇到如下錯誤。
Access to image at 'file:///users/tania/star.png' from origin 'null'
has been blocked by CORS policy: The response is invalid.
複製程式碼
在同一個伺服器上提供影象將會保證你不會遇到上面的錯誤。
與其他例子不同,我們將使用 img
代替 div
。這次的 CSS 很簡單——只用把 url()
放進 shape-outside
屬性,就像 background-image
一樣。
<img src="./star.png" class="star">
<p>Example text...</p>
複製程式碼
.star {
float: left;
height: 350px;
width: 350px;
shape-outside: url('./star.png')
}
複製程式碼
因為我使用了透明背景的星星影象,文字知道哪些區域是透明的哪些是不透明的,並進行自適應佈局。
漸變
最後,漸變也可以用來當成形狀。漸變和影象一樣,就像我們上面用到的影象例子,文字也將知道在透明部分環繞。
我們將使用漸變的一個新屬性 —— shape-image-threshold
。shape-image-threshold
定義形狀的 alpha 通道閾值,或者影象透明的百分比值。
我們將製作一個漸變例子,它是 50%/50% 的顏色和透明分割,並且設定 shape-image-threshold
為 .5
,意味著超過 50% 不透明的所有畫素都應被視為影象的一部分。
<div class="gradient"></div>
<p>Example text...</p>
複製程式碼
.gradient {
float: left;
height: 300px;
width: 100%;
background: linear-gradient(to bottom right, #86F7CC, transparent);
shape-outside: linear-gradient(to bottom right, #86F7CC, transparent);
shape-image-threshold: .5;
}
複製程式碼
我們可以看到漸變在不透明和透明的中心對角線完美分割。
結語
在本文中,我們學習了 CSS Shapes 的三個屬性 shape-outside
、shape-margin
和 shape-image-threshold
。我們也瞭解到如何使用函式值建立可供文字環繞的圓、橢圓、內嵌矩形以及複雜的多邊形,並且演示了形狀如何檢測影象和漸變的透明部分。
你可以在如下 demo 中找到本文中用到的所有例子,也可以下載原始檔。
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。