Can I do knock-out/punch-through transparency with CSS fonts? - css

I would like to know if there is any way I can apply 100% transparency to text so that we can see the background picture of the page within the characters in the text.
i.e. imagine I’ve got a <div> with a white background, and a background image on <body>. I’d like to set the text inside the <div> so that the background image on <body> can be seen through the text, despite the white background on the <div>.
I could probably use an inverted font but I would prefer a better way to do it if there is one.

Does it have to be dynamic? The only way to do that is with an image with transparency (GIF or, better, PNG).
I'm not sure if this is what you want, but will explain it anyway.
Situation: you have a non plain background that you want to bee seen through your text.
Solution: no CSS is coming to the rescue for this. You'll have to use your trusty image editor to create a layer with text, and another layer that will be the negative of your text
This could allow you to have some interesting effects, but if you want it to be dynamic, you'll have to generate the images on the fly serverside.
This kind of trickery is currently impossible with pure CSS (might be possible with Javascript).
Edit
Seeing Paul's find on webkit got me thinking on how to fake that behavior in Firefox, Opera and IE. So far I've had good luck using the canvas element on Firefox, and I'm trying to find some behavior in filter:progid:DXImageTransform.Microsoft.
So far with canvas, this is what I did
<html>
<body>
<canvas id="c" width="150" height="150">
</canvas>
<script>
ctx = document.getElementById("c").getContext("2d");
// draw rectangle filling the canvas element
ctx.fillStyle = "red";
ctx.fillRect(0,0,150,150);
// set composite property
ctx.globalCompositeOperation = 'destination-out';
// the text to be added now will "crop out" the red rectangle
ctx.strokeText("Cropping the", 10, 20);
ctx.strokeText("red rectangle", 10, 40);
</script>
</body>
</html>
by using a detination-out compositing and drawing text on the canvas.

I’m not exactly clear what you’re asking (100% transparency means that something’s invisible, and invisible text isn’t generally a great idea), but in general:
The CSS opacity property applies to an entire element, not just its text. So if you have this HTML:
<div class="opacity-50">
This is a div with a background colour and 50% opacity
</div>
And this CSS:
.opacity-50 {
background: #ccc;
color: #000;
opacity: 0.5;
}
Then both its background and its text will have 50% opacity.
rgba colour values allow you to specify semi-transparent colours. So, if you have this HTML:
<div class="text-opacity-50">
This is a div with semi-transparent text
</div>
And this CSS:
.text-opacity-50 {
background: #ccc;
color: rgba(0,0,0,0.5);
}
Then only its text will have 50% opacity.
I think rgba colour values are supported by slightly fewer browses than opacity.

Ah — if you’re talking about “punch-through” transparency, no, CSS doesn’t do this.
Except for WebKit (the rendering engine in Safari and Chrome), which has a totally custom, made-up-by-Dave-Hyatt, not-even-in-CSS-3 property value, -webkit-background-clip: text;.
No other browser other than Safari and Chrome supports it.

You can spent the time to make your own font with InkScape and IcoMoon and make a negative knocked out font, then your letters can be see trough! I used this technique for some see trough Icons.

Why not try to set the DIV's background image to a completely transparent GIF?
http://www.pageresource.com/dhtml/csstut9.htm

Using a .png without background is a good method. In Photoshop you can save for the web.
or in css:
#div
{
background:transparent;
color:whatever;
}

Related

CSS Transparent Text with Solid Background Surrounding Text

I am searching for a pure CSS method for creating transparent text within a box(div,p,etc) where the box is filled with a color surrounding the text, but not the text itself (which would be transparent a la rgba/hsla).
Imagine a div styled in such a way that the text color within is rgba .2 alpha lvl, and the background color is solid, where the background solid color cannot be seen in the text. Of course, a solution using multiple stacked divs/blocks would be greatly acceptable, but should allow for a hover state, so the effect can be switched on/off. In using this, one could apply this div on top of an image or another div that can be seen through the letters.
SO! CSS/html works in such a way that text is always applied on top of a background (called a background for a reason), so, using transparent colors on text color does nothing but show the color of the background. I have tried creating a background with a big box shadow, in order to see if it's ever calculated differently, and it is not (and couldn't think of another method).
Instead of blabbering on with my limited CSS knowledge, I think you get the point, so give me your best! I want this to work in Chrome and Firefox at least.
Stacked Overflow doesn't allow me to put a jsfiddle without accompanied code, and I don't want to put pointless code here just to link to a 'starting point' code.
Instead, here's an image explaining the obvious idea:
Demo Fiddle
You CAN accomplish this in CSS only, but with limited support.
You can set the -webkit-background-clip property, and -webkit-text-fill-color to transparent.
This will only work in webkit browsers however.
e.g.:
div {
color: white; /* Fallback */
background: url(yourimage.png) no-repeat;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
See here for more on background-clip
The background-clip CSS property specifies whether an element's
background, either the color or image, extends underneath its border.
If there is no background image, this property has only visual effect
when the border has transparent regions (because of border-style) or
partially opaque regions; otherwise the border covers up the
difference.
Alternatively- you can use SVG, per this question

How to have an opaque background image on a div?

I have a <div> which contains a bunch of <p>s and would like to have an opaque background image behind text, scaled to fill the entire <div>. I.e. no matter how much text I add or remove, the image should grow or shrink to cover the entire background of the <div>.
And only the image should have opacity. Text within the div should be solid black.
How do I do that, please? (and do I have to worry about browsers which do not support CSS3?)
[Answer] from o.p.
I stepped back and looked at the problem another way and found an answer which is cross-browser and does not need CSS3.
I fired up The Gimp and added opactiy into the image itself! Exactly what I sought to do, with no fancy CSS3 necessary ;-)
Thanks very much for your help, #JSW189. I hope you don't mind me posting in your answer, but this is the solution which I chose.
You want to use the background-image property to add the image, then background-size:100% to have the background image fill the entire div.
div {
background-image:url('image_url_goes_here.jpg');
background-size: 100%;
}
JS Fiddle Example.
Further, if you would like to toggle with the opacity, you can use the opacity property. It is set to opacity:1 (opaque) by default, but you can change that by toggling the opacity between 1 and 0. So, for example, if you want an opacity of 50%, you would use opacity:.5.
Opacity JS Fiddle Example.
Note that background-size is a CSS3 property. You can see a browser compatibility chart here. However, this problem can be solved by libraries like modernizr.

CSS outline property not showing in Firefox for SVG image?

I'm trying to design an interaction that uses an SVG canvas (the full app uses d3) and image elements drawn on the canvas. I'd like each image to change somehow when the user hovers or clicks on the image, to show that it is selected. The most basic style change I could think of is changing the outline of the image (i.e. draw a border around it), and this works fine on Chrome 23/Chromium 20. However it does not have any effect on Firefox 16.
jsFiddle: http://jsfiddle.net/RSLsy/
Code:
<!DOCTYPE HTML>
<html>
<body>
<style>
.map {
background-color: blue;
}
.button:hover {
outline: solid medium black;
}
</style>
<div>
<svg width="400" height="300" class="map">
<image class="button" xlink:href="http://www.gstatic.com/ui/v1/button/search-white.png"
x="10" y="10" width="20" height="20"/>
</svg>
</div>
</body>
</html>
Any ideas for how I can achieve this type of effect cross-browser?
Thanks in advance!
If you aren't limited to using png images and could potentially have icon shape images like the magnifying glass as svg paths, you can use JQuery to animate their fill, stroke, etc. Here is a fiddle I made for another SO question regarding animating color change on hover that you might be able to repurpose.
http://jsfiddle.net/webchemist/hBHBn/
in your case you would want to change the JQuery UI Color plugin hook to
jQuery.Color.hook('stroke');
to get an outline effect. That fiddle should work in IE9 and all current versions of Firefox, Opera, Chrome and Safari
Edit
I updated your fiddle to get the same effect in chrome & firefox w css (havent tested other browsers) by wrapping the image element in a group with an empty rectangle the same size and location of the image. Not sure why it wont make the group element the size of the image element without the rect element holding it open.. Adding duplicate empty rectangles for each of your image elements is probably not ideal but might be easier than making svg paths for my original fiddle solution
http://jsfiddle.net/RSLsy/2/

Making an opacity text-gradient over a transparent background

it should look like http://img190.imageshack.us/img190/1686/textgradient.jpg the tricky part is, it should work for opera, canvas..? also important: the transparency is only needed for the big texts in the screenshot.
the text is simple html text in a span tag. the background is a somewhat transparent png, defined as css background-image of the container div.
i'd have no problems with using canvas or something like that for displaying the text.
If only Cufón supported a horizontal linear gradient "out of the box" you would have been sorted for an easy <canvas> solution. Funnily enough, a conversation on cufon supporting a horizontal linear gradient was just started in the last 24 hours. The demo below demonstrates Cufón with a vertical linear gradient using rgba.
Demo: jsfiddle.net/Marcel/35PXy (fullscreen)
well, it was a long day, and i've found a solution by myself.
it uses canvas.
for a canvas with html height 73px and width 720px:
var ctx = myCanvasEl.getContext("2d");
ctx.font = "53pt Arial, Helvetica, sans-serif";
var gradient = ctx.createLinearGradient(400, 0, 650, 0);
gradient.addColorStop(0, "rgb(255,255,255)");
gradient.addColorStop(1, "rgba(255,255,255,0)");
ctx.fillStyle = gradient;
ctx.fillText(myText, 0, 58);
The simplest way to do this that I can think of is to create a copy of the background image, go into photoshop and create a gradient that's mostly transparent. Then overlay the gradient on the text. That'll work in every browser, I believe.
You don't need canvas anymore. Use property background-clip: text combined with a gradient background with rgba (alpha channel to full transparency).
Here an example:
http://tympanus.net/Tutorials/ExperimentsBackgroundClipText/index2.html
It's great but it works just in webkit browser, at this time.
For a more compatible solution you can look at mask-image http://trentwalton.com/2011/05/19/mask-image-text/
Similar to the first method, you should fade mask to full transparency to get the effect you want to realize.

CSS - Opaque text on low opacity div?

I have a div with 60% opacity, to show part of a background image behind the div. Because the opacity is at 60%, the text in that div appears as grey.
Is there anyway to override this level and make the text appear black?
Any advice appreciated.
Thanks.
Set the opacity on the background rather than the element.
background-color: rgba(255,0,0,0.6);
A while ago I wrote about how to achieve this in a backwards compatible way.
I've experimented with this in the past on my own website. By far the easiest method to achieve what you want is to create a single-pixel .PNG image with its opacity set to less than 100% (i.e., partly-transparent) and use it as a background image. By default it will fill the whole containing element - make sure that the CSS background-repeat attribute is set to 'repeat' if it doesn't.
Doing things this way you don't have to set transparency on the containing element itself, hence the opacity of its text will be unaffected.
Amazingly, there is just the tool for making a semi-transparent single-pixel .PNG here.
The opacity applies to the whole div and all of its children. Unfortunately, you cannot undo that opacity, but only add more. And besides that, there's no way for CSS to select the text inside an element.
In your case, the best solution is to apply a transparent background image (with PNG) to your div block, like a white one pixel image with 60% opacity.
Another solution would be to use different boxes and positioning, like described in this tutorial by Steven York.
this should answer just about all of your questions: http://css-tricks.com/non-transparent-elements-inside-transparent-elements/
The simplest solution would be to create a semi-transparent PNG with the correct colour and use that as a background image.
Another solution that may be possible depending on your layout is to put the text in a separate layer and position that over the top of the semi-transparent part. Something like this would work:
<div style="position: relative; background-image: url('your_image.jpg')">
<div style="opacity: 0.5; background-color: #fff; position: absolute"></div>
<div style="position: absolute">The text to go on top</div>
</div>
You'd need to add your own positions/sizes (the top, left, width and height properties) as appropriate.

Resources