-2

I read Cutting a triangle out of div, BUT have it horizontally centered here and I am looking for a very similar solution, but not exactly the same.Since the question is from 2014, I prefer to start a new thread.

A nice solution to the above question is http://jsfiddle.net/FaddH/:

body {
    background-image: url(http://i.imgur.com/XxGffrU.jpg); background-size: cover;
    background-position: center bottom; min-height: 1000px; margin: 0;
}

#your_div { position: fixed; top: 30%; width: 90%; left: 5%; height: 100px; }
#back { width: 100%; height: 100%; }
<div id="your_div">
    <svg id="back" viewBox="0 0 100 10" preserveAspectRatio="none">
        <path d="M 0,0 L 100,0 100,10 0,10 0,0 M 50,8 L 55,6 52,6 52,2 48,2 48,6 45,6 z" style="fill: white; fill-rule: evenodd;"></path>
    </svg>
</div>

enter image description here

Now I'd like to do the same but instead of the arrow, I need a text to cut out the div and make the background visible. Would that be possible somehow?

I could also imagine to prepare the text as SVG-file, but it would be best if it would be possible to write the text directly into the html/js.

Appreciate every help and suggestion! Thanks in advance!

Community
  • 1
  • 1
Rostam N.
  • 15
  • 3
  • Hi, on SO we prefer our questions to be stand alone - feel free to link to other questions, but it's best if you describe the problem, desired outcome and what you've tried to solve it within the question itself, only using links as references. – Jeff Aug 26 '16 at 01:04

1 Answers1

3

If I understood the question correctly, you can make use of the combination of -webkit-background-clip: text and -webkit-text-fill-color: transparent, but this is experimental feature and only work on webkit browsers and supposed to be supported on the soon to be released Firefox 49 (read the "text" row of the Browser Compatibility table), but for IE, so sorry.

CodePen 1
.. for -webkit-background-clip: text part, currently, test with webkit browsers to see the effect

#test-div {
  width: 800px;
  height: 200px;
  font-weight: bold;
  font-size: 120px;
  background: url('//lorempixel.com/800/200/sports/3/') no-repeat;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}
<div id="test-div">Dummy Text</div>

Good news is as you mentioned in the question SVG would be great with much wider browser support (back to IE9), also the mask element could contain multiple elements, shapes, text, paths all together. Beside it's possible to control the opacity of clipping by using different levels of gray-scale colors as alpha channel [CodePen example].

Using SVG mask:

#theSVG #txtMask {
  font-size: 120px;
  font-weight: bold;
  fill: white;
}
#theSVG #theIMG {
  mask: url(#theMask);
}
<svg id="theSVG" viewBox="0 0 800 200" width="800" height="200">
  <defs>
    <mask id="theMask">
      <text id="txtMask" x="0" y="50%">Dummy Text</text>
    </mask>
  </defs>
  <image id="theIMG" xlink:href="http://lorempixel.com/800/200/sports/3/" x="0" y="0" height="200px" width="800px" />
</svg>

Updated Edit:

For a similar effect like the cut-off arrow inside the white rectangle in your question but with text instead, both CSS and SVG solutions:

CodePen 2
.. for -webkit-background-clip: text part, currently, test with webkit browsers to see the effect

#test-div,
#test-div .txt {
  width: 800px;
  height: 200px;
  font-weight: bold;
  font-size: 60px;
  position: relative;
  background: url('//lorempixel.com/800/200/sports/3/') no-repeat;
}
#test-div .white-rect {
  width: 80%;
  height: 120px;
  line-height: 120px;
  position: relative;
  top: 30px;
  margin: 0 auto;
  background-color: rgba(255, 255, 255, 0.9);
}
#test-div .txt {
  box-sizing: border-box;
  position: absolute;
  left: 0;
  top: 0;
  padding-top: 50px;
  text-align: center;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* SVG */

#theSVG #txtMask {
  font-size: 60px;
  font-weight: bold;
}
<h2>Using "background-clip:text"</h2>
<div id="test-div">
  <div class="white-rect"></div>
  <div class="txt">Dummy Text</div>
</div>
<hr>
<h2>Using SVG</h2>
<svg id="theSVG" viewBox="0 0 800 200" width="800" height="200">
  <defs>
    <mask id="theMask">
      <rect x="10%" y="30" width="80%" height="120" fill="white" />
      <text id="txtMask" x="30%" y="55%">Dummy Text</text>
    </mask>
  </defs>
  <image xlink:href="http://lorempixel.com/800/200/sports/3/" x="0" y="0" height="200px" width="800px" />
  <rect mask="url(#theMask)" x="10%" y="30" width="80%" height="120" fill="rgba(255,255,255,0.9)" />
</svg>
Mi-Creativity
  • 9,554
  • 10
  • 38
  • 47
  • 1
    Thanks for the downvote :) , would be better if you give a reason though – Mi-Creativity Aug 26 '16 at 01:08
  • Thanks a lot for your reply, Mi-Creativity! Actually I don't really understand the "background-clip" in css, as on the photo it just looks like text on an image. But since it is only experimental, I think it's not the best to go with right now. Your SVG solution looks nice and it is almost as I want it to be. I'll play arount with that a little bit. – Rostam N. Aug 26 '16 at 04:12
  • Regarding the downvotes... Yeah I also don't understand why people just vote down without even giving a reason or comment. THAT behavior must get a downvote! – Rostam N. Aug 26 '16 at 04:14
  • You welcome, and from [MDN: backround-clip](https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip) "*`text: The background is painted within (clipped to) the foreground text`*", but again this is only a feature in webkit browsers for now and it needs prefix, firefox 49 will have it and IE no response. – Mi-Creativity Aug 26 '16 at 04:20
  • So for now you have two options, either implement it using SVG only, thus you have very wide support, except IE8 and below, android 4.3 and below.. another way you can use `background-clip:text`, and with feature detection you provide the SVG solution as polyfill *only* if `background-clip:text` is not supported – Mi-Creativity Aug 26 '16 at 04:23
  • You can use SVG `pattern` instead of `mask` to have a similar effect too, check this [css-tricks: how to do knockout text](https://css-tricks.com/how-to-do-knockout-text/) it achieves the same cut-off effect but uses SVG `pattern` instead of `mask`. – Mi-Creativity Aug 26 '16 at 04:31
  • Another great benefit of using SVG here is that the mask could be anything, you can have text mixed with shapes and paths all together, also remember than like alpha mask, black filters out and white shows, different levels of gray-ness gives different transparency, the more the gray shade is close to black "darker" the more transparent effect you get and vice versa, so you can have different elements forming one mask, shapes with letters and yet every element produces different level of transparency, but it's the gray-scale which matters – Mi-Creativity Aug 26 '16 at 04:42
  • Thanks a lot for your help! Yes I also think using SVG would be best, so it would work on most browsers. Anyhow I played around with your solution a little bit.... it's nice, but not exactly what I need. I didn't describe very good. I have a fixed background and need the cutout in a scrollable div. Please see my script on jsfiddle: https://jsfiddle.net/egvh2341/ - here I put the SVG just as img-tag.... so you can see what I mean. That SVG should cut out the white background div. Do you have an idea for this? – Rostam N. Aug 26 '16 at 12:57
  • You welcome, concerning your fiddle, well the way you were doing it wouldn't show effect for both `background-clip:text` nor SVG `mask`, basically because if you include them in the `#content`, they'll clip their corresponding rectangles but the `#content` background color is also white you won't see any thing clipped – Mi-Creativity Aug 26 '16 at 15:18
  • to fix it, I converted the `#content` to `.content` so that it could be used many times and I include the SVG code between `.content` divs seamlessly, then I created a `#wrapper` (with no background color so that we can see the clipping effect) around it this wrapper will serve as wrapper for both the SVG and the `.content` div, another use of this `#wrapper` is we assign the `box-shadow` effect to it to have only one unified shadow because if it's on `.content` divs shadow will appear on the SVG below certain `.content` div – Mi-Creativity Aug 26 '16 at 15:23
  • and that's it, with two SVGs [jsFiddle example](https://jsfiddle.net/vwxk0fzq/1/). (after I've done all of the above, a little "`4px`" gab below every SVG and the next `.content` div appeared and I have no clue why, so I had to put this `margin-top:-5px;` in the `.content` CSS to fix it. – Mi-Creativity Aug 26 '16 at 15:26
  • Now your fiddle looks really nice! The only thing is... actually I do not really understand what you did here :) Could you explain it a little bit more? Is the height of 120px important? Because I would like to write different things, and sometimes it may be more than only one line. But when I put in a
    between 'lorem' and 'ipsum' it all breaks. Also when you delete the SVG1 there is the little gap again.
    – Rostam N. Aug 26 '16 at 17:16
  • Oh and what means the x="0" y="0" in rect tag? Do you know a good SVG-Tutorial online where I can learn a little bit more about working with SVG's? – Rostam N. Aug 26 '16 at 17:23
  • Another thing I just saw..... when you change the width of #content-wrap to 500px it somehow cuts the svg text. Can you tell why? I assumend when the width is set to 100% it would adjust automatically to the wrapper's width. – Rostam N. Aug 26 '16 at 17:51
  • I think I am slowly getting what your code does. Well very very slowly.... :-) But the reason why I need the mask to adjust its height dynamically is, that the inside text (here: Lorem Ipsum) will later be put in dynamically from a json language file. So sometimes it is only one line, but sometimes also two or three lines, depending on the language. Would there be a way to load the SVG rect + mask dynamically via javascript with the needed height? – Rostam N. Aug 26 '16 at 22:42
  • What I've in that fiddle is not about SVG only, it's something general, if you have an element **A** with a certain background color, and you include another element **B** which has a cut-off shape or text with the same back ground color as **A**, it doesn't matter what element **B** would be, a div with `background-clip`, an SVG with `mask`, or just a PNG or GIF with cut-off in it.. the effect won't be noticeable because you're showing the same color through the cut-off – Mi-Creativity Aug 27 '16 at 00:39
  • take [this image](http://image.prntscr.com/image/684f6d2c53cd41f3b169940d019c299d.png) for example, it's a full white PNG with text cutt-off, if you open it in Chrome you'll not see anything (or this what you;d think at first) because Chrome will show it on a white background, so the cut-off will pass white too and all you get is full white, open the same image in firefox, firefox provide another color than white as background, and you'll see the text – Mi-Creativity Aug 27 '16 at 00:42
  • Using the same image I made this fiddle https://jsfiddle.net/qo46q5t6/ to mimic your case, although the image is in the `#content` div you can't see it, because you're seeing white through the cut-off, now change the `#content` background color to let's say skyblue, https://jsfiddle.net/qo46q5t6/1/ now you see the cut-off and can read it. but hey, you don't want this, you want to show the background image from the `body`, you can't do this as long as `#content` has background color, so what you need to do is take the picture outside the `#content` div but still make it appears as it is inside. – Mi-Creativity Aug 27 '16 at 00:46
  • To do this, we need to have more than one `#content` div, the more cut-off elements you want to have and show the body background image through, the more copies of `#content` divs you have to insert elements with cut-off in between.. but keep in mind you must not have more than one element with the same ID because IDs should be unique, so we have to convert the id `#content` to class `.content`, to have an element with cut-off after the first paragraph, we need to one `.content` for content *above* the cut-off element, and another one for content `below` it >> https://jsfiddle.net/qo46q5t6/2/ – Mi-Creativity Aug 27 '16 at 00:53
  • Ehh, same `4px` gap appeared, give `.content` `margin-top:-5px`, and give the `#wrapper` `padding-top:9px;` (`4px` original padding + `5px` to balance the very first `.content` `margin-top:-5px`), and we have this https://jsfiddle.net/qo46q5t6/3/ now.. Next turn the `.content` background color back to white (or same color as the cut-off element) and you'll get this final result https://jsfiddle.net/qo46q5t6/4/ , exactly what I did using SVG instead of the PNG, same idea, and if in future you want to use `background-clip` instead, it'll be the same technique too – Mi-Creativity Aug 27 '16 at 01:00
  • "*`Another thing I just saw..... when you change the width of #content-wrap to 500px it somehow cuts the svg text`*" well the svg `font-size:70px` for that length of text in a `500px` of `#content-wrap` makes it break, if you want less width of the `#content-wrap` or more horizontal text to add then you have to lower the `font-size`.. this is general, check these https://jsfiddle.net/cdj9guyo/3/ and https://jsfiddle.net/cdj9guyo/1/, it breaks because big size font, give the `#content-wrap` `overflow:hidden` and its cut https://jsfiddle.net/cdj9guyo/2/ , same thing happened in your case – Mi-Creativity Aug 27 '16 at 01:23
  • Here is your fiddle https://jsfiddle.net/vwxk0fzq/9/, `#wrap-content` width is `500px`, I changed the SVG `font-size` to `50px` instead of `70px` and that's it.. btw to have the text horizontally centered set `x="50%"` and add `text-anchor="middle"` as I did in the fiddle – Mi-Creativity Aug 27 '16 at 01:28
  • that leads us to your other question, and believe me you do ask many question :), "*`x="0" y="0" in rect tag`*".. well it's the coordinates, x and y, top left point is 0,0 (x=0, y=0), imagine an element with `position` property and have `left=0` and `top=0`, it's the same, to have the element starts at 50% horizontally and 25% vertically, you set `x="50%" y="25%", same as `left:50%; top:25%` in css, this is usually the top left corner of the element, like, start drawing `rect` from point(x,y), with `width="A"` and `height="B"`, same coordinates layout as Photoshop, illustrator, CSS.. etc – Mi-Creativity Aug 27 '16 at 01:35
  • for `circle` you have `cx="A" cy="B"` because it locates the center of the circle. To learn more about SVG check [MDN: SVG Reference](https://developer.mozilla.org/en-US/docs/Web/SVG), especially *SVG element reference* and *SVG attribute reference* sections, also search in google and youtube for SVG tutorials, https://www.youtube.com/results?search_query=SVG+tutorial start with the simple ones first – Mi-Creativity Aug 27 '16 at 01:39
  • Oh dear, thanks a lot for taking your time and explaining all these details. I live in Germany and right now here it is 3:30AM and I'm reading this with great interest! Thank you!! – Rostam N. Aug 27 '16 at 01:40
  • You welcome, I'm in Iraq and it's 4:40 A.M now :).. the height is essential yes but you can control it with javascript depending on your text, check this [fiddle example](https://jsfiddle.net/rgsrm6wt/). – Mi-Creativity Aug 27 '16 at 01:53
  • also keep in mind that SVG is mostly graphics represented by text commands (*something like `canvas`, but with big differences*), don't overuse it as normal text, like for what you're trying to achieve, big dynamically generated set of text would generally be overkill and could get hard to control it dynamically – Mi-Creativity Aug 27 '16 at 01:57
  • Thank you, I will try that JS out tomorrow. You're in Iraq?? Wow! I thought you would be in US.... well I hope you are in a more safe area in Iraq. Actually my uncle also lives in Iraq.... in Erbil, as far as I know :) Unfortunately I haven't talked to him for long time now. I wanted to visit him, but then the overall there situation got so dangerous. I hope it will get better soon. – Rostam N. Aug 27 '16 at 02:09
  • Hello Friend, hope you're fine! You helped me a lot with the SVG thing last time. Thanks again for that! Now I sent a new post today and wanted to ask you if you could be so kind again and have a look on that one. I really appreciate! – Rostam N. Oct 14 '16 at 19:04
  • http://stackoverflow.com/questions/40047562/how-to-perform-a-function-after-json-mustache-translation – Rostam N. Oct 14 '16 at 19:05