Create a Reverse Clip-Path - CSS or SVG

后端 未结 2 848
-上瘾入骨i
-上瘾入骨i 2021-01-02 19:06

I\'m trying to create what is in essence the reverse of a CSS clip-path. When using clip-path, an image or div is clipped so that only the shape you specify remains and the

2条回答
  •  南笙
    南笙 (楼主)
    2021-01-02 19:47

    You can put the image above the blue part and you apply the clip-path on it then the result will be the same as if you have created a hole inside the blue part to see the image below:

    body {
      width: 100%; 
      height: 100vh;
      padding: 0; margin: 0;
      display: flex;
      }
    
    #box {
      margin: auto;
      position: relative;
      width: 33%;
      height: 200px;
      background: blue;
    }
    
    #innerbox {
      width: 100%;
      height: 100%;
      background: url(https://lorempixel.com/400/400/) center/cover;
      top: 0;
      left: 0;
      position: absolute;
      z-index:1;
      clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
    }

    Another idea is to consider multiple background and you will have better support than clip-path and also less of code:

    body {
      height: 100vh;
      margin: 0;
      display: flex;
    }
    
    #box {
      margin: auto;
      position: relative;
      width: 33%;
      height: 200px;
      background: 
        linear-gradient(to bottom right,transparent 49%,blue 50%) bottom/100% 60%,
        linear-gradient(to top right,transparent 49%,blue 50%) top/100% 60%,
        linear-gradient(blue,blue) left/20% 100%,
        url(https://lorempixel.com/400/400/) center/cover;
      background-repeat:no-repeat;
    }

    UPDATE

    If you want some opacity, here is an idea where you have to duplicate the content using clip-path (a drawback):

    body {
      width: 100%; 
      height: 100vh;
      padding: 0; margin: 0;
      display: flex;
      }
    
    #box {
      margin: auto;
      position: relative;
      width: 33%;
      height: 200px;
      background: blue;
    }
    
    #innerbox,#innerbox-2 {
      width: 100%;
      height: 100%;
      background: url(https://lorempixel.com/400/400/) center/cover;
      top: 0;
      left: 0;
      position: absolute;
      z-index:2;
    }
    #innerbox {
      /* if you initially planned to have x opacity so you need to set 1-x here*/
      opacity:0.4;
    }
    
    #innerbox-2 {
      z-index:1;
      clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
      animation:animate 5s linear alternate infinite;
    }
    
    @keyframes animate {
      from {
        clip-path:polygon(10% 10%, 10% 90%, 90% 50%);
      }
      to {
         clip-path:polygon(20% 50%, 90% 50%, 80% 10%);
      }
    }

    Title

    Some content

    Title

    Some content

    UPDATE 2

    You can consider SVG to do your initial requirement. Simply use an SVG instead of a div where you will have a mask.

    body {
      width: 100%; 
      height: 100vh;
      padding: 0; margin: 0;
      display: flex;
      }
    
    #box {
      margin: auto;
      position: relative;
      width: 33%;
      height: 200px;
      background: blue;
      background: url(https://lorempixel.com/400/400/) center/cover;
    }
    
    #innerbox {
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      position: absolute;
      z-index:1;
    }

    You can also use the same SVG as background:

    body {
      width: 100%; 
      height: 100vh;
      padding: 0; margin: 0;
      display: flex;
      }
    
    #box {
      margin: auto;
      position: relative;
      width: 33%;
      height: 200px;
      background: blue;
      background: url(https://lorempixel.com/400/400/) center/cover;
    }
    
    #innerbox {
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      position: absolute;
      z-index:1;
      background:url('data:image/svg+xml;utf8, ');
    }

    Update 3 (what I recommend in 2020)

    You can use CSS mask to get the effect you want with mask-composite

    body {
      width: 100%; 
      height: 100vh;
      padding: 0; margin: 0;
      display: flex;
      }
    
    #box {
      margin: auto;
      position: relative;
      width: 33%;
      height: 200px;
      background: url(https://lorempixel.com/400/400/) center/cover;
    }
    
    #innerbox {
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      position: absolute;
      -webkit-mask:url('data:image/svg+xml;utf8,') 0/100% 100%;
              mask:url('data:image/svg+xml;utf8,') 0/100% 100%;
      background:blue;
    }

    And the inverted version using the same shape

    body {
      width: 100%; 
      height: 100vh;
      padding: 0; margin: 0;
      display: flex;
      }
    
    #box {
      margin: auto;
      position: relative;
      width: 33%;
      height: 200px;
      background: url(https://lorempixel.com/400/400/) center/cover;
    }
    
    #innerbox {
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      position: absolute;
      -webkit-mask:
         url('data:image/svg+xml;utf8,') 0/100% 100%,
         linear-gradient(#fff,#fff);
      -webkit-mask-composite:destination-out;
              mask:
         url('data:image/svg+xml;utf8,') 0/100% 100%,
         linear-gradient(#fff,#fff);
      mask-composite:exclude;  
      background:blue;
    }

提交回复
热议问题