Skip to content Skip to sidebar Skip to footer

Create A Reverse Clip-path - Css Or Svg

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 rest of

Solution 1:

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%);
}
<divid="box"><divid="innerbox"></div></div>

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;
}
<divid="box"></div>

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%);
  }
}
<divid="box"><divid="innerbox"><h1>Title</h1><p>Some content</p></div><divid="innerbox-2"><h1>Title</h1><p>Some content</p></div></div>

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;
}
<divid="box"><svgviewBox="0 0 200 200"id="innerbox"preserveAspectRatio="none"><defs><maskid="hole"><rectwidth="100%"height="100%"fill="white"/><!-- the hole defined a polygon --><polygonpoints="20,20 20,180 180,100 "fill="black"/></mask></defs><!-- create a rect, fill it with the color and apply the above mask --><rectfill="blue"width="100%"height="100%"mask="url(#hole)" /></svg></div>

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,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><defs><mask id="hole"><rect width="100%" height="100%" fill="white"/> <polygon points="20,20 20,180 180,100 " fill="black"/></mask></defs><rect fill="blue" width="100%" height="100%" mask="url(%23hole)" /></svg>');
}
<divid="box"><divid="innerbox"></div></div>

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,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100%100%;
          mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100%100%;
  background:blue;
}
<divid="box"><divid="innerbox"></div></div>

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,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100%100%,
     linear-gradient(#fff,#fff);
  -webkit-mask-composite:destination-out;
          mask:
     url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" preserveAspectRatio="none"><polygon points="20,20 20,180 180,100 " fill="black"/></svg>') 0/100%100%,
     linear-gradient(#fff,#fff);
  mask-composite:exclude;  
  background:blue;
}
<divid="box"><divid="innerbox"></div></div>

Solution 2:

This ranks high on Google and the answer didn't solve my problem b/c I cannot touch my background image so here is another way of doing this:

Create a frame with the clip-path.

body {
  width: 100%;
  height: 100vh;
  padding: 0;
  margin: 0;
  display: grid;
  place-items: center;
}

#clip,
#background {
  width: 400px;
  height: 400px;
}

#clip {
  clip-path: polygon(0%0%, 0%100%, 25%100%, 25%25%, 75%25%, 75%75%, 25%75%, 25%100%, 100%100%, 100%0%);
  position: absolute;
  background: #fff;
  opacity: 0.8;
}

#background {
  background: url(https://picsum.photos/400/400/) center/cover;
  z-index: -1;
}
<divid="background"><divid="clip"></div></div>

I put the clip-div inside the image because of convenience but you can also have it outside. However, make sure that you are okay with the limited browser support of clip-path.

Post a Comment for "Create A Reverse Clip-path - Css Or Svg"