带有边框和透明间隙的CSS三角形切口

时间:2016-04-21 23:37:01

标签: css css3 border css-shapes skew

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

separator

使用this answer中的skewX()技术,我能够准确地模仿三角形切口(两个伪元素附加到下部的顶部,一个向左倾斜,一个向右倾斜,所以上部的背景显示通过):

enter image description here

但我无法弄清楚如何添加边框,如第一张图片所示。

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

有没有办法用CSS做到这一点?

3 个答案:

答案 0 :(得分:7)

可以用CSS做到这一点,但我能找到的唯一方法是使用相当数量的渐变来模仿边界的非常复杂的方法。这不能用正常边界完成,因为这会导致边界超出其会合点或内部区域永不满足。它也不能用盒子阴影来完成,因为边框和填充区域之间的间隙需要是透明的。 (并不是说不能用那些,但只是我无法让它工作,也许有一种方法与那些)。

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

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

输出 - 正如你可以通过悬停元素看到的那样 - 也是响应。



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>
&#13;
&#13;
&#13;

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

  • 渐变中使用的颜色与边框颜色相同。因此,如果边框颜色需要为红色而不是#DDD,那么所有颜色值都应更改为红色。
  • 边框的粗细将使用background-size确定前两个渐变,并使用渐变的颜色停止点作为接下来的两个渐变。

    • 对于前两个,Y轴上的background-size只是边框厚度。改变它以适应所需的厚度。 X轴上的background-size只是50%减去伪的高度减去边界厚度的一半
    • 对于接下来的两个,应设置渐变的颜色停止点,使颜色开始(和透明端)为50% - 边框厚度的一半和颜色结束(透明网开始)和50%+边框的一半厚度(使其产生所需厚度的行程)。
  • 应设置background-position,以便在彩色区域和边框之间存在所需的间隙。
    • 对于前两个,X轴中的background-position应分别为左边(0%)和右边(100%)。它们在Y轴上的位置应该高于伪元素,所以它应该是100%减去伪元素的高度减去间距。
    • 对于接下来的两个,background-position涉及更复杂的计算,涉及边界间距,厚度和伪元素的高度。逻辑如下。
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的顶部部分使用带边框的透明剪切,那么您可以像在下面的代码段中那样实现它。

&#13;
&#13;
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;
}
&#13;
<div></div>
<div></div>
&#13;
&#13;
&#13;

答案 1 :(得分:5)

这里使用渐变和(@Harry)边框和&amp; amp;影子: 已知宽度有很大帮助,否则,您需要使用calc()调整一些阴影偏移值。

&#13;
&#13;
div.bdr {
  padding-bottom: 5px;/* to be used to draw a transparent line */
  background: #1B4046;
  background-clip: content-box;/* here comes the 5 transparent pixel line */
  box-shadow: -273px 5px 0 #1B4046, 274px 5px 0 #1B4046; 
  /* move shadow far away to only draw them by bits 
  Notice, wrapper must be hidding overflow */
  margin-bottom:2em;
}

.bdr.bg-color{
  background-color:tomato;
  background-image:linear-gradient(to top, transparent 5px,   #1B4046 5px);

  background-clip:border-box;
  }
div.bdr:after {  
  content: '';
  height: 30px;
  width: 30px;
  padding: 5px; 
  display: block;
  margin: auto;
  z-index: -1;
  transform: rotate(45deg);
  margin: -20px auto -20px;
  background:  #1B4046;
  background-clip: content-box;/* again, keep some parts transparent */
  box-shadow:6px 6px 0  -1px #1B4046;  
}
.bdr.bg-color:after {
  z-index:0;
  padding:5px 0 0 5px;
  border:5px solid transparent;
  border-left:0;
  border-top:0;
  box-shadow:6px 6px 0  -1px #1B4046;
  
  background:linear-gradient(to bottom right, transparent 50%, #1B4046 50%) no-repeat , linear-gradient(to bottom right, transparent 50%, tomato 50%) 5px 5px  no-repeat;
  }
article {
  width:500px;
  margin:auto;
  color:white;
}
h1 {
  text-align:center;
}
div.shapebdr {
  padding-bottom: 40px;
  margin: 32px 0;
  background: linear-gradient(to top, transparent 30px, #1B4046 30px, #1B4046 35px, transparent 35px) bottom left, linear-gradient(to top, transparent 30px, #1B4046 30px, #1B4046 35px, transparent 35px) bottom right, linear-gradient(to top, transparent 40px, #1B4046 40px) bottom;
  ;
  background-repeat: no-repeat;
  background-size: 230px 100%, 230px 100%, 100% 100%;
  position: relative;
}

div.shapebdr:after {
  content: '';
  height: 40px;
  width: 40px;
  padding: 10px;
  display: block;
  margin: auto;
  z-index: -1;
  background: inherit;
  transform: rotate(45deg);
  margin: -40px auto -20px;
  background: linear-gradient(to top, #1B4046, #1B4046) no-repeat, linear-gradient(to top, #1B4046 0, #1B4046 5px, transparent 5px) no-repeat right, linear-gradient(to left, #1B4046 0, #1B4046 5px, transparent 5px) no-repeat bottom right;
  background-clip: content-box, border-box, border-box;
  background-size: auto auto, 57% 100%, 100% 57%;
}

div.br:after {
  margin: auto;
  margin-bottom: -40px;  
}


article {
  overflow: hidden;
  padding-bottom: 40px;
}
html {
  min-height: 100%;
  background: linear-gradient(30deg, gray, yellow, purple, lime, tomato, turquoise, gray);
}
p {
  padding:0.25em;
  margin:0.25em;
position:relative;/* make sure text shows over the pseudo element */
}
&#13;
<article>
  <h1>border and shadow approach </h1>
  <div class="bdr">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      facilisis luctus, metus</p>
  </div>
  <h1>gradient approach</h1>
  <div class="shapebdr">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor,
      facilisis luctus, metus</p>

  </div>
   <h1>shadow + gradient approach to fill translucide line</h1> 
  <div class="bdr bg-color">
    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
      lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor,
      facilisis luctus, metus</p>

  </div>
</article>
&#13;
&#13;
&#13;

pen to play with

答案 2 :(得分:2)

无法抗拒发布另一个版本......

太多的手工计算值使其成为一个完美的解决方案,但如果尺寸固定,则可以适合您。

.test {
  width: 400px;
  height: 80px;
  margin-top: 100px;
  position: relative;
  overflow: hidden;
  background-image: linear-gradient(-120deg, transparent 31px, lightblue 21px),                       linear-gradient(120deg, transparent 31px, lightblue 21px);
  background-size: 50% 80%, 50% 80%;
  background-repeat: no-repeat;
  background-position: 0px 100%, 100% 100%;
}


.test:before {
  content: "";
  position: absolute;
  width: 50%;
  height: 50px;
  border-top: solid 4px blue;
  border-right: solid 4px blue;
  top: 0px;
  right: calc(50% - 2px);
  transform: skewX(30deg);
  transform-origin: right bottom;
}

.test:after {
  content: "";
  position: absolute;
  width: 50%;
  height: 50px;
  border-top: solid 4px blue;
  border-left: solid 4px blue;
  top: 0px;
  left: calc(50% - 2px);
  transform: skewX(-30deg);
  transform-origin: right bottom;
}
<div class="test"></div>