Skip to content Skip to sidebar Skip to footer

How To Achieve A Responsive Ribbon Shape In Css?

Trying to achieve this with css. I've achieved in doing this but this breaks if my label (CAREER) is longer the size of the div. If its longer then the content wraps and the heigh

Solution 1:

Here is an idea that rely on skew transformation where it will be responsive and you will have transparency:

.box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:05px5px0;
  position:relative;
  margin:5px;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  left:0;
  height:50%;
  width:3px;
  background:green;
}
.box:before {
  top:0;
  transform:skew(45deg);
  transform-origin:top;
}
.box:after {
  bottom:0;
  transform:skew(-45deg);
  transform-origin:bottom;
}
<divclass="box"></div><divclass="box"style="height:80px"></div>

Ribbon Edge CSS

If you want to keep the same width for the arrow, you can consider a different idea using background:

.box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:05px5px0;
  position:relative;
  margin:5px;
  overflow:hidden;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  left:0;
  top:0;
  height:50%;
  width:30px;
  background:
    linear-gradient(to top right,
      transparent calc(50% - 4px),green,transparent 50%) 
      bottom/100%calc(100% + 4px);
}
.box:after {
  transform:scaleY(-1);
  transform-origin:bottom;
}
<divclass="box"></div><divclass="box"style="height:80px"></div>

and with SVG too

.box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:05px5px0;
  position:relative;
  margin:5px;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  left:0;
  top:0;
  height:50%;
  width:30px;
  background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><line x1="0" y1="-1" x2="15" y2="16" stroke="green"  /></svg>') 00/100%100%;
}
.box:after {
  transform:scaleY(-1);
  transform-origin:bottom;
}
<divclass="box"></div><divclass="box"style="height:80px"></div>

enter image description here

You can also optimize the code and do it without pseudo element:

.box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:05px5px0;
  margin:5px;
  background:
   url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><line x1="0" y1="-1" x2="15" y2="16" stroke="green"  /></svg>') top left/30px50%,
   url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><line x1="0" y1="16" x2="15" y2="-1" stroke="green"  /></svg>') bottom left/30px50%;
  background-repeat:no-repeat;
}
<divclass="box"></div><divclass="box"style="height:80px"></div>

The same SVG can be used to obtain the first result where the arrow width is also dynamic. The trick is to only define the height and preserve the ratio:

.box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:05px5px0;
  margin:5px;
  background:
   url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15"><line x1="0" y1="-1" x2="15" y2="16" stroke="green"  /></svg>') top left/auto 50%,
   url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15"><line x1="0" y1="16" x2="15" y2="-1" stroke="green"  /></svg>') bottom left/auto 50%;
  background-repeat:no-repeat;
}
<divclass="box"></div><divclass="box"style="height:80px"></div>

You can easily add a coloration inside too.

With skew transformation:

.box {
  height: 50px;
  border: 2px solid green;
  border-left: 0;
  border-radius:05px5px0;
  position:relative;
  overflow:hidden;
  z-index:0;
  margin:5px;
}
.box:before,
.box:after{
  content:"";
  position:absolute;
  z-index:-1;
  left:0;
  right:0;
  height:50%;
  border-left:3px solid green;
  background:yellow;
}
.box:before {
  top:0;
  transform:skew(45deg);
  transform-origin:top;
}
.box:after {
  bottom:0;
  transform:skew(-45deg);
  transform-origin:bottom;
}
<divclass="box"></div><divclass="box"style="height:80px"></div>

With the SVG background

.box {
  height: 50px;
  padding-left:30px;
  border: 2px solid green;
  border-left: 0;
  border-radius:05px5px0;
  margin:5px;
  background:
   url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><polygon points="16,17 16,-2 0,-1 " fill="yellow" stroke="green" /></svg>') top left/30px50%,
   url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 15 15" preserveAspectRatio="none"><polygon points="16,16 16,-2 0,16 " fill="yellow" stroke="green" /></svg>') bottom left/30px50%,
   yellow content-box;
  background-repeat:no-repeat;
}
<divclass="box"></div><divclass="box"style="height:80px"></div>

Solution 2:

If you have white-on-white background, then you can use two css-triangles that one covers other and creates edge for ribbon. If you need some transparency, then you should rely on clip-path(check if support is proper for your users)OR some SVG elements.

* {
  box-sizing: border-box;
}

.ribbon {
  width: 100%;
  height: 100px;
  border: 2px solid blue;
  position: relative;
  padding: 0120px;
  line-height: 100px;
  text-align: center;
  font-size: 30px;
}
.ribbon:before,
.ribbon:after {
  content: '';
    width: 0;
    height: 0;
    border-top: 50px solid transparent;
    border-left: 100px solid green;
    border-bottom: 50px solid transparent;
    position: absolute;
    top: 0;
    left: 0;
  }
  
  .ribbon:after {
  border-left-color: white;
  left: -3px;
  }
<divclass="ribbon">CARRIER</div>

For less-hacky approach use simple background image.

Post a Comment for "How To Achieve A Responsive Ribbon Shape In Css?"