带边框和透明间隙的CSS三角形切口 [英] CSS triangular cutout with border and transparent gap

查看:64
本文介绍了带边框和透明间隙的CSS三角形切口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用CSS作为页面各部分之间的分隔符来绘制以下模式:

I need to draw the following pattern with CSS as a separator between sections of my page:

使用此答案中的skewX()技术,我能够准确地模拟三角形切口(两个伪元素被附加到下部的顶部,向左倾斜,向右倾斜,以便上部的背景显示完整):

Using the skewX() technique from this answer, I was able to mimic the triangular cutout accurately (two pseudo-elements are appended to the top of the lower section, one skewed left and one skewed right, so that the background of the upper section shows through):

但是我不知道如何添加边框,如第一幅图所示.

But I can't figure out how to then add the border, as shown in the first image.

问题在于边框和下部之间的间隙必须透明,因为上部的背景可以是渐变,图像等.因此,我不能简单地将图像用于三角形切口,因为我不知道它后面会有什么内容.

The problem is that the gap between the border and the lower section has to be transparent, because the background of the upper section can be a gradient, an image, etc. Therefore, I can't simply use an image for the triangular cutout, because I can't know what content will be behind it.

有没有可能用CSS做到这一点?

Is there any possible way to do this with CSS?

推荐答案

使用CSS可以做到这一点,但是我能找到的唯一方法是使用非常多的渐变来模仿边界的非常复杂的方法.使用常规边界无法做到这一点,因为这会导致边界超出其交汇点或内部区域永不相交.使用框阴影无法做到这一点,因为边框和填充区域之间的间隙必须透明. (不是说不能用这些做,只是我不能使它起作用,也许这些也有办法.)

It is possible to do this with CSS but the only approach that I could find is a very complex one using a fair amount of gradients to mimic the borders. This couldn't be done with normal borders because that resulted in either the borders extending beyond their meeting point or the inner area never meeting. It couldn't be done with box shadow's also because the gap between the border and the filled area need to be transparent. (Not saying it cannot be done with those but just that I couldn't get it to work, maybe there is a way with those too).

以下是我设法实现边界的方法:

The below is how I've managed to achieve the border:

  • 使用四个线性渐变创建所需的边框.
  • 第一和第二实际上是纯色(也就是说,从一种颜色到另一种颜色没有变化),但是我使用了渐变色,因为这样可以控制背景尺寸.这两条线产生一条水平实线,其中一条位于左侧,另一条位于右侧,位于使用伪元素生成的透明切口的上方.
  • 第3和第4条产生的斜线的厚度与边框所需的厚度相同.
  • 设置所有四个渐变的大小和位置,以使其产生边界效果.

输出(如您将鼠标悬停在元素上所看到的)也具有响应能力.

The output - as you can see by hovering the element - is responsive too.

div {
  position: relative;
  height: 200px;
  width: 300px;
  background: linear-gradient(#DDD, #DDD), /* horizontal border line on left */
              linear-gradient(#DDD, #DDD),  /* horizontal border line on right */
              linear-gradient(to top right, transparent calc(50% - 2px), #DDD calc(50% - 2px), #DDD calc(50% + 2px), transparent calc(50% + 2px)), /* angled border on left of center */
              linear-gradient(to top left, transparent calc(50% - 2px), #DDD calc(50% - 2px), #DDD calc(50% + 2px), transparent calc(50% + 2px)), /* angled border on right of center */
              radial-gradient(circle, #3F9CBA 0%, #153346 100%) /* actual background */;
  background-size: calc(50% - 38px) 4px, 
                   calc(50% - 38px) 4px, 
                   40px 40px, /* size of one half of the triangle */
                   40px 40px, /* size of one half of the triangle */
                   auto auto /* size of actual bg */;
  background-position: 0% calc(100% - 44px), 
                       100% calc(100% - 44px), 
                       calc(50% - 18px) calc(100% - 8px), 
                       calc(50% + 18px) calc(100% - 8px), 
                       0px 0px;
  background-repeat: no-repeat;
  overflow: hidden;
  border-bottom: 20px solid #DDD;
}
div:before,
div:after {
  position: absolute;
  content: '';
  height: 40px;
  width: 50%;
  bottom: 0;
  background: #DDD;
  backface-visibility: hidden;
}
div:before {
  left: 0;
  transform-origin: left bottom;
  transform: skewX(45deg);
}
div:after {
  right: 0;
  transform-origin: right bottom;
  transform: skewX(-45deg);
}

/* Just for demo */

div {
  transition: all 1s;
}
div:hover {
  height: 250px;
  width: 550px;
}

<div></div>

以下是需要根据所需的边框颜色和宽度设置背景属性的方式(所有针对45度倾斜角的计算,不同的角度将需要不同的计算):

The following is how the background properties need to be set based on the required border color and width (all calculations for 45 degree skew angle, different angle will need different calculations):

  • 渐变中使用的颜色与边框颜色相同.因此,如果边框颜色需要为红色而不是#DDD,则所有颜色值都应更改为红色.
  • 边界的厚度将使用前两个渐变的background-size以及接下来两个渐变的渐变色停止点来确定.

  • The colors used within the gradient is the same as the border color. So, if border color needs to be red instead of #DDD then all color values should be changed to red.
  • The thickness of the border will be determined using background-size for the first two gradients and using the gradient's color-stop points for the next two gradients.

  • 对于前两个,Y轴上的background-size只是边框的粗细.对其进行更改以适合所需的厚度. X轴上的background-size就是50%减去伪高度减去边框厚度的一半
  • 对于接下来的两个,应设置渐变的颜色停止点,以使颜色开始(和透明端)的边界为50%-边框厚度的一半,颜色结束(透明框的起点)和边界的50%+一半的边界厚度(以便产生所需厚度的笔划).
  • For the first two, the background-size in Y-axis is nothing but the border thickness. Change it to suit the needed thickness. The background-size in X-axis is nothing but 50% minus the height of the pseudo minus half of border thickness
  • For the next two, the color stop points of the gradient should be set such that the color starts (and transparent ends) at 50% - half the border thickness and color ends (transparnet starts) and 50% + half the border thickness (so that it produces a stroke of required thickness).
  • 对于前两个,X轴上的background-position分别应为左边缘(0%)和右边缘(100%).它们在Y轴上的位置应位于伪元素上方,因此应为100%减去伪元素的高度减去间距.
  • 对于接下来的两个,background-position涉及更复杂的计算,其中包括边界间距,厚度和伪元素的高度.逻辑如下.
  • For the first two, the background-position in X-axis should be left edge (0%) and right edge (100%) respectively. Their position in Y-axis should be above the pseudo-element and so it should be 100% minus pseudo-element's height minus the spacing.
  • For the next two, the background-position involves more complex calculation involving the border spacing, thickness and pseudo-element's height. The logic is present below.
background: linear-gradient([color, [color]),
            linear-gradient([color], [color]), 
            linear-gradient(to top right, 
                            transparent calc(50% - [border-thickness/2]), 
                            [color] calc(50% - [border-thickness/2]), 
                            [color] calc(50% + [border-thickness/2]),
                            transparent calc(50% + [border-thickness/2])),
            linear-gradient(to top left, 
                            transparent calc(50% - [border-thickness/2]),
                            [color] calc(50% - [border-thickness/2]), 
                            [color] calc(50% + [border-thickness/2]), 
                            transparent calc(50% + [border-thickness/2])), 
                            radial-gradient(circle, #3F9CBA 0%, #153346 100%) /* actual background */;

background-size: calc(50% - [pseudo-height - border-thickness/2]) [border-thickness], 
                 calc(50% - [pseudo-height - border-thickness/2]) [border-thickness], 
                 [pseudo-height] [pseudo-height], 
                 [pseudo-height] [pseudo-height], 
                 auto auto /* size of actual bg */;

background-position: 0% calc(100% - [pseudo-height + border-space]), 
                     100% calc(100% - [pseudo-height + border-space]), 
                     calc(50% - [(pseudo-height - border-space)/2]) calc(100% - [border-space + border-thickness/2]), 
                     calc(50% + [(pseudo-height - border-space)/2]) calc(100% - [border-space + border-thickness/2]), 
                     0px 0px;


如果需要在下部div顶部带有边框的透明切口,则可以像下面的代码片段中那样实现.


If you need the transparent cut with border on the top part of the lower div then you could achieve it like in the below snippet.

div {
  height: 200px;
  width: 300px;
}
div:nth-child(1) {
  background: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
  background-repeat: no-repeat;
}
div:nth-child(2) {
  position: relative;
  margin-top: -48px;
  padding-top: 48px;
  background: linear-gradient(#DDD, #DDD), linear-gradient(#DDD, #DDD), linear-gradient(to top right, transparent calc(50% - 2px), #DDD calc(50% - 2px), #DDD calc(50% + 2px), transparent calc(50% + 2px)), linear-gradient(to top left, transparent calc(50% - 2px), #DDD calc(50% - 2px), #DDD calc(50% + 2px), transparent calc(50% + 2px)), linear-gradient(#DDD, #DDD);
  background-size: calc(50% - 38px) 4px, calc(50% - 38px) 4px, 40px 40px, 40px 40px, auto auto;
  background-position: 0% 0px, 100% 0px, calc(50% - 18px) 0px, calc(50% + 18px) 0px, 0px 0px;
  background-repeat: no-repeat;
  background-clip: border-box, border-box, border-box, border-box, content-box;
  overflow: hidden;
}
div:nth-child(2):before,
div:nth-child(2):after {
  position: absolute;
  content: '';
  height: 40px;
  width: 50%;
  top: 8px;
  background: #DDD;
  backface-visibility: hidden;
}
div:before {
  left: 0;
  transform-origin: left bottom;
  transform: skewX(45deg);
}
div:after {
  right: 0;
  transform-origin: right bottom;
  transform: skewX(-45deg);
}
/* Just for demo */

div {
  transition: all 1s;
}
body:hover > div {
  height: 250px;
  width: 550px;
}

<div></div>
<div></div>

这篇关于带边框和透明间隙的CSS三角形切口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆