Search code examples
cssbordercss-shapesborder-imagecss-gradients

Border-image gradient pattern in triangle shape


I want to create an odd shaped triangle with css. My first thought was to use transparent borders with transform: rotate and it worked (see left triangle). Now I want to use a gradient border image pattern as background for a same triangle but I can't make it work. I tried many things like changing border-width, using wrappers and overflow:hidden among others, nothing worked. Here I post one of my tries (see right shape) as you see the pattern takes all the space, not following the triangle shape. Any ideas?

#top-left {
  position:absolute;
  left:78px;
  width: 0;
  height: 0;
  border-top: 100px solid transparent;  
  border-right: 80px solid black;
  border-bottom: 50px solid transparent;
  -webkit-transform: rotate(-20deg); 
}

#top-right {
  position:absolute;
  left:300px;
  width: 0;
  height: 0;
  border-image: repeating-linear-gradient( 0deg, pink, pink 1%, purple 1%, purple 8%) 10;
  border-image-width: 100px 80px 50px 0px;
  border-width: 100px 80px 50px 0px;
  border-style: solid;
  -webkit-transform: rotate(-20deg); 
}
<div id="wrapper">
 <div id="top-left"></div>  
 <div id="top-right"></div>
</div>

Edit: Andrey Fedorov's answer is good, but there is a problem when the background is not a solid color, like this for example:

body{  
background-color: #6d695c;
background-image:
repeating-linear-gradient(120deg, rgba(255,255,255,.1), rgba(255,255,255,.1) 1px, transparent 1px, transparent 60px),
repeating-linear-gradient(60deg, rgba(255,255,255,.1), rgba(255,255,255,.1) 1px, transparent 1px, transparent 60px),
linear-gradient(60deg, rgba(0,0,0,.1) 25%, transparent 25%, transparent 75%, rgba(0,0,0,.1) 75%, rgba(0,0,0,.1)),
linear-gradient(120deg, rgba(0,0,0,.1) 25%, transparent 25%, transparent 75%, rgba(0,0,0,.1) 75%, rgba(0,0,0,.1));
background-size: 70px 120px;
}
#wrapper {
  position: relative;
}

#top-left {
  position:absolute;
  left:0px;
	width: 0;
	height: 0;
	border-top: 100px solid #fff;  
	border-right: 80px solid transparent;
	border-bottom: 50px solid #fff;
  -webkit-transform: rotate(-20deg); 
}

#top-right {
  position:absolute;
  z-index: -10;
  left:0;
  width: 0;
  height: 0;
  border-image: repeating-linear-gradient( 0deg, pink, pink 1%, purple 1%, purple 8%) 10;
  border-image-width: 100px 80px 50px 0px;
  border-width: 100px 80px 50px 0px;
  border-style: solid;
  -webkit-transform: rotate(-20deg); 
}
<div id="wrapper">
 <div id="top-left"></div>  
 <div id="top-right"></div>
</div>


Solution

  • You still can use linear-gradient with no-repeat and background-size to draw each pieces :

    examples by steps from a single tag :

    /* testing gradients */
    p , div#wrapper {
      width:80px;
      float:left;
      margin:1em;
      height:150px;
      /* see me then remove this  shadow */
      box-shadow:0 0 0 2px;
    }
    p {
      background:
        linear-gradient(130deg, transparent 49.75%, pink 50.5%) 0 42px  no-repeat ;
      background-size:
        100% 15px;
      transform: rotate(-20deg); 
    }
    p + p{
      background:
        linear-gradient(130deg, transparent 49.75%, pink 50.5%) 0 42px  no-repeat ,
        linear-gradient(130deg,transparent 62px, purple 63px) top no-repeat;
      background-size:
        100% 15px,
        100% 65%;
    }
    p + p + p {
      
      background:
        linear-gradient(130deg, transparent 49.75%, pink 50.5%) 0 42px  no-repeat ,
        linear-gradient(130deg,transparent 62px, purple 63px) top no-repeat,
        linear-gradient(33deg , transparent 42px, pink 43px) no-repeat bottom;
      background-size:
        100% 15px,
        100% 65%, 
        100% 8px;
    }
    p+ p + p + p {
        background:
        linear-gradient(130deg, transparent 49.75%, pink 50.5%) 0 42px  no-repeat ,
        linear-gradient(130deg,transparent 62px, purple 63px) top no-repeat,
        linear-gradient(33deg , transparent 42px, pink 43px) no-repeat bottom, 
        linear-gradient(33deg, transparent 42px, purple 43px) bottom no-repeat;
      background-size:
        100% 15px,
        100% 65%, 
        100% 8px, 
        100% 35.5%;
      }
    p:last-of-type{
      box-shadow:0 0
    }
    
    /* your original CSS/issue */
    body{  
    background-color: #6d695c;
    background-image:
    repeating-linear-gradient(120deg, rgba(255,255,255,.1), rgba(255,255,255,.1) 1px, transparent 1px, transparent 60px),
    repeating-linear-gradient(60deg, rgba(255,255,255,.1), rgba(255,255,255,.1) 1px, transparent 1px, transparent 60px),
    linear-gradient(60deg, rgba(0,0,0,.1) 25%, transparent 25%, transparent 75%, rgba(0,0,0,.1) 75%, rgba(0,0,0,.1)),
    linear-gradient(120deg, rgba(0,0,0,.1) 25%, transparent 25%, transparent 75%, rgba(0,0,0,.1) 75%, rgba(0,0,0,.1));
    background-size: 70px 120px;
    }
    #wrapper {
      position: relative;
    }
    
    #top-left {
      position:absolute;
      left:0px;
    	width: 0;
    	height: 0;
    	border-top: 100px solid #fff;  
    	border-right: 80px solid transparent;
    	border-bottom: 50px solid #fff;
      -webkit-transform: rotate(-20deg); 
      transform: rotate(-20deg); 
    }
    
    #top-right {
      position:absolute;
      z-index: -10;
      left:0;
      width: 0;
      height: 0;
      border-image: repeating-linear-gradient( 0deg, pink, pink 1%, purple 1%, purple 8%) 10;
      border-image-width: 100px 80px 50px 0px;
      border-width: 100px 80px 50px 0px;
      border-style: solid;
      -webkit-transform: rotate(-20deg); 
      transform: rotate(-20deg); 
    }
    <!-- your issue -->
    <div id="wrapper">
     <div id="top-left"></div>  
     <div id="top-right"></div>
    </div>
    <!-- p for testing purpose -->
    <p></p>
    <p></p>
    <p></p>
    <p></p>
    <p></p>

    inbricated element + gradient & transform could do too:

    body{  
    background-color: #6d695c;
    background-image:
    repeating-linear-gradient(120deg, rgba(255,255,255,.1), rgba(255,255,255,.1) 1px, transparent 1px, transparent 60px),
    repeating-linear-gradient(60deg, rgba(255,255,255,.1), rgba(255,255,255,.1) 1px, transparent 1px, transparent 60px),
    linear-gradient(60deg, rgba(0,0,0,.1) 25%, transparent 25%, transparent 75%, rgba(0,0,0,.1) 75%, rgba(0,0,0,.1)),
    linear-gradient(120deg, rgba(0,0,0,.1) 25%, transparent 25%, transparent 75%, rgba(0,0,0,.1) 75%, rgba(0,0,0,.1));
    background-size: 70px 120px;
    }
    
    div.inbricate {
      margin:1em;
      height:150px;
      width:80px;
      position:relative;
      overflow:hidden;
      transform:rotate(-20deg);
      box-shadow: 0 0 ;
    }
    .inbricate div {
      transform:rotate(31deg) scale(1.2, 0.9) skew(-5deg);
      transform-origin: 100% 102%;
      height:100%;
      background:linear-gradient(-40deg,   pink 8%, purple 8%, purple 65%, pink 65%, pink 75%, purple 75% )
    }
    <div class=inbricate>
      <div>
      </div>
    </div>