[譯]《Smashing》: 用 CSS 形狀打造高級排版

原文Take A New Look At CSS Shapes
做者Rachel Andrew 發表時間:september 4, 2018
譯者:西樓聽雨 發表時間: 2018/9/16
(轉載請註明出處)css

摘要:在本文中,咱們將對 CSS 形狀的概念,以及如何用圖片、漸變和基礎形狀來建立非矩形類的形狀作一個講解。另外咱們還會講到 Firefox 的新工具是如何讓咱們編輯形狀變得簡單的。web

展開原文 CSS Shapes Level 1 has been available in Chrome and Safari for a number of years, however, this week it ships in a production version of Firefox with the release of Firefox 62 — along with a very nice addition to the Firefox DevTools to help us work with Shapes. In this article, I’ll take a look at some of the things you can do with CSS Shapes. Perhaps it’s time to consider adding some curves to your designs?

CSS 形狀第一階段規範已經在 Chrome 和 Safari 中實現了有好幾年了,而隨着 Firefox 62 在本週發佈,Firefox 也已經在生產版本中支持了——另外隨之發佈的還有一個很棒的開發者工具功能,它對咱們使用形狀能夠帶來幫助。在本文中,咱們將看下一能夠用 CSS 形狀作哪些事情。也許是時候考慮給咱們的設計添加一些曲線效果了!瀏覽器

什麼是 CSS 形狀(CSS Shapes)?

The CSS Shapes specification Level 1 defines three new properties:服務器

CSS 形狀規範的第一階段 (CSS Shapes Level 1) 定義了三個新的屬性:app

  • shape-outside
  • shape-image-threshold
  • shape-margin

展開原文 The purpose of this specification is to allow content to flow around a non-rectangular shape, something which is quite unusual on our boxy web. There are a few different ways to create shapes, which we will have a look at in this tutorial. We will also have a look at the Shape Path Editor, available in Firefox, as it can help you to easily understand the shapes on your page and work with them.

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

展開原文 Note that your image needs to be CORS compatible, so hosted on the same server as the rest of your content or sending the correct headers if hosted on a CDN. Browser DevTools will usually tell you if your image is being blocked due to CORS.

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-outsideand 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 屬性,便可實現將非透明區域的邊線所造成的路徑做爲形狀。

設置外邊距

展開原文 To push the line of the text away from the image we can use the `shape-margin` property. This creates a margin between the line of the shape and the content running alongside it.

爲了將文本從圖片上推開,咱們可使用 shape-margin 屬性,它能夠在形狀及其周圍的內容之間設置一個邊界。

利用僞類充當形狀載體 (Using Generated Content For Our Shape)

展開原文 In the case above, we have the image displayed on the page and then the text curved around it. However, you could also use an image as the path for the shape in order to create a curved text effect without also including the image on the page. You still need something to float, however, and so for this, we can use Generated Content.

上面的例子中,咱們將圖片展現在頁面中,並使得文本環繞着它彎曲。其實,你也能夠作到在不展現那張圖片的狀況的同時使用那張圖片的形狀做爲環繞路徑來得到一樣的效果。不過要作到這種效果,咱們仍然須要有一個浮動的元素,爲此,咱們能夠用生成的內容 (Generated Content;[譯註] 這裏指僞類) 來充當。

展開原文 In this example, we have inserted some generated content, floated it left, given it a width and a height and then used `shape-outside` with our image just as before. We then get a curved line against the whitespace, but no visible image.

在這個例子中,咱們經過插入生成的內容,並將其浮動到左側,給其設置寬度和高度,而後使用以前的圖片做爲 shape-outside 。這樣咱們就達到了在沒有可見的圖片的狀況下,仍然得到曲線性地圍繞空白區域的效果。

使用漸變做爲形狀

展開原文 A CSS gradient is just like an image, which means we can use a gradient to create a shape, which can make for some interesting effects. In this next example, I have created a gradient which goes from blue to transparent; your gradient will need to have a transparent or semi-transparent area in order to use shapes. Once again, I have used generated content to add the gradient and am then using the gradient in the value for `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 的值。

在漸變過分到全透明的地方,就會造成形狀,也是內容所環繞的邊界。

使用 shape-image-threshold 來支持環繞半透明圖片

展開原文 So far we have looked at using a completely transparent part of an image or of a gradient in order to create our shape, however, the third property defined in the CSS Shapes specification means that we can use images or gradients with semi-opaque areas by setting a threshold. A value for `shape-image-threshold` of `1` means fully opaque while `0` means fully transparent.

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 通道的非全透明的圖片,這個屬性的效果徹底同樣。

展開原文 This method of creating shapes from images and gradients is — I think — the most straightforward way of creating a shape. You can create a shape as complex as you need it to be, in the comfort of a graphics application and then use that to define the shape on your page. That said, there is another way to create our shapes, and that’s by using *Basic Shapes*.

上面這些建立形狀的方法,在我看來,是最直接的。你能夠經過先在圖像處理類軟件中按照你的須要建立任意複雜的形狀,而後在頁面中進行使用。其實我是想說還有另外一種方式建立形狀,那就是使用基礎形狀 (Basic Shapes) 。

用基礎形狀建立 CSS 形狀

展開原文 The Basic Shapes are a set of predefined shapes which cover a lot of different types of shapes you might want to create. To use a basic shape, you use the basic shape *type* as a value for `shape-outside`. This type uses functional notation, so we have the name of the shape followed by brackets (inside which are some values for our shape).

「基礎形狀」是一系列預約義的形狀,它包含了許多你可能想要建立的各種形狀。使用基礎形狀時,咱們使用的是基礎形狀的類型做爲 shape-outside 的值。這種類型使用函數形式來表示的,因此他們的名字的尾部會有一對括號 (括號裏面是一些關於咱們所需的形狀的值) 。

The options that you have are the following:

你可使用的形狀類型有如下這些:

  • inset()
  • circle()
  • ellipse()
  • polygon()
展開原文 We will take a look at the `circle()` type first as we can use this to understand some useful things which apply to all shapes which use the basic shape type. We will also have a look at the new tools in Firefox for inspecting these shapes.

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> (譯註:形狀的半徑),它能夠是一個長度值,也能夠是一個百分比。

展開原文 This is a really good to time have a look at the shape that has been created using the Firefox Shape Path Editor. You can inspect the shape by clicking on the generated content and then clicking the little shape icon next to the property `shape-outside`; your shape will now highlight.

如今就是咱們用 Firefox 的 Shape Path Editor 來查看一下這個形狀的好時機。點擊生成的內容,而後點擊其 shape-outside 屬性旁的圖標,就能夠將形狀高亮顯示出來。

The shape highlighted with a line

展開原文 You can see how the circle extends to the edge of the margin on our box. This is because the initial *reference box* used by our shape is `margin-box`. You already know something of reference boxes if you have ever added `box-sizing: border-box` to your CSS. When you do this, you are asking CSS to use the `border-box` and not the default `content-box` as the size of elements. In Shapes, we can also change which reference box is used. After any basic shape, add `border-box`to use the border to define the shape or `content-box` to use the edge of the content (inside the padding). For example:

你能夠看到,這個圓的範圍觸及到了外邊距的外邊緣上,這是由於咱們的形狀默認使用的參照盒子 (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。

A smaller circle is highlighted

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) ,會展現出它的各種參照盒子,據此你能夠選擇出特定形狀下效果最好的那個。

Highlights showing the margin, border and padding

circle() 的位置值

展開原文 A second value can be passed to `circle()` which is a position; if you do not pass this value, it defaults to `center`. However, you can use this value to pull your circle around. In the next example, I have positioned the circle by using `shape-outside(50% at 30%)`; this changes where the center of the circle is positioned.

circle() 中的第二個值表示的是位置,若是你不指定的話,默認爲 center。你能夠利用這個值來任意調整你的圓所在的位置。在接下來的例子中,我使用 shape-outside(50% at 30%) (譯註:這明顯是原文的筆誤,正確的是 circle(50% at 30%)) 來設置這個圓的位置,它調整的是這個圓的中心點所處的位置。

clip-path

展開原文 Something useful to know is that the same `` values can be used as a value for `clip-path`. This means that after creating a shape, you can clip away the image or background color that extends outside of the shape. In the example below, I am going to do this with our example gradient background, so that we end up with a circle that has text curved around from our square box.

一個有用的知識是,基礎形狀一樣可使用在 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.

本段講的這些,對咱們的其餘基礎形狀一樣適用。如今讓咱們來看下一他們是如何使用的。

INSET()

展開原文 The `inset()` value defines a rectangle. This might not seem very useful as a float is a rectangle, however, this value means that you can inset the content wrapping your shape. It takes four values for top, right, bottom, and left plus a final value which defines a border radius.

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) 來將內容從右側和底部內斂進來,在加上一個圓角半徑。如今,你能夠看到這些內容將如何覆蓋到盒子的背景顏色上:

ELLIPSE()

展開原文 An ellipse is a squashed circle and as such needs two radii for x and y (in that order). You can then push the ellipse around just as with circle using the position value. In the example below, I am creating an ellipse and then using clip-path with the same values to remove the content outside of my shape.

橢圓就是被壓扁了的圓,因此咱們須要有兩個半徑: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 屬性,爲的是演示如何配合使用這個屬性,將內容推開必定距離。

POLYGON()

展開原文 Creating polygon shapes gives us the most flexibility, as our shapes can be created with three or more points. The value passed to the polygon needs to be three or more pairs of values which represent coordinates.

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 中。

兼容性問題 (FALLBACKS)

展開原文 As CSS Shapes are applied to a float, in many cases the fallback is that instead of seeing the content wrap around a shape, the content will wrap around a floated element (in the way that content has always wrapped around floats). Browsers ignore properties they do not understand, so if they don’t understand Shapes, it doesn’t matter that the `shape-outside` property is there.

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 */
    }

}
複製代碼
展開原文 With Firefox releasing their support we now only have one main browser without support for Shapes — Edge. If you want to see Shapes support across the board you could go and [vote for the feature here](https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/6263716-shapes), and see if we can encourage the implementation of the feature in Edge.

隨着 Firefox 發佈了對形狀的支持,如今剩下惟一還不支持形狀的主流瀏覽器就是 Edge 了。若是你但願看到形狀廣受支持,你能夠前往這裏爲這個特性投一票

更多關於 CSS 形狀的信息

展開原文 In this article, I’ve tried to give a quick overview of some of the interesting things that are possible with CSS Shapes. For a more in-depth look at each feature, check out the [Guides to CSS Shapes](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Shapes) over at MDN. You can also read a [guide to the Shape Path Editor in Firefox](https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Edit_CSS_shapes).

在本文中,我試着對 CSS 形狀可能的用途作了一個概覽。關於每一個特性更詳細的信息,能夠查看 MDN 上的 Guides to CSS Shapes (CSS 形狀指導)。另外還能夠查看 guide to the Shape Path Editor in Firefox (Firefox 的 Shape Path Editor 使用指導) 。

相關文章
相關標籤/搜索