Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[译] [304] [#12] 切角效果 #11

Closed
cssmagic opened this issue Sep 16, 2015 · 1 comment
Closed

[译] [304] [#12] 切角效果 #11

cssmagic opened this issue Sep 16, 2015 · 1 comment

Comments

@cssmagic
Copy link
Owner


本文是早期译版,未经校审。仅供参考。


Cutout corners

切角效果

Prerequisites

  • CSS gradients
  • background-size
  • the {#secret-xxx}

背景知识

  • CSS 渐变
  • background-size
  • “{$secret$}” 攻略(第 {$page$} 页)

The problem

难题

Cutting corners is not just a way to save money, but also a rather popular style in both print and web design. It usually involves cutting out one or more of an element’s corners in a 45° angle (also known as beveled corners). Especially lately, with flat design winning over skeuomorphism, there has been an increase in the popularity of this effect. When the cutout corners are only on one side and occupy 50% of the element’s height each, it creates an arrow shape that is very popular for buttons and breadcrumb navigation -- see Figure XX.XX.

切角不仅是为了省钱,它还是一种非常流行的设计风格,不论是在印刷媒介还是在网页设计中都是如此。它最常见的形态是把元素的一个或多个角切成 45° 的缺口(也称作 斜面切角)。尤其是在最近,当扁平化设计的风头完全盖过拟物化之后,这种效果就越发流行了。当切角效果只应用在元素的某一侧,且切角的尺寸刚好达到元素高度的 50% 时,就会得到一个箭头形状,这在按钮和面包屑导航中的应用非常普遍——参见 图 3.23

图 3.23

FIGURE

A button with cutout corners, creating an arrow shape that emphasizes its meaning

一个使用了切角效果的按钮,箭头形状很好地强调了它自身的含义。

However, CSS is still not well equipped for creating this effect in an easy, straightforward one-liner. This leads most authors toward using background images to achieve it, either by obscuring the cutout corners with triangles (when the backdrop is a solid color), or by using one or more images for the entire background, with the corner(s) already cut.

但是,目前的 CSS 仍然无法做到只用一行简单直观的代码就生成这样的效果。这导致绝大多数网页开发者倾向于使用背景图片来达到目的,比如使用三角形盖住元素的顶角来模拟切角效果(假设此时网页背景是纯色),或者使用一张或多张已经切过角的图片来作为整个元素的背景。

图 3.24

FIGURE

An example of a website where a cutout corner (bottom-left of the semi-transparent “Find & Book” box) really adds to the design

以这个网站为例,它就在设计中运用到了切角效果(“Find & Book” 半透明区块的左下角)。

Such methods are clearly inflexible, difficult to maintain, and add latency, both by increasing HTTP requests and the total filesize of the website. Is there a better way?

这些方案显然都不够灵活,难以维护,而且增加了网页的加载时间——不仅增加了额外的 HTTP 请求,而且网页所需的文件体积也增加了。我们还有更好的方法吗?

The solution

解决方案

One solution comes in the form of the omnipotent CSS gradients. Let’s assume we only want one cutout corner, say the bottom-right one. The main trick is to take advantage of the fact that gradients can accept an angle direction (e.g., 45deg) and color stop positions in absolute lengths, both of which are not affected by changes in the dimensions of the element the background is on.

第一种方案来自于无所不能的 CSS 渐变。假设我们暂时只需要一个角被切掉的效果,就以右下角为例吧。这其中最大的窍门在于充分利用渐变的一大特性——渐变可以接受一个角度(比如 45deg)作为方向,而且色标的位置信息也可以是绝对的长度值,这一点丝毫不受容器尺寸的影响

Putting it all together, all we need is one linear gradient. It would need a transparent color stop for the cutout corner and another color stop in the same position, with the color we want for our background. The CSS looks like this (for a 15px size corner):

综合以上这些想法,我们只需要一个线性渐变就可以达到目标。这个渐变需要把一个透明色标放在切角处,然后在相同位置设置另一个色标,并且把它的颜色设置为我们想要的背景色。CSS 代码看起来是这样的(假设切角的深度是 15px):

background: #58a;
background:
    linear-gradient(-45deg, transparent 15px, #58a 0);

Simple, wasn’t it? You can see the result in Figure XX.XX. Technically, we don’t even need the first declaration. We only included it as a fallback: if CSS gradients are not supported, the second declaration will be dropped, so we still want to get at least a solid color background.

很简单,对吧?你可以在 图 3.25 中看到结果。事实上,第一行声明并不是必需的。我们加上它是把它作为回退机制:如果某些浏览器不支持 CSS 渐变,那第二行声明会被丢弃,而此时我们至少还能得到一个简单的实色背景。

图 3.25

FIGURE

An element with the bottom right corner cut off, through a simple CSS gradient

元素右下角的切角效果是由一幅简单的 CSS 渐变实现的。(图中文字为:嘿,别走神儿!你应该把注意力放在边角上,而不是放在文字上。这段文字只是用来充充场面而已。)

Now, let’s assume we want two cutout corners, say the two bottom ones. We can’t achieve this with only one gradient, so we will need two. Our first thought might be something like this:

现在,假设我们想要两个角被切掉的效果,比如以底部的两个角为例吧。我们只用一层渐变是无法做到这一点的,因此,我们得再加一层。我们最初的想法可能是这样的:

background: #58a;
background:
    linear-gradient(-45deg, transparent 15px, #58a 0),
    linear-gradient(45deg, transparent 15px, #655 0);

{小提示}

We are using separate colors (#58a and #655) for easier debugging. In practice, both gradients would be the same color.

我们为两层渐变使用了不同的颜色(#58a#655)以便更好地调试。在实际开发中,它们的颜色应该是相同的。


图 3.26

FIGURE

Failed attempt to apply the cutout effect to both bottom corners

尝试给底部的两个角设置切角样式,但失败了。

However, as you can see in Figure XX.XX, this doesn’t work. By default, both gradients occupy the entire element, so they obscure each other. We need to make them smaller, by using background-size to make each gradient occupy only half the element:

可是,我们在 图 3.26 中可以发现,这样写是行不通的。默认情况下,这两层渐变都会填满整个元素,因此它们会相互覆盖。需要让它们都缩小一些,于是我们使用 background-size 让每层渐变分别只占据整个元素一半的面积

background: #58a;
background:
    linear-gradient(-45deg, transparent 15px, #58a 0)
        right,
    linear-gradient(45deg, transparent 15px, #655 0)
        left;
background-size: 50% 100%;
图 3.27

FIGURE

background-size is not enough

光用 background-size 还是不够的。

You can see what happens in Figure XX.XX. As you can see, although background-size was applied, the gradients are still covering each other. The reason for this is that we forgot to turn background-repeat off, so each of our backgrounds is repeated twice. Therefore, our backgrounds are still obscuring each other -- by repetition this time. The new code would look like this:

我们可以在 图 3.27 中看到结果。如你所见,尽管我们已经用了 background-size,但这两层渐变仍然是相互覆盖的。原因在于,我们忘记把 background-repeat 给关掉了,因而每层渐变图案都各自平铺了两次。这导致我们的两层渐变背景仍然是相互覆盖的——只不过这次是因为背景平铺的关系。改进后的代码会是这样的:

background: #58a;
background:
    linear-gradient(-45deg, transparent 15px, #58a 0)
        right,
    linear-gradient(45deg, transparent 15px, #655 0)
        left;
background-size: 50% 100%;
background-repeat: no-repeat;
图 3.28

FIGURE

Our bottom-left and bottom-right cutout corners work now

左下角和右下角的切角效果终于实现了。

You can see the result in Figure XX.XX and verify that--finally--it works! At this point, you are probably able to figure out how to apply this effect to all four corners. You will need four gradients, and the code looks like this:

你可以在 图 3.28 中看最终效果——我们终于成功了!看到这里,你应该已经猜到怎样把四个角都做出切角效果了。你需要四层渐变图案,而代码如下所示:

background: #58a;
background:
    linear-gradient(135deg,  transparent 15px, #58a 0)
        top left,
    linear-gradient(-135deg, transparent 15px, #655 0)
        top right,
    linear-gradient(-45deg, transparent 15px, #58a 0)
        bottom right,
    linear-gradient(45deg, transparent 15px, #655 0)
        bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
图 3.29

FIGURE

The effect applied to all four corners, with four gradients

通过四层渐变图案,就可以给四个角都加上切角效果。

You can see the result in Figure XX.XX. One issue with the preceding code is that it’s not particularly maintainable. It requires five edits to change the background color and four to change the corner size. A preprocessor mixin could help reduce the repetition. Here’s how the code could look with SCSS:

你可以在 图 3.29 中看到结果。上面这段代码有一个问题,它的可维护性并不理想。我们在改变背景色时需要修改五处;而在改变切角尺寸时需要修改四处。使用预处理器的 mixin 可以帮助我们减少代码的重复度。如果用 SCSS 来写,代码会是这样的:

@mixin beveled-corners($bg,
         $tl:0, $tr:$tl, $br:$tl, $bl:$tr) {
    background: $bg;
    background:
        linear-gradient(135deg, transparent $tl, $bg 0)
            top left,
        linear-gradient(225deg, transparent $tr, $bg 0)
            top right,
        linear-gradient(-45deg, transparent $br, $bg 0)
            bottom right,
        linear-gradient(45deg, transparent $bl, $bg 0)
            bottom left;
    background-size: 50% 50%;
    background-repeat: no-repeat;
}

Then, where needed, it would be used like this, with 2–5 arguments:

然后,在需要的时候,我们就可以直接调用它,并传入 2~5 个参数:

@include beveled-corners(#58a, 15px, 5px);

In this example, the element we will get a 15px top-left and bottom-right cutout corner and a 5px top-right and bottom-left one, similar to how border-radius works when we provide fewer than four lengths. This is due to the fact that we provided default values for the arguments in our SCSS mixin, and yes, these default values can refer to other arguments as well.

在上面这行代码中中,元素的左上角和右下角会得到 15px 的切角效果,而右上角和左下角会得到 5px 的切角效果——如果我们提供的值少于四个时,它的行为跟 border-radius 属性是类似的。这归功于我们在 SCSS 的 mixin 中为各个参数指定了默认值,而且没错,这些默认值也可以引用其他参数的值。

{试一试} play.csssecrets.io/bevel-corners-gradients

Curved cutout corners

弧形切角

图 3.30

FIGURE

An excellent use of curved cutout corners in g2geogeske.com; the designer has made them the central design element, as they are present in the navigation, the content, and even the footer

g2geogeske.com 网站很好地驾驭了内凹圆角设计风格;设计师把它作为一种核心设计元素,因为内凹圆角不仅出现在导航中,还出现在内容中,甚至是页脚中。

A variation of the gradient method works to create curved cutout corners, an effect many people refer to as “inner border radius,” as it looks like an inverse version of rounded corners. The only difference is using radial gradients instead of linear ones:

上述渐变技巧还有一个变种,可以用来创建弧形切角(很多人也把这种效果称为 “内凹圆角”,因为它看起来就像是圆角的反向版本)。唯一的区别在于,我们会用径向渐变来替代上述线性渐变:

background: #58a;
background:
    radial-gradient(circle at top left,
             transparent 15px, #58a 0) top left,
    radial-gradient(circle at top right,
             transparent 15px, #58a 0) top right,
    radial-gradient(circle at bottom right,
             transparent 15px, #58a 0) bottom right,
    radial-gradient(circle at bottom left,
             transparent 15px, #58a 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;
图 3.31

FIGURE

Curved cutout corners, with radial gradients

使用径向渐变生成的内凹圆角效果。

You can see the result in Figure XX.XX. Just like in the previous technique, the corner size can be controlled through the color stop positions and a mixin would make the code more maintainable here as well.

你可以在 图 3.31 中看到效果。跟前一段所述的技巧类似,切角的大小可以通过色标的位置信息来控制,而且我们同样可以用一个 mixin 来改善这段代码的可维护性。

{试一试} play.csssecrets.io/scoop-corners

Inline SVG & border-image solution

内联 SVG 与 border-image 方案

While the gradient-based solution works, it has quite a few issues:

虽然基于渐变的方案是行之有效的,但也不是完全没有问题:

  • The code is very long and repetitive. In the common case, where we want the same corner size on all four corners, we need to make four edits to modify it. Similarly, we need to make four edits to modify the background color, five counting the fallback.
  • 它的代码还是非常繁琐冗长的。在常规设计中,四个角的切角尺寸往往是一致的,但我们在改变这个值时仍然需要修改四处。与此类似,我们在改变背景色的时候也需要修改四处,如果算上回退背景色的话就是五处。
  • It is messy to downright impossible (depending on the browser) to animate between different corner sizes.
  • 它的繁琐导致我们完全不可能(在某些浏览器下)让各个切角的尺寸以动画的方式发生变化。

Thankfully, there are a couple different methods we could use, depending on our needs. One of them is to use border-image with an inline SVG that generates the corners. Given how border-image works (if you don’t remember, take a look at the quick primer in Figure XX.XX), can you imagine how our SVG would look?

谢天谢地,我们还有其他一些方法可供选择,具体采用哪种方法取决于实际需求。其中之一就是使用 border-image,并通过一个内联的 SVG 图像来产生切角效果。基于 border-image 的工作原理(如果对此有些淡忘了,不妨回头看看 图 3.32 所作的科普),你能想像出这个 SVG 图像是什么样子吗?

Because dimensions don’t matter (border-image takes care of scaling and SVGs scale perfectly regardless of dimensons -- ah, the joy of vector graphics!), every measurement could be 1, for easier, shorter, numbers. The corners would be of length 1, and the straight edges would also be 1. The result (zoomed) would look like Figure XX.XX. The code would look like this:

由于尺寸完全不是一个问题(border-image 会解决缩放问题,而 SVG 可以做到与尺寸完全无关的完美缩放——这就是矢量图的好处啦!),每个切片的尺寸都可以设置为 1,以便理解和书写。切角的尺寸也是 1,直线边缘也都是 1。它的(
缩放大后的)样子会是 图 3.32 这样的。而相应的代码可能是这样的:

border: 15px solid transparent;
border-image: 1 url('data:image/svg+xml,\
    <svg xmlns="http://www.w3.org/2000/svg"
         width="3" height="3" fill="%2358a">\
    <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
    </svg>');
图 3.32

FIGURE

Our SVG-based border image, with its slicing

边框图像是基于 SVG 的,切割线也标示出来了。

Note that we used a slice size of 1. This does not mean 1 pixel; it is referring to the coordinate system of the SVG file (hence the lack of units). If we had specified it in percentages, we would need to approximate {1 \over 3} of the image with something like 33.34%. Approximating numbers is always risky, because not all browsers use the same level of precision. However, by using units of the coordinate system of the SVG file, we’re saved from precision headaches.

请注意,我们使用的切片尺寸是 1。这并不表示 1 个像素;它所对应的是 SVG 文件的坐标系统(因此不需要单位)。如果我们用百分比来指定这些长度,就只能采用 33.34% 这样的值来近似地获得图像尺寸的三分之一。近似值总是有风险的,因为不是所有的浏览器都使用同等级别的计算精度。但如果使用 SVG 文件的坐标系统作为度量单位,我们就不用掉这个坑了。

The result is shown in Figure XX.XX. As you can see, our cutout corners are there, but there is no background. We can solve that in two ways: either by specifying a background, or by adding the keyword fill to our border-image declaration, so that it doesn’t discard the middle slice. In this case, we are going to go with specifying a background, because it will also act as a fallback.

它的效果展示在 图 3.33 中。如你所见,我们的切角效果出来了,但还缺少整片背景。我们有两种办法可以解决这个问题:要么提供一个背景色,要么给 border-image 属性值加上 fill 关键字——这样它就不会丢掉 SVG 中央的那个切片了。在这个例子中,我们决定指定一个背景色,因为它还可以发挥回退的作用

图 3.33

FIGURE

Applying our SVG on the border-image property

把我们的 SVG 应用到 border-image 属性中。

In addition, you may have noticed that our corners are smaller than with the previous technique, which can be baffling. But we specified a 15px border width! The reason is that with the gradient, the 15px was along the gradient line, which is perpendicular to the direction of the gradient. The border width, however, is not measured diagonally, but horizontally/vertically. Can you see where this is going? Yup, it’s the ubiquitous Pythagorean theorem again, that we also saw in the {#secret-xxx}. Figure XX.XX should help make things clearer. Long story short, to achieve the same size, we need to use a border width that is \sqrt{2} times larger than the size we would use with the gradient method. In this case, that would be 15 \times \sqrt{2} \approx 21.213203436 pixels, which is sensible to approximate to 20px, unless we really, absolutely need the diagonal size to be as close to 15px as possible:

这里插一句,你可能已经注意到了,我们的切角跟前面的技巧相比要小一些,这令人有些困惑。我们明明已经指定 15px 作为边框宽度了呀!其实原因在于,在渐变中,这个 15px 是沿着渐变轴来度量的,它的方向是跟渐变推进的方向是一致的。而边框宽度,是以斜边的方式来度量的,而不是水平或垂直方向。你能看出它们的差别吗?对,我们又要请出万能的勾股定理了,我们在 “{$secret$}” 攻略(第 {$page$} 页)中就已经见过它了。图 3.34 应该可以很好的解释这个问题。简而言之,为了得到相同的尺寸,我们需要把渐变中的尺寸拿来,再乘以 \sqrt{2} 倍,然后才能用在边框宽度属性中。在这个例子中,它实际上就是 15 \times \sqrt{2} \approx 21.213203436 像素,我们取个近似值 20px 就可以了,除非我们真的、绝对要求斜边尺寸尽最大可能严格接近 15px

border: 20px solid transparent;
border-image: 1 url('data:image/svg+xml,\
    <svg xmlns="http://www.w3.org/2000/svg"
         width="3" height="3" fill="%2358a">\
    <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
    </svg>');
background: #58a;
图 3.34

FIGURE

Specifying a border-width of 15px, results in a (diagonally measured) corner size of {15 \over \sqrt{2}} \approx 10.606601718, which is why our corners looked smaller

border-width 指定为 15px,所产生的切角尺寸(斜向度量结果)为 {15 \over \sqrt{2}} \approx 10.606601718,这就是为什么它比前面的切角看起来稍小一些。

However, as you can see in Figure XX.XX, this doesn’t exactly have the expected result. Where did our laboriously created cutout corners go? Fear not, young padawan, for our corners are still there. You can understand what’s happening if you set the background to a different color, such as #655.

但是,我们在 图 3.35 中会发现,这实际上并没有得到我们期望的效果。我费尽周折创建的切角效果去哪儿了啊?别担心,年轻人,我们的切角其实就在那儿。如果你把背景设置为另一种颜色,比如 #655,就会比较容易理解事情的真相了。

图 3.35

FIGURE

Where did our nice corners go?!

我们美美的切角效果跑到哪儿去了?!

As you can see in Figure XX.XX, the reason our corners disappeared was that the background we specified was obscuring them. All we need to do to fix this is to use background-clip to prevent the background from extending to the border area:

图 3.36 所示,原来这是因为背景色和切角边框混成一团了。我们接下来做的就是请出 background-clip 来修复这个问题,避免背景色蔓延到边框区域:

border: 20px solid transparent;
border-image: 1 url('data:image/svg+xml,\
    <svg xmlns="http://www.w3.org/2000/svg"\
         width="3" height="3" fill="%2358a">\
    <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
    </svg>');
background: #58a;
background-clip: padding-box;
图 3.36

FIGURE

Changing our background to another color solves the ...disappearing corners mystery

把背景色设置为另一种颜色,终于解开了 “切角消失” 的谜团。

The issue is now fixed and our box now looks exactly like Figure XX.XX. However, we can easily change the corner size in only one place: we just modify the border width. We can even animate it, because border-width is animatable! We can also change the background with only two edits instead of five. In addition, because our background is now independent of the corner effect, we can even specify a gradient on it, or any other pattern, as long as it’s still #58a toward the edges. For example, check out Figure XX.XX for an example using a radial gradient from hsla(0,0%,100%,.2) to transparent.

这样一来,问题就解决了,我们的容器现在看起来完全就是 图 3.29 中的效果。终于,我们做到了在改变切角尺寸时只改一处:我们只需要修改边框宽度就可以了。我们甚至可以给它加上动画,因为 border-width 属性是支持动画的!我们还做到了在改变背景时只改两处,而不是五处。此外,由于背景效果跟切角效果是相互独立的,我们甚至可以把背景设置为一层渐变图案,或者其他图案——来看看 图 3.37 这个例子吧,它就使用了一幅由 hsla(0,0%,100%,.2) 过渡到 transparent 的径向渐变图案。

图 3.37

FIGURE

Our cutout corners with a radial gradient background

切角与径向渐变背景组合之后的效果。

There is only one small issue remaining. If border-image is not supported, the fallback is not only the absence of corners. Due to background clipping, it also looks like there is less spacing between the box edge and its content. To fix that, we could just give our border a color that is identical to the background:

我们只剩下最后一个小问题了。在不支持 border-image 的环境下,回退的结果就不仅是没有切角效果了。由于背景裁切的关系,它看起来好像在容器的边缘和内容之间缺了一圈空隙。为了修复这个问题,我们可以给边框指定跟背景一致的颜色:

border: 20px solid #58a;
border-image: 1 url('data:image/svg+xml,\
    <svg xmlns="http://www.w3.org/2000/svg"\
         width="3" height="3" fill="%2358a">\
    <polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\
    </svg>');
background: #58a;
background-clip: padding-box;

This color is ignored when border-image applies, but will provide a more graceful fallback when it doesn’t, which will look like Figure XX.XX. As a drawback, this increases the number of edits we need to make to change the background color to three.

border-image 属性生效时,这个边框色就会被忽略;但当 border-image 不支持时,边框色就可以提供一个更加平稳的回退措施,此时的结果就是 图 3.35 的样子。不过随之来而的一个缺点就是,当我们改变背景色时所要修改的地方会增加到三处

{试一试} play.csssecrets.io/bevel-corners


{致敬}

Hat tip to Martijn Saly for coming up with the initial idea of using border-image and inline SVG as a solution for beveled corners, in a tweet of his from January 5, 2015.

Martijn Saly 脱帽致敬,感谢他在 2015 年 1 月 5 日的一条推文 中首次提出用 border-image 和内联 SVG 实现斜面切角的创意。

Clipping path solution

裁切路径方案

{警告!!} 不完全支持

While the border-image solution is very compact and relatively DRY, it still has its limitations. For example, we still need to have either a solid color background, or a background that is a solid color toward the edges. What if we want a different kind of background, such as a texture, a pattern, or a linear gradient?

前面所述的 border-image 方案确实非常紧凑,也比较 DRY,但它还是存在一些局限。举个例子,我们要么得指定某个实色的背景,要么得指定一个边缘接近某个实色的背景图案。假如我们想设置其他类型的背景(比如纹理、平铺图案或一道线性渐变),又该如何?

There is another way that doesn’t have these limitations, though it of course has other limitations of its own. Remember the clip-path property from the {#secret-xxx}? The amazing thing about CSS clipping paths is that we can mix percentages (which refer to the element dimensions) with absolute lengths, offering us tremendous flexibility.

还有另外一种方法不存在这种局限,但也有着它自已独有的局限。还记得我们在 **“{$secret$}” 攻略(第 {$page$} 页)**中用到的 clip-path 属性吗?CSS 裁切路径最神奇的地方在于我们可以同时使用百分比数值(它会以元素自身的宽高作为基数度进行换算)和绝对长度值,从而提供巨大的灵活性。

For example, the code for the clipping path to clip an element in a rectangle with beveled corners of 20px size (measured horizontally) would look like this:

举个例子,如果用裁切路径来给一个元素切出 20px 大小(以水平方向度量)的斜面切角,它的代码可能就是这个样子的:

background: #58a;
clip-path: polygon(
    20px 0, calc(100% - 20px) 0, 100% 20px,
    100% calc(100% - 20px), calc(100% - 20px) 100%,
    20px 100%, 0 calc(100% - 20px), 0 20px
);

Despite the code being short, this doesn’t mean it’s DRY, which is one of its biggest issues if you’re not using a preprocessor. In fact, it’s the most WET of the pure CSS solutions we presented, with eight (!) edits required to change the corner size. On the other hand, we can change the background in only one place, so there’s that.

尽管这种方法的代码确实短了很多,但这并不意味着它是 DRY 的,如果你不用预处理器,这就是它最大的缺陷。实际上,它是本节所述的所有纯 CSS 方案中最不 DRY 的,因为如果要改动切角的尺寸,我们需要修改八处!不过另一方面,改变背景倒是变得比较方便,只需修改一处即可。

Among its benefits is that we can have any background we want, or even clip replaced elements such as images. Check out Figure XX.XX for an image styled with beveled corners. None of the previous methods can do this. In addition, it is also animatable, not only to different corner sizes, but different shapes altogether. All we need to do is use a different clipping path.

这个方法最大的好处在于,我们可以使用任意类型的背景,甚至还可以对替换元素(比如图片)进行裁切。来看看 图 3.38 这个例子,它给一张图片设置了斜面切角样式。

图 3.38

FIGURE

An image styled with beveled corners, via clip-path

运用 clip-path 属性给一张图片设置斜面切角样式。

Beyond its WETness and its limited browser support, it also has the drawback that it will clip text, if there is no sufficient padding, as it just clips the element without distinguishing between its parts. In contrast, the gradient method will just let the text overflow beyond the corners (because they’re just a background) and the border-image method will act just like a border and make the text wrap.

暂且不提代码不够 DRY 以及浏览器支持程度上的不足,它还有一个更大的缺点,就是当内边距的不够宽时,它会裁切掉文本,因为它只能对元素做统一的裁切,并不能区分元素的各个部分。与此不同的是,渐变方案允许文字溢出并超出切角区域(因为它只是背景图案);而 border-image 方案则会起到普通边框的作用,令文字折行。

{试一试} play.csssecrets.io/bevel-corners-clipped


{关于未来}

切角效果

In the future, we won’t have to resort to CSS gradients, clipping, or SVG for this effect. A new property, corner-shape, is coming in CSS Backgrounds & Borders Level 4 to save us from these pains. It will be used in conjunction with border-radius to produce cutout corners of different shapes, with their sizes defined in border-radius. For example, specifying 15px cutout corners on all sides would be as simple as:

在未来,我们再也不需要费尽心机地动用 CSS 渐变、裁切或 SVG 来实现这个效果了。CSS 背景与边框(第四版)将引入一个全新的属性 corner-shape,可以彻底解决这个痛点。这个属性需要跟 border-radius 配合使用,从而产生各种不同形状的切角效果,而切角的尺寸正是 border-radius 的值。举例来说,为容器的四个角指定 15px 的斜面切角就是如此简单:

border-radius: 15px;
corner-shape: bevel;

Related specs

相关规范

@2ming
Copy link

2ming commented Jan 14, 2016

无所不能的渐变,第一次学到这种用法,真是大开眼界... 等书

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants