Search code examples
htmlcssbordercss-shapesclip-path

Triangle edges with consistent angle in CSS


I have to code a design like this:

CSS triangles with consistent angle I did everything as shown on the picture, but I ran into a problem. The angle of this polygon changes when the screen size changes, but I need it to be consistent to match the angle of the hexagon logo. I tried several things such as putting the triangle PNG as the header's background image - the angle is consistent but then the border gets too big on the larger screens and too small on the smaller screens and I need the border size to be consistent across all screen sizes as well (50px).

Hopefully someone can help. If you have a better way than using clip-path, I am open to that solution as well! Tips: Pattern (background-image) size is fixed, Logo size is fixed, Border size is fixed, the only thing that should scale is the polygon with consistent angle.

The code below matches for 1920px screen size width.

body {
  background-color: #6e4d3c;
  margin: 0;
  padding: 0;
}

header {
  background: #FFF;
  height: 850px;
  clip-path: polygon(
    0 0, /* left top */
    100% 0, /* right top */ 
    100% 300px, /* right bottom */
    50% 100%, /* center */
    0 300px  /* left bottom */
  );  
}

.clipped {
  background: #99ffe7 url(http://i.pics.rs/70hBA.png) no-repeat top center;
  height: 800px;
  position: relative;
  clip-path: polygon(
    0 0, /* left top */
    100% 0, /* right top */ 
    100% 250px, /* right bottom */
    50% 100%, /* center */
    0 250px  /* left bottom */
  );
}

#logo {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 340px;
}
    <header> <!-- serves as the white border -->
      <div class="clipped">
        <img id="logo" src="http://i.pics.rs/M7gQb.png" alt="Logo">
      </div>
    </header>


Solution

  • Instead of clip-path I would consider mask with gradient to have the same angle . The trick is to use big values that you make fixed and you place the gradients around the center.

    body {
      background-color: #6e4d3c;
      margin: 0;
    }
    
    header {
      -webkit-mask:    
        linear-gradient(to bottom left ,#fff 49.8%,transparent 50%) bottom 0 right calc(50% + 750px),
        linear-gradient(to bottom right,#fff 49.8%,transparent 50%) bottom 0 left  calc(50% + 750px);
      -webkit-mask-size:1501px 875px;
      -webkit-mask-repeat:no-repeat;
      mask:
        linear-gradient(to bottom left ,#fff 49.8%,transparent 50%) bottom 0 right calc(50% + 750px),
        linear-gradient(to bottom right,#fff 49.8%,transparent 50%) bottom 0 left  calc(50% + 750px);
      mask-size:1501px 875px;
      mask-repeat:no-repeat;
      height: 700px;
      
      /* I use a similar gradient here to create the border effect */
      background: 
        linear-gradient(to bottom left ,transparent calc(50% - 50px),#fff calc(50% - 49px))
         bottom 0 right calc(50% + 750px)/1501px 875px,
        linear-gradient(to bottom right,transparent calc(50% - 50px),#fff calc(50% - 49px))
         bottom 0 left  calc(50% + 750px)/1501px 875px,
        url(http://i.pics.rs/70hBA.png) top/cover
        #99ffe7;
      background-repeat:no-repeat;
      display:flex;
    }
    
    #logo {
      width: 340px;
      margin:auto;
    }
    <header>
        <img id="logo" src="http://i.pics.rs/M7gQb.png" alt="Logo">
    </header>

    It's a bit tricky but here is an illustration of the gradient alone as background so you can better understand what is happening:

    body {
      background-color: #6e4d3c;
      margin: 0;
      padding: 0;
    }
    
    header {
      background:
        linear-gradient(to bottom left ,green 49.8%,transparent 50%) bottom 0 right calc(50% + 750px),
        linear-gradient(to bottom right,blue  49.8%,transparent 50%) bottom 0 left  calc(50% + 750px);
      background-size:1501px 875px;
      background-repeat:no-repeat;
    
      height: 700px;
    }
    <header>
      
    </header>

    The colors are the visible part of you elements and if we can consider A the angle created by each gradient we will have sin(A) = 875px/1500px = 0.583 which will give us an angle of 35.685deg. Increase/deacrese the values to control the angle. Keep the same ratio to keep the same angle. Simply make sure the width defined by 1500px is big enough for the gradient to cover all the screen and the height defined by 875px is big enough to cover the height of the element:

    Using small value will get you this:

    body {
      background-color: #6e4d3c;
      margin: 0;
    }
    
    header {
      -webkit-mask:
        linear-gradient(to bottom left ,#fff 49.8%,transparent 50%) bottom 0 right calc(50% + 60px),
        linear-gradient(to bottom right,#fff 49.8%,transparent 50%) bottom 0 left  calc(50% + 60px);
      -webkit-mask-size:121px 70px;
      -webkit-mask-repeat:no-repeat;
      mask:
        linear-gradient(to bottom left ,#fff 49.8%,transparent 50%) bottom 0 right calc(50% + 60px),
        linear-gradient(to bottom right,#fff 49.8%,transparent 50%) bottom 0 left  calc(50% + 60px);
      mask-size:121px 70px;
      mask-repeat:no-repeat;
      height: 800px;
      
      background: 
        linear-gradient(to bottom left ,transparent 48%,#fff 48%)
         bottom 0 right calc(50% + 600px)/1201px 700px,
        linear-gradient(to bottom right,transparent 48%,#fff 48%)
         bottom 0 left  calc(50% + 600px)/1201px 700px,
        url(http://i.pics.rs/70hBA.png) top/cover,
        #99ffe7;
      background-repeat:no-repeat;
      display:flex;
    }
    
    #logo {
      width: 340px;
      margin:auto;
    }
    <header>
        <img id="logo" src="http://i.pics.rs/M7gQb.png" alt="Logo">
    </header>

    Here is a related question to get more details about the calculation of the background-size/background-position: Using percentage values with background-position on a linear-gradient


    PS: I add/remove 1px or a small value of percentage to avoid having jagged edges on the gradients