Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a drop shadow to transparent text with CSS

Tags:

css

Is there a way to add a drop shadow to transparent text so the background behind the text remains visible? Maybe some way to use the text itself as a mask? Or a text-blend-mode (with reasonable cross-browser support)?

My naive attempt:

span {
    background-image: url(http://i.imgur.com/EWDVnfb.png);
    color: #FFF;
    font-family: sans-serif;
    font-size: 100pt;
    font-weight: bold;
    line-height: 2em;
    padding: .5em;
    text-shadow: 0 0 .5em #F00;
}
<span>Test</span>
like image 680
lwiseman Avatar asked Feb 26 '15 18:02

lwiseman


People also ask

Can you add drop shadow in CSS?

We can add a drop shadow to any HTML element using the CSS property box-shadow .

How do you add transparency to text in CSS?

To set the opacity of a background, image, text, or other element, you can use the CSS opacity property. Values for this property range from 0 to 1. If you set the property to 0, the styled element will be completely transparent (ie. invisible).


1 Answers

Here's a solution that works on Chrome and Safari:

Fiddle

Basically, the idea is to have 2 div overplayed on each other. The lower one provides the background and the shadow. And the the div above just uses a mask to cut out the exact same text from the background image, so that it covers the text of lower element, but not the shadow:

div {
    position:absolute;
    top:0;
    left:0;
    background-image: url(http://i.imgur.com/EWDVnfb.png);
    font-family: sans-serif;
    font-size: 100pt;
    font-weight: bold;
    line-height: 2em;
    padding: .5em;
}
div.shadow {
    color: #fff;
    text-shadow: 0 0 .5em #F00;
}
div.text {
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
}

EDIT

I just found a wonderful article on css-tricks.com So, there seems to be a solution with much better browser support. The idea is to replace the top-layer div by and svg containing the same text and use a pattern to fill the text with the background image, here's a sketch:

<div class="shadow">Test</div>
<div>
    <svg width="400" height="200">
        <pattern id="mask" patternUnits="userSpaceOnUse"
             width="400" height="200" viewbox="0 0 400 200">
            <image xlink:href="..." width="300" height="300" />
        </pattern>
        <text x="0" y="1em">Test</text>
    </svg>
</div>

CSS (in addition to the CSS of my above solution):

text {
  fill:url(#mask);
}

I've been trying to get this to work as well, with partial success. (DEMO) But I'm not very good with svg's and someone else might be able to fix it. Anyway, the weakness here is that positioning this correctly and reliably is a real pain while you get that automagically right with the Webkit-only solution.

like image 79
mmgross Avatar answered Sep 22 '22 09:09

mmgross