原文:Take A New Look At CSS Shapes
做者:Rachel Andrew 發表時間:september 4, 2018
譯者:西樓聽雨 發表時間: 2018/9/16
(轉載請註明出處)css
摘要:在本文中,咱們將對 CSS 形狀的概念,以及如何用圖片、漸變和基礎形狀來建立非矩形類的形狀作一個講解。另外咱們還會講到 Firefox 的新工具是如何讓咱們編輯形狀變得簡單的。web
CSS 形狀第一階段規範已經在 Chrome 和 Safari 中實現了有好幾年了,而隨着 Firefox 62 在本週發佈,Firefox 也已經在生產版本中支持了——另外隨之發佈的還有一個很棒的開發者工具功能,它對咱們使用形狀能夠帶來幫助。在本文中,咱們將看下一能夠用 CSS 形狀作哪些事情。也許是時候考慮給咱們的設計添加一些曲線效果了!瀏覽器
The CSS Shapes specification Level 1 defines three new properties:服務器
CSS 形狀規範的第一階段 (CSS Shapes Level 1) 定義了三個新的屬性:app
shape-outside
shape-image-threshold
shape-margin
In the current specification, shapes can only be applied to a float, so any shapes example needs to start with a floated element. In the example below, I have a PNG image with a transparent background in which I have floated the image left. The text that follows the image now flows around the right and bottom of my image.ide
What I would like to happen is for my content to follow the shape of the opaque part of the image, rather than follow the line of the physical image file. To do this, I use the shape-outside
property, with the value being the URL of my image. I’m using the actual image file to create a path for the content to flow around.函數
這個規範的制定,目的是爲了讓內容的排布能夠支持環繞着非矩形類形狀進行,即那些和咱們 Web 的盒子模型極大不一樣的形狀。建立形狀有多種方式,咱們會在這篇教程中講到。另外咱們還會對 Shape Path Editor ——可在 Firefox 中找到——作一下介紹,由於它能夠幫助咱們理解和使用形狀。工具
在當前版本的規範中,規定了形狀只能被應用在浮動元素上。在下面的這個例子中,我放了一張背景透明的 PNG 圖片,並將其浮動到左邊。其後的文本隨之排布在了其右側和底部。flex
在這例子中,我真正但願的結果是,個人內容能夠圍繞圖片中非透明部分的形狀進行排布,而不是這個圖片文件的物理邊線。因此,爲了實現這種效果,我使用的是 shape-outside
屬性,並把這個圖片的 URL 做爲其值。這裏我使用的就是圖片文件來爲個人內容建立環繞路徑的。 ui
This method of creating shapes uses the alpha channel of the image to create the shape, as we have a shape with a fully transparent area, then all we need do is pass the URL of the image to shape-outside
and the shape path follows the line of the fully opaque area.
注意,你的圖片須兼容 CORS,因此須要把圖片放在和你內容相同的服務器下,或者假如放在 CDN 上的話,須要確保響應正確的 HTTP 頭部。若是你的圖片由於 CORS 被屏蔽了,能夠在瀏覽器的開發者工具中看到。
(譯註:CORS,全稱 Cross-Origin Resource Sharing;跨源性資源共享。這裏的「圖片」指的是 shape-outside
屬性中的 URL,而不是指 img 標籤——它是無需兼容 CORS 的 )
這種建立形狀的方法,使用的是圖片的 alpha 通道。由於咱們這張圖片裏的形狀以外都是徹底透明的區域,因此咱們只需把它 URL 給到 shape-outside
屬性,便可實現將非透明區域的邊線所造成的路徑做爲形狀。
爲了將文本從圖片上推開,咱們可使用 shape-margin
屬性,它能夠在形狀及其周圍的內容之間設置一個邊界。
上面的例子中,咱們將圖片展現在頁面中,並使得文本環繞着它彎曲。其實,你也能夠作到在不展現那張圖片的狀況的同時使用那張圖片的形狀做爲環繞路徑來得到一樣的效果。不過要作到這種效果,咱們仍然須要有一個浮動的元素,爲此,咱們能夠用生成的內容 (Generated Content;[譯註] 這裏指僞類) 來充當。
在這個例子中,咱們經過插入生成的內容,並將其浮動到左側,給其設置寬度和高度,而後使用以前的圖片做爲 shape-outside
。這樣咱們就達到了在沒有可見的圖片的狀況下,仍然得到曲線性地圍繞空白區域的效果。
Once the gradient becomes fully transparent, then the shape comes into play, and the content runs along the edge of the gradient.
CSS 漸變就至關於一張圖片,也就是說咱們能夠用其來建立形狀,這樣咱們就能夠製做出一些有趣的特效。在下面這個例子中,我建立了一個藍色到透明的漸變(要使用形狀,須要有必定的透明區域或半透明區域)。此次我一樣使用了生成的內容做爲漸變的載體和 shap-outside
的值。
在漸變過分到全透明的地方,就會造成形狀,也是內容所環繞的邊界。
A gradient like our example above is a great way to see this in action as we can change the shape-image-threshold
value and move the line along which the text falls to more opaque areas or more transparent areas. This property works in exactly the same way with an image that has an alpha channel yet is not fully transparent.
到這裏爲止,咱們已經看到了如何使用圖片或漸變的全透明部分來建立形狀。其實,CSS 形狀規範中定義的這第三個屬性可讓咱們經過設置一個透明度閾值來使用圖片或漸變的半透明部分建立形狀。這個屬性的值爲 1
時,表示徹底不透明;值爲 0
時,表示全透明。
要觀察它的效果,前一個例子中的漸變就是一個很好的對象,咱們能夠改變其 shape-image-threshold
屬性的值來使文本落在更加不透明的區域或更加透明的區域中的位置。對於有 alpha 通道的非全透明的圖片,這個屬性的效果徹底同樣。
上面這些建立形狀的方法,在我看來,是最直接的。你能夠經過先在圖像處理類軟件中按照你的須要建立任意複雜的形狀,而後在頁面中進行使用。其實我是想說還有另外一種方式建立形狀,那就是使用基礎形狀 (Basic Shapes) 。
「基礎形狀」是一系列預約義的形狀,它包含了許多你可能想要建立的各種形狀。使用基礎形狀時,咱們使用的是基礎形狀的類型做爲 shape-outside
的值。這種類型使用函數形式來表示的,因此他們的名字的尾部會有一對括號 (括號裏面是一些關於咱們所需的形狀的值) 。
The options that you have are the following:
你可使用的形狀類型有如下這些:
inset()
circle()
ellipse()
polygon()
In the example below, I am creating the most simple of shapes: a circle using shape-outside: circle(50%)
. I’m using generated content again, and I have given the box a background color, and also added a margin, border, and padding to help highlight some of the concepts of using CSS Shapes. You can see in the example that the circle is created centered on the box; this is because I have given the circle a value of 50%. That value is the <shape-radius>
which can be a length or a percentage. I’ve used a percentage so that the radius is half of the size of my box.
在下面的例子中,我建立是最簡單的形狀之一:一個圓,使用的是 shape-outside: circle(50%)
。此次我仍是使用生成的內容,並給了這個 box 一個背景色,還設置了一個外邊距、邊框和內邊距,以此來着重展現使用 CSS 形狀的一些概念。在這個例子中,你能夠看到,這個圓居中在這個 box 中;這是由於我給了這個圓一個 50%
的值。這個值的定義爲 <shape-radius>
(譯註:形狀的半徑),它能夠是一個長度值,也能夠是一個百分比。
如今就是咱們用 Firefox 的 Shape Path Editor 來查看一下這個形狀的好時機。點擊生成的內容,而後點擊其 shape-outside
屬性旁的圖標,就能夠將形狀高亮顯示出來。
你能夠看到,這個圓的範圍觸及到了外邊距的外邊緣上,這是由於咱們的形狀默認使用的參照盒子 (reference box) 是 margin-box
。若是你以前有添加過 box-sizing: border-box
,你其實就已經知道什麼是參照盒子,當你添加這個屬性時,就是在告訴 CSS 要使用 border-box
而不是默認的 content-box
做爲元素的尺寸。在形狀的使用中,咱們一樣能夠調整其所使用的參照盒子。在任意基礎形狀以後,加上 border-box
表示使用邊框來定義形狀,加上 content-box
則使用內容區域 (在 padding 以內) 的邊緣的來定義。例如:
.content::before {
content: "";
width: 150px;
height: 150px;
margin: 20px;
padding: 20px;
border: 10px solid #FC466B;
background: linear-gradient(90deg, #FC466B 0%, #3F5EFB 100%);
float: left;
circle(50%) content-box;
}
複製代碼
You will see the circle appear to become much smaller. It is now using the width of the content — in this case the width of the box at 150px — rather than the margin box which includes the padding, border, and margin.
這樣,你就會發現這個圓看上去嚴重縮小了,它如今使用的是內容區域的寬度——本例中爲 150px ——而不是包含了內邊距、邊框和外邊距的 margin-box。
Inspecting your element in Firefox DevTools will also show you the reference boxes so you can choose which might give you the best result with your particular shape.
在 Firefox 的開發者工具中對這個元素進行審視 (inspecting) ,會展現出它的各種參照盒子,據此你能夠選擇出特定形狀下效果最好的那個。
circle()
中的第二個值表示的是位置,若是你不指定的話,默認爲 center
。你能夠利用這個值來任意調整你的圓所在的位置。在接下來的例子中,我使用 shape-outside(50% at 30%)
(譯註:這明顯是原文的筆誤,正確的是 circle(50% at 30%)
) 來設置這個圓的位置,它調整的是這個圓的中心點所處的位置。
一個有用的知識是,基礎形狀一樣可使用在 clip-path 上;也就是說在建立了一個形狀值後,你能夠把超出了形狀以外的圖片和背景顏色部分剪掉。在下面這個例子中,我將用咱們的漸變背景的例子來展現,咱們會獲得一個圍繞着彎曲了的文本的圓。
All of the above concepts can be applied to our other basic shapes. Now let’s have a quick look at how they work.
本段講的這些,對咱們的其餘基礎形狀一樣適用。如今讓咱們來看下一他們是如何使用的。
In the example below, I am using the values to inset the content on the right and bottom of the floated image, plus adding a border radius around which my content will wrap using shape-outside: inset(0 30px 100px 0 round 40px)
. You can see how the content is now over the background color of the box:
inset()
值定義的是一個矩形。這看上去好像沒什麼用,由於浮動元素自己就是矩形;其實它的真正的涵義是你能夠將文本內斂 (inset) 進來。它接收四個參數,分別爲頂部、右側,底部和左側,再加一個圓角半徑值。
在下面這個例子中,我使用 shape-outside: inset(0 30px 100px 0 round 40px)
來將內容從右側和底部內斂進來,在加上一個圓角半徑。如今,你能夠看到這些內容將如何覆蓋到盒子的背景顏色上:
橢圓就是被壓扁了的圓,因此咱們須要有兩個半徑:x 和 y (建立時順序與此一致) 來建立,也一樣也能夠像圓同樣經過位置值來任意調整位置。在下面這個例子中,我建立了一個橢圓並把相同的值使用在 clip-path 屬性上。
In the above example, I also used shape-margin
to demonstrate how we can use this property as with our image generated shapes to push the content away.
在這個例子中,我還使用了 shape-margin
屬性,爲的是演示如何配合使用這個屬性,將內容推開必定距離。
It is here where the Firefox tools become really useful as we can use them to help create our polygon. In the below example, I have created a polygon with four points. In the Firefox DevTools, you can double-click on any line to create a new point, and double-click again to remove it. Once you have created a polygon that you are happy with, you can then copy the value out of DevTools for your CSS.
多邊形形狀的建立可讓咱們擁有最大的靈活性,由於咱們的形狀能夠用三個以上的點來建立。傳遞到多邊形中的值須要至少3對錶示座標的值。
這個時候 Firefox 就變得很是有用了,由於他能夠幫助咱們建立多邊形。下面這個例子中,我建立了一個由四個點組成的多邊形,在 Firefox 的開發者工具中,你能夠在任意一條邊上雙擊來添加一個新的點,再次雙擊能夠移出這個點。在你建立出了讓你滿意的多邊形後,你就能夠將其從開發者工具中拷貝出來用到你的 CSS 中。
Where you should take care would be in any situation where not having shapes could mean that content overlaid an area which made it difficult to read. Perhaps you are using Shapes to push content away from a busy area of a background image, for example. In that case, you should first make sure that your content is usable for the non-Shapes people, then use Feature Queries to check for support of shape-outside
and overwrite that CSS and apply the shape. For example, you could use a margin to push the content away for non-Shapes visitors and remove the margin inside your feature query.
由於 CSS 形狀是應用在浮動元素上的,因此在大多數狀況下出現兼容性問題時,咱們看的將會是內容圍繞着浮動元素 (就和通常狀況下的同樣),而不是圍繞着形狀排布。瀏覽器會把他所不支持的屬性忽略掉,因此若是它們不支持形狀,把 shape-outside
屬性放上去也不會有什麼影響。
你真正須要考慮的問題是,在不支持形狀的狀況下,會使得內容難以閱讀的內容排布情形。一般咱們使用形狀,都會把內容隔開必定距離。在這種情形下,你應該首先確保那些不支持形狀的用戶,而後再使用特性查詢(Feature Query)來檢查 shape-outside
的支持狀況,並進行 CSS 覆蓋和應用形狀。例如,你能夠爲不支持形狀的用戶設置一個外邊距,以此將內容推開;而後在特性查詢中將這個外邊距移除。
.content {
margin-left: 120px;
}
@supports (shape-outside: circle()) {
.content {
margin-left: 0;
/* add the rest of your shapes CSS here */
}
}
複製代碼
隨着 Firefox 發佈了對形狀的支持,如今剩下惟一還不支持形狀的主流瀏覽器就是 Edge 了。若是你但願看到形狀廣受支持,你能夠前往這裏爲這個特性投一票。
在本文中,我試着對 CSS 形狀可能的用途作了一個概覽。關於每一個特性更詳細的信息,能夠查看 MDN 上的 Guides to CSS Shapes (CSS 形狀指導)。另外還能夠查看 guide to the Shape Path Editor in Firefox (Firefox 的 Shape Path Editor 使用指導) 。