使用 CSS 切角

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7324722/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 01:32:34  来源:igfitidea点击:

Cut Corners using CSS

csscss-shapes

提问by Rixius

I'm looking to "cut" the top left corner of a div, like if you had folded the corner of a page down.

我希望“剪切” div 的左上角,就像您将页面的一角向下折叠一样。

I'd like to do it in pure CSS, are there any methods?

我想用纯 CSS 来做,有什么方法吗?

回答by Joseph Silber

If the parent element has a solid color background, you can use pseudo-elements to create the effect:

如果父元素具有纯色背景,则可以使用伪元素来创建效果:

div {
    height: 300px;
    background: red;
    position: relative;
}

div:before {
    content: '';
    position: absolute;
    top: 0; right: 0;
    border-top: 80px solid white;
    border-left: 80px solid red;
    width: 0;
}
<div></div>

http://jsfiddle.net/2bZAW/

http://jsfiddle.net/2bZAW/



P.S.The upcoming border-corner-shapeis exactly what you're looking for. Too bad it might get cut out of the spec, and never make it into any browsers in the wild :(

PS即将到来border-corner-shape的正是你正在寻找的。太糟糕了,它可能会被从规范中剔除,并且永远不会在野外使用任何浏览器:(

回答by web-tiki

If you need a transparent cut out edge, you can use a rotated pseudo element as a background for the divand position it to cut out the desired corner:

如果您需要一个透明的切出边缘,您可以使用一个旋转的伪元素作为 的背景div并将其定位以切出所需的角:

Transprent cut out edge on a div

div 上的透明切出边缘

body {
  background: url(http://i.imgur.com/k8BtMvj.jpg);
  background-size: cover;
}
div {
  position: relative;
  width: 50%;
  margin: 0 auto;
  overflow: hidden;
  padding: 20px;
  text-align: center;
}
div:after {
  content: '';
  position: absolute;
  width: 1100%; height: 1100%;
  top: 20px; right: -500%;
  background: rgba(255,255,255,.8);
  transform-origin: 54% 0;
  transform: rotate(45deg);
  z-index: -1;
}
<div>
  ... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>
</div>

Note that this solution uses transforms and you need to add the required vendor prefixes. For more info see canIuse.

请注意,此解决方案使用转换,您需要添加所需的供应商前缀。有关更多信息,请参阅canIuse

To cut the bottom right edge, you can change the top, transform and transform-origin properties of the pseudo element to:

剪切右下边缘,您可以将伪元素的 top、transform 和 transform-origin 属性更改为:

body {
  background: url(http://i.imgur.com/k8BtMvj.jpg);
  background-size: cover;
}
div {
  position: relative;
  width: 50%;
  margin: 0 auto;
  overflow: hidden;
  padding: 20px;
  text-align: center;
}
div:after {
  content: '';
  position: absolute;
  width: 1100%; height: 1100%;
  bottom: 20px; right: -500%;
  background: rgba(255,255,255,.8);
  transform-origin: 54% 100%;
  transform: rotate(-45deg);
  z-index: -1;
}
<div>
  ... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>... content ...<br/>
</div>

回答by Stewartside

CSS Clip-Path

CSS 剪辑路径

Using a clip-pathis a new, up and coming alternative. Its starting to get supported more and more and is now becoming well documented. Since it uses SVG to create the shape, it is responsive straight out of the box.

使用剪辑路径是一种新的、即将到来的替代方案。它开始得到越来越多的支持,并且现在变得有据可查。由于它使用 SVG 来创建形状,因此它开箱即用。

div {
  width: 200px;
  min-height: 200px;
  -webkit-clip-path: polygon(0 0, 0 100%, 100% 100%, 100% 25%, 75% 0);
  clip-path: polygon(0 0, 0 100%, 100% 100%, 100% 25%, 75% 0);
  background: lightblue;
}
<div>
  <p>Some Text</p>
</div>

CSS Transform

CSS 转换

I have an alternative to web-tiki's transform answer.

我有一个替代 web-tiki 的转换答案。

body {
  background: lightgreen;
}
div {
  width: 200px;
  height: 200px;
  background: transparent;
  position: relative;
  overflow: hidden;
}
div.bg {
  width: 200%;
  height: 200%;
  background: lightblue;
  position: absolute;
  top: 0;
  left: -75%;
  transform-origin: 50% 50%;
  transform: rotate(45deg);
  z-index: -1;
}
<div>
  <div class="bg"></div>
  <p>Some Text</p>
</div>

回答by Harry

Here is another approach using CSS transform: skew(45deg)to produce the cut corner effect. The shape itself involves three elements (1 real and 2 pseudo-elements) as follows:

这是使用 CSStransform: skew(45deg)产生切角效果的另一种方法。形状本身涉及三个元素(1 个实元素和 2 个伪元素),如下所示:

  • The main container divelement has overflow: hiddenand produces the left border.
  • The :beforepseudo-element which is 20% the height of the parent container and has a skew transform applied to it. This element prodcues the border on the top and cut (slanted) border on the right side.
  • The :afterpseudo-element which is 80% the height of the parent (basically, remaining height) and produces the bottom border, the remaining portion of the right border.
  • 主容器div元素具有overflow: hidden并产生左边框。
  • 所述:before伪元件,其是20%的父容器的高度,并且具有偏斜变换施加到其上。此元素在顶部产生边框并在右侧切割(倾斜)边框。
  • 所述:after伪元件,其是80%的母体(基本上,剩余高度)的高度,并产生下边框,右边框的剩余部分。

The output produced is responsive, produces a transparent cut at the top and supports transparent backgrounds.

产生的输出是响应式的,在顶部产生透明切口并支持透明背景。

div {
  position: relative;
  height: 100px;
  width: 200px;
  border-left: 2px solid beige;
  overflow: hidden;
}
div:after,
div:before {
  position: absolute;
  content: '';
  width: calc(100% - 2px);
  left: 0px;
  z-index: -1;
}
div:before {
  height: 20%;
  top: 0px;
  border: 2px solid beige;
  border-width: 2px 3px 0px 0px;
  transform: skew(45deg);
  transform-origin: right bottom;
}
div:after {
  height: calc(80% - 4px);
  bottom: 0px;
  border: 2px solid beige;
  border-width: 0px 2px 2px 0px;
}
.filled:before, .filled:after {
  background-color: beige;
}

/* Just for demo */

div {
  float: left;
  color: beige;
  padding: 10px;
  transition: all 1s;
  margin: 10px;
}
div:hover {
  height: 200px;
  width: 300px;
}
div.filled{
  color: black;
}
body{
 background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<div class="cut-corner">Some content</div>
<div class="cut-corner filled">Some content</div>

enter image description here

在此处输入图片说明



The below is another method to produce the cut corner effect by using linear-gradientbackground images. A combination of 3 gradient images (given below) is used:

下面是另一种使用linear-gradient背景图像产生切角效果的方法。使用了 3 张渐变图像(如下所示)的组合:

  • One linear gradient (angled towards bottom left) to produce the cut corner effect. This gradient has a fixed 25px x 25px size.
  • One linear gradient to provide a solid color to the left of the triangle that causes the cut effect. A gradient is used even though it produces a solid color because we can control size, position of background only when images or gradients are used. This gradient is positioned at -25px on X-axis (basically meaning it would end before the place where the cut is present).
  • Another gradient similar to the above which again produces a solid color but is positioned at 25px down on the Y-axis (again to leave out the cut area).
  • 一个线性渐变(向左下角倾斜)以产生切角效果。此渐变具有固定的 25px x 25px 大小。
  • 一种线性渐变,用于在三角形左侧提供纯色,从而产生剪切效果。即使它产生纯色,也会使用渐变,因为只有在使用图像或渐变时我们才能控制背景的大小和位置。此渐变位于 X 轴上的 -25px(基本上意味着它会在切割出现的位置之前结束)。
  • 另一个类似于上面的渐变,它再次产生纯色,但位于 Y 轴向下 25 像素处(再次省略切割区域)。

The output produced is responsive, produces transparent cut and doesn't require any extra elements (real or pseudo). The drawback is that this approach would work only when the background (fill) is a solid color and it is very difficult to produce borders (but still possible as seen in the snippet).

产生的输出是响应式的,产生透明的剪切并且不需要任何额外的元素(真实的或伪的)。缺点是这种方法仅在背景(填充)是纯色时才有效,并且很难生成边框(但仍然可以在代码段中看到)。

.cut-corner {
  height: 100px;
  width: 200px;
  background-image: linear-gradient(to bottom left, transparent 50%, beige 50%), linear-gradient(beige, beige), linear-gradient(beige, beige);
  background-size: 25px 25px, 100% 100%, 100% 100%;
  background-position: 100% 0%, -25px 0%, 100% 25px;
  background-repeat: no-repeat;
}
.filled {
  background-image: linear-gradient(black, black), linear-gradient(black, black), linear-gradient(black, black), linear-gradient(black, black), linear-gradient(to bottom left, transparent calc(50% - 1px), black calc(50% - 1px), black calc(50% + 1px), beige calc(50% + 1px)), linear-gradient(beige, beige), linear-gradient(beige, beige);
  background-size: 2px 100%, 2px 100%, 100% 2px, 100% 2px, 25px 25px, 100% 100%, 100% 100%;
  background-position: 0% 0%, 100% 25px, -25px 0%, 0px 100%, 100% 0%, -25px 0%, 100% 25px;
}

/* Just for demo */

*{
  box-sizing: border-box;
  }
div {
  float: left;
  color: black;
  padding: 10px;
  transition: all 1s;
  margin: 10px;
}
div:hover {
  height: 200px;
  width: 300px;
}
body{
 background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<div class="cut-corner">Some content</div>
<div class="cut-corner filled">Some content</div>

enter image description here

在此处输入图片说明

回答by Nate

You could use linear-gradient. Let's say the parent divhad a background image, and you needed a divto sit on top of that with a gray background and a dog-eared left corner. You could do something like this:

你可以使用linear-gradient. 假设父母div有一个背景图片,你需要一个div坐在上面的灰色背景和一个狗耳朵的左角。你可以这样做:

.parent-div { background: url('/image.jpg'); }
.child-div { 
   background: #333;
   background: linear-gradient(135deg, transparent 30px, #333 0);
}

See it on CodePen

在 CodePen 上查看

Further reading:

进一步阅读:

回答by RemBem

If you need a diagonal border instead of a diagonal corner, you can stack 2 divs with each a pseudo element:

如果你需要一个对角边框而不是一个对角角,你可以用一个伪元素堆叠 2 个 div:

DEMO

演示

http://codepen.io/remcokalf/pen/BNxLMJ

http://codepen.io/remcokalf/pen/BNxLMJ

.container {
  padding: 100px 200px;
  overflow: hidden;
}

div.diagonal {
  background: #da1d00;
  color: #fff;
  font-family: Arial, Helvetica, sans-serif;
  width: 300px;
  height: 300px;
  padding: 70px;
  position: relative;
  margin: 30px;
  float: left;
}

div.diagonal2 {
  background: #da1d00;
  color: #fff;
  font-family: Arial, Helvetica, sans-serif;
  width: 300px;
  height: 300px;
  padding: 70px;
  position: relative;
  margin: 30px;
  background: #da1d00 url(http://www.remcokalf.nl/background.jpg) left top;
  background-size: cover;
  float: left;
}

div.diagonal3 {
  background: #da1d00;
  color: #da1d00;
  font-family: Arial, Helvetica, sans-serif;
  width: 432px;
  height: 432px;
  padding: 4px;
  position: relative;
  margin: 30px;
  float: left;
}

div.inside {
  background: #fff;
  color: #da1d00;
  font-family: Arial, Helvetica, sans-serif;
  width: 292px;
  height: 292px;
  padding: 70px;
  position: relative;
}

div.diagonal:before,
div.diagonal2:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border-top: 80px solid #fff;
  border-right: 80px solid transparent;
  width: 0;
}

div.diagonal3:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border-top: 80px solid #da1d00;
  border-right: 80px solid transparent;
  width: 0;
  z-index: 1;
}

div.inside:before {
  content: '';
  position: absolute;
  top: -4px;
  left: -4px;
  border-top: 74px solid #fff;
  border-right: 74px solid transparent;
  width: 0;
  z-index: 2;
}

h2 {
  font-size: 30px;
  line-height: 1.3em;
  margin-bottom: 1em;
  position: relative;
  z-index: 1000;
}

p {
  font-size: 16px;
  line-height: 1.6em;
  margin-bottom: 1.8em;
}

#grey {
  width: 100%;
  height: 400px;
  background: #ccc;
  position: relative;
  margin-top: 100px;
}

#grey:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  border-top: 80px solid #fff;
  border-right: 80px solid #ccc;
  width: 400px;
}
<div id="grey"></div>
<div class="container">
  <div class="diagonal">
    <h2>Header title</h2>
    <p>Yes a CSS diagonal corner is possible</p>
  </div>
  <div class="diagonal2">
    <h2>Header title</h2>
    <p>Yes a CSS diagonal corner with background image is possible</p>
  </div>
  <div class="diagonal3">
    <div class="inside">
      <h2>Header title</h2>
      <p>Yes a CSS diagonal border is even possible with an extra div</p>
    </div>
  </div>
</div>

回答by Sviatoslav Oleksiv

This code allows you to cut corners on each side of the rectangle:

此代码允许您在矩形的每一侧切角:

div {
  display:block;
  height: 300px;
  width: 200px;
  background: url('http://lorempixel.com/180/290/') no-repeat;
  background-size:cover;

  -webkit-clip-path: polygon(10px 0%, calc(100% - 10px) 0%, 100% 10px, 100% calc(100% - 10px), calc(100% - 10px) 100%, 10px 100%, 0% calc(100% - 10px), 0% 10px);
  clip-path: polygon(10px 0%, calc(100% - 10px) 0%, 100% 10px, 100% calc(100% - 10px), calc(100% - 10px) 100%, 10px 100%, 0% calc(100% - 10px), 0% 10px);
}

http://jsfiddle.net/2bZAW/5552/

http://jsfiddle.net/2bZAW/5552/

enter image description here

在此处输入图片说明

回答by hakJav

With a small edit to Joseph's code, the element does not require a solid background:

对 Joseph 的代码稍作修改,该元素不需要纯色背景:

div {
    height: 300px;
    background: url('http://images2.layoutsparks.com/1/190037/serene-nature-scenery-blue.jpg');
    position: relative;
}

div:before {
    content: '';
    position: absolute;
    top: 0; right: 0;
    border-top: 80px solid white;
    border-left: 80px solid rgba(0,0,0,0);
    width: 0;
}

http://jsfiddle.net/2bZAW/1921/

http://jsfiddle.net/2bZAW/1921/

This use of 'rgba(0,0,0,0)' allows the inner 'corner' to be invisible .

' rgba(0,0,0,0)' 的这种使用允许内部的“角落”不可见。

You can also edit the 4th parameter 'a', where 0 < a < 1, to have a shadow for more of a 'folded-corner' effect:

您还可以编辑第 4 个参数 'a',其中0 < a < 1,以获得更多“折叠角”效果的阴影:

http://jsfiddle.net/2bZAW/1922/(with shadow)

http://jsfiddle.net/2bZAW/1922/(带阴影)



NOTE:RGBA color values are supported in IE9+, Firefox 3+, Chrome, Safari, and in Opera 10+.

注意:IE9+、Firefox 3+、Chrome、Safari 和 Opera 10+ 支持 RGBA 颜色值。

回答by Simon Franzen

We had the problem of different background colors for our cutted elements. And we only wanted upper right und bottom left corner.

我们遇到了切割元素背景颜色不同的问题。我们只想要右上角和左下角。

enter image description here

在此处输入图片说明

body {
 background-color: rgba(0,0,0,0.3)
 
}

.box {
 position: relative;
 display: block;
 background: blue;
 text-align: center;
 color: white;
 padding: 15px;
 margin: 50px;
}

.box:before,
.box:after {
 content: "";
 position: absolute;
 left: 0; 
 right: 0;
 bottom: 100%;
 border-bottom: 15px solid blue;
 border-left: 15px solid transparent;
 border-right: 15px solid transparent;
}

.box:before{
 border-left: 15px solid blue;
}

.box:after{
 border-right: 15px solid blue;
}

.box:after {
 bottom: auto;
 top: 100%;
 border-bottom: none;
 border-top: 15px solid blue;
}


/* Active box */
.box.active{
 background: white;
 color: black;
}



.active:before,
.active:after {
 border-bottom: 15px solid white;
}

.active:before{
 border-left: 15px solid white;
}

.active:after{
 border-right: 15px solid white;
}

.active:after {
 border-bottom: none;
 border-top: 15px solid white;
}
<div class="box">
 Some text goes here. Some text goes here. Some text goes here. Some text goes here.<br/>Some text goes here.<br/>Some text goes here.<br/>Some text goes here.<br/>Some text goes here.<br/>Some text goes here.<br/>
</div>
<div class="box">
 Some text goes here.
</div>
<div class="box active">
 Some text goes here.
 <span class="border-bottom"></span>
</div>
<div class="box">
 Some text goes here.
</div>

回答by Kiwad

According to Harry's linear-gradient solution (answered Oct 14 '15 at 9:55), it says that opacity background isn't possible, I tried it and yep, it isn't.

根据 Harry 的线性梯度解决方案(2015 年 10 月 14 日 9:55 回答),它说不透明背景是不可能的,我试过了,是的,它不是。

But! I found a workaround. No it's not super optimised, but it worked. So here's my solution. Since Harry doesn't use pseudo element, we can achieve this by creating one.

但!我找到了一个解决方法。不,它不是超级优化,但它有效。所以这是我的解决方案。由于 Harry 不使用伪元素,我们可以通过创建一个来实现这一点。

Set position relative to the container and create a pseudo element with the same linear-gradient properties. In other words, just clone it. Then put a transparent background for the container, and lets say a black background for the clone. Put a position absolute on it, a z-index of -1 and an opacity value (ie. 50%). It will do the job. Again it's a workaround and it's not perfect but it works just fine.

设置相对于容器的位置并创建一个具有相同线性渐变属性的伪元素。换句话说,只需克隆它。然后为容器放置一个透明背景,让克隆为黑色背景。在其上放置绝对位置,z-index 为 -1 和不透明度值(即 50%)。它会完成这项工作。同样,这是一种解决方法,它并不完美,但效果很好。

.cut-corner {
    position: relative;
    color: white;
    background-repeat: no-repeat;
    background-image: linear-gradient(white, white), linear-gradient(white, white), linear-gradient(white, white), linear-gradient(white, white), linear-gradient(to bottom left, transparent calc(50% - 1px), white calc(50% - 1px), white calc(50% + 1px), transparent calc(50% + 1px)), linear-gradient(transparent, transparent), linear-gradient(transparent, transparent);
    background-size: 2px 100%, 2px 100%, 100% 2px, 100% 2px, 25px 25px, 100% 100%, 100% 100%;
    background-position: 0% 0%, 100% 25px, -25px 0%, 0px 100%, 100% 0%, -25px 0%, 100% 25px;
}
.cut-corner:after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    right: 0;
    top: 0;
    z-index: -1;
    opacity: 0.5;
    background-repeat: no-repeat;
    background-image: linear-gradient(white, white), linear-gradient(white, white), linear-gradient(white, white), linear-gradient(white, white), linear-gradient(to bottom left, transparent calc(50% - 1px), white calc(50% - 1px), white calc(50% + 1px), black calc(50% + 1px)), linear-gradient(black, black), linear-gradient(black, black);
    background-size: 2px 100%, 2px 100%, 100% 2px, 100% 2px, 25px 25px, 100% 100%, 100% 100%;
    background-position: 0% 0%, 100% 25px, -25px 0%, 0px 100%, 100% 0%, -25px 0%, 100% 25px;
}

/* Just for demo */

div {
  padding: 10px;
}
body{
 background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<div class="cut-corner">
  Some content<br>
  Some content<br>
  Some content<br>
  Some content  
</div>