Transparent text cut out of background
It's possible with css3 but it's not supported in all browsers
With background-clip: text; you can use a background for the text, but you will have to align it with the background of the page
body {
background: url(http://www.color-hex.com/palettes/26323.png) repeat;
margin:10px;
}
h1 {
background-color:#fff;
overflow:hidden;
display:inline-block;
padding:10px;
font-weight:bold;
font-family:arial;
color:transparent;
font-size:200px;
}
span {
background: url(http://www.color-hex.com/palettes/26323.png) -20px -20px repeat;
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
display:block;
}
<h1><span>ABCDEFGHIKJ</span></h1>
http://jsfiddle.net/JGPuZ/1337/
Automatic Alignment
With a little javascript you can align the background automatically:
$(document).ready(function(){
//Position of the header in the webpage
var position = $("h1").position();
var padding = 10; //Padding set to the header
var left = position.left + padding;
var top = position.top + padding;
$("h1").find("span").css("background-position","-"+left+"px -"+top+"px");
});
body {
background: url(http://www.color-hex.com/palettes/26323.png) repeat;
margin:10px;
}
h1 {
background-color:#fff;
overflow:hidden;
display:inline-block;
padding:10px;
font-weight:bold;
font-family:arial;
color:transparent;
font-size:200px;
}
span {
background: url(http://www.color-hex.com/palettes/26323.png) -20px -20px repeat;
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1><span>ABCDEFGHIKJ</span></h1>
http://jsfiddle.net/JGPuZ/1336/
Although this is possible with CSS, a better approach would be to use an inline SVG with SVG masking. This approach has some advantages over CSS :
- Much better browser support: IE10+, chrome, Firefox, safari...
- This doesn't impact SEO as spiders can crawl SVG content (google indexes SVG content since 2010)
CodePen Demo : SVG text mask
body,html{height:100%;margin:0;padding:0;}
body{
background:url('https://farm9.staticflickr.com/8760/17195790401_94fcf60556_c.jpg');
background-size:cover;
background-attachment:fixed;
}
svg{width:100%;}
<svg viewbox="0 0 100 60">
<defs>
<mask id="mask" x="0" y="0" width="100" height="50">
<rect x="0" y="0" width="100" height="40" fill="#fff"/>
<text text-anchor="middle" x="50" y="18" dy="1">SVG</text>
<text text-anchor="middle" x="50" y="30" dy="1">Text mask</text>
</mask>
</defs>
<rect x="5" y="5" width="90" height="30" mask="url(#mask)" fill-opacity="0.5"/>
</svg>
If you aim on making the text selectable and searchable, you need to include it outside the <defs>
tag. The following example shows a way to do that keeping the transparent text with the <use>
tag:
body,html{height:100%;margin:0;padding:0;}
body{
background:url('https://farm9.staticflickr.com/8760/17195790401_94fcf60556_c.jpg');
background-size:cover;
background-attachment:fixed;
}
svg{width:100%;}
<svg viewbox="0 0 100 60">
<defs>
<g id="text">
<text text-anchor="middle" x="50" y="18" dy="1">SVG</text>
<text text-anchor="middle" x="50" y="30" dy="1">Text mask</text>
</g>
<mask id="mask" x="0" y="0" width="100" height="50">
<rect x="0" y="0" width="100" height="40" fill="#fff"/>
<use xlink:href="#text" />
</mask>
</defs>
<rect x="5" y="5" width="90" height="30" mask="url(#mask)" fill-opacity="0.5"/>
<use xlink:href="#text" mask="url(#mask)" />
</svg>
One way that works on most modern browsers is to use
background: black;
color: white;
mix-blend-mode: multiply;
for transparent text on a black background, or
background: white;
color: black;
mix-blend-mode: screen;
for transparent text on a white background.
For this to work in chrome, you also need to set any background colour on the html
element.
Put these styles on your text element and then put whatever background you want behind that. Multiply basically maps the 0-255 color code to 0-1 and then multiplies that by whatever is behind it, so black stays black and white multiplies by 1 and effectively becomes transparent. Screen is effectively the opposite for this case. http://codepen.io/nic_klaassen/full/adKqWX/
It is possible, but so far only with Webkit based browsers (Chrome, Safari, Rockmelt, anything based on the Chromium project.)
The trick is to have an element within the white one that has the same background as the body, then use -webkit- background-clip: text;
on the inner element which basically means "don't extend the background beyond the text" and use transparent text.
section
{
background: url(http://norcaleasygreen.com/wp-content/uploads/2012/11/turf-grass1.jpg);
width: 100%;
height: 300px;
}
div
{
background: rgba(255, 255, 255, 1);
color: rgba(255, 255, 255, 0);
width: 60%;
heighT: 80%;
margin: 0 auto;
font-size: 60px;
text-align: center;
}
p
{
background: url(http://norcaleasygreen.com/wp-content/uploads/2012/11/turf-grass1.jpg);
-webkit-background-clip: text;
}
http://jsfiddle.net/BWRsA/
I just discovered a new way to do this while messing around, I'm not entirely sure how it works ( if someone else wants to explain please do ).
It seems to work very well, and requires no double backgrounds or JavaScript.
Here's the code: JSFIDDLE
body {
padding: 0;
margin: 0;
}
div {
background: url(http://www.color-hex.com/palettes/26323.png) repeat;
width: 100vw;
height: 100vh;
}
body::before {
content: '$ALPHABET';
left: 0;
top: 0;
position: absolute;
color: #222;
background-color: #fff;
padding: 1rem;
font-family: Arial;
z-index: 1;
mix-blend-mode: screen;
font-weight: 800;
font-size: 3rem;
letter-spacing: 1rem;
}
<div></div>