2

I have an animated background and I would really like the effect of my text to be cut out and show the background.

I have seen example where you can attach a background image and set background color to the same layer and then show the image in the text but not any examples where the layer underneath was revealed. Is it possible?

So in this snippet the white text would be cut out and you could see the gradient changing through the hole.

body {
  background: linear-gradient(270deg, #000, #fff);
  background-size: 400% 400%;
  -webkit-animation: AnimationName 5s ease infinite;
  -moz-animation: AnimationName 5s ease infinite;
  animation: AnimationName 5s ease infinite;
}
@-webkit-keyframes AnimationName {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
@-moz-keyframes AnimationName {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
@keyframes AnimationName {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

.container{
  width: 400px;
  height: 200px;
  background-color: darkred;
  margin: auto;
  color: #fff;
  font-size: 80px;
  font-weight: 900;
  text-align: center;
}
<div class="container">TO BE CUT OUT</div>

jsfiddle: https://jsfiddle.net/nmhmxkyj/

Guerrilla
  • 13,375
  • 31
  • 109
  • 210
  • That is the example I mentioned. It works by an image attached to same layer, it doesn't reveal the layer behind as far as I can see. – Guerrilla Feb 11 '16 at 16:23
  • Actually the second solution looks like it will work, I only read the accepted answer. You were right. – Guerrilla Feb 11 '16 at 16:31
  • Along with the SVG answer on the linked question, you can also write text out on a `canvas` and set the `globalCompositeOperation` to `destination-out` and it will cut out the overlapping shapes. [fiddle demo](https://jsfiddle.net/7wLkrmku/) – Patrick Evans Feb 11 '16 at 16:36
  • I found this, looks like a really cool effect. https://css-tricks.com/how-to-do-knockout-text/ – dmgig Feb 11 '16 at 16:37
  • Actually the linked post doesnt answer it because its using a mask and not cutting the text out. The mask is still obscured by the layer underneath, it doesn't cut a hole. – Guerrilla Feb 11 '16 at 16:52

2 Answers2

2

You can use SVG and apply <mask>

@import url(https://fonts.googleapis.com/css?family=Lato:900);
body, html {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}

body {
  background:  url('http://science-all.com/images/mountain/mountain-03.jpg');
  background-size: cover;
  background-position: center center;
}

svg {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-45%, -50%);
}

text {
  font-size: 80px;
  text-anchor: middle;
  font-family: 'Lato', sans-serif;
}
<svg width="450px" height="250px">
  <mask id="mask" height="100%" width="100%">
    <rect x="0" y="0" width="100%" height="100%" fill="#fff"></rect>
    <text>
      <tspan x="45%" dy="1.2em">TO BE</tspan>
      <tspan x="45%" dy="1.1em">CUT OUT</tspan>
    </text>
  </mask>

  <rect width="100%" height="100%" mask="url(#mask)" fill="#8B0000"></rect>
</svg>
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
0

My previous answer was the only way I could find to complete this in pure CSS. However, this is possible using javascript and a canvas. Would this satisfy your question?

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.save();
ctx.beginPath();
ctx.fillStyle = "darkred";
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fill();
ctx.font = "70pt Arial";
ctx.globalCompositeOperation = "xor";
ctx.beginPath();
ctx.fillText("To Be", 60, 80);
ctx.fillText("Cut Out", 35, 180);
ctx.fill();
ctx.restore();
body {
  background: linear-gradient(270deg, #000, #fff);
  background-size: 400% 400%;
  -webkit-animation: AnimationName 5s ease infinite;
  -moz-animation: AnimationName 5s ease infinite;
  animation: AnimationName 5s ease infinite;
}
@-webkit-keyframes AnimationName {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
@-moz-keyframes AnimationName {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
@keyframes AnimationName {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
<canvas id="canvas" width="400px" height="200px"></canvas>

JSFiddle: https://jsfiddle.net/p98waufL/

Spencer May
  • 4,266
  • 9
  • 28
  • 48
  • 1
    This isn't revealing a layer underneath. It cuts out from the same layer so you wont be able to see the background animation in my example – Guerrilla Feb 11 '16 at 16:26
  • @Guerrilla I don't think it is possible the way you want it. Could you not just create a simple background gif and use this method? It seems like your background will change less than the text will. – Spencer May Feb 11 '16 at 16:39
  • @Guerrilla would you be opposed to using canvases? – Spencer May Feb 11 '16 at 16:42
  • I am open to using canvas. I tried the second solution on the linked post but iit doesn't actually cut out the layer, it makes a mask over the top which still obscures that background when there is a layer in beween – Guerrilla Feb 11 '16 at 16:51
  • @Guerrilla I updated my answer with a js/canvas solution. – Spencer May Feb 11 '16 at 16:52
  • Thanks, I guess I must draw all layers in canvas then? Is there a way for the red box to be a div? – Guerrilla Feb 11 '16 at 16:54
  • @Guerrilla, yea you would have to draw everything you wanted "cut" through in the canvas, it will not cut the elements underneath it – Patrick Evans Feb 11 '16 at 17:49