IE simulated text-shadow flows separately from its text

I’ve asked this question in another popular forum (here) and was surprised not to have a single response in 2 weeks, maybe because it was tagged as a “jQuery” issue although fundamentally a CSS & cross-browser issue. I am certain a solution will be useful to the SitePoint community and beyond.

I’ve been using jQuery and IE filters to create a text shadow in IE<=9, to make up for the missing text-shadow property. This can be seen in the top-of-page h2 headings on the site http://area11aa.ie, which uses jQuery on browsers that don’t support the text-shadow property (detected by modernizr) to replicate the text inside the h2 element…

jQuery(".no-textshadow h1, .no-textshadow h2").each(function(){
  var text_shadow_markup = jQuery(this).html();
  jQuery(this).append("<span class='shadow'>"+text_shadow_markup+"</span>");
});

…where it is styled with this CSS, as per this IE drop shadow technique:

@media only screen and (min-width: 768px) {
  h2 {
    text-shadow: #000000 0px 5px 5px;
    position: relative;
    zoom: 1;
    z-index: 1;
  }
  h2 span.shadow {
    color: #000000;
    position: absolute;
    left: -7px;
    top: -2px;
    z-index: -1;
    zoom: 1;
    filter: progid:DXImageTransform.Microsoft.Glow(Color=#000000,Strength=2) progid:DXImageTransform.Microsoft.blur(pixelradius=5,enabled='true');
    -ms-filter: "progid:DXImageTransform.Microsoft.Glow(Color=#000000,Strength=2) progid:DXImageTransform.Microsoft.blur(pixelradius=5,enabled='true')";
  }
}

The problem: Depending upon the screen width, the simulated drop shadows flow independently of the text behind them. You can always see this in IE8 and IE9 by slowly changing the window width until one of the shadows pops away from its text, like this (screenshot from IE9):

I don’t understand how this can happen if the shadow span is absolutely positioned in the containing box of the h2 element. Yet they are able to flow as if they were unattached. I realise this may be a browser bug and therefore would be happy with a workaround supporting IE8 & IE9, as I would be if someone can point out any problems with my application above.

I’ve heard that CSS Sandpaper text-shadow implements a similar technique. In the next few days I’m about to test to see if it has the same problem… if it does, our next design is totally screwed.

I would therefore love to know if 1) if there is a best-practice way of dealing with this problem, and 2) failing a more general approach, if anyone has tested CSS Sandpaper enough to know if it’s free from this vulnerability & could be endorsed as a best-practice solution.

Have you tried any of these?

http://www.impressivewebs.com/css3-text-shadow-in-internet-explorer/
http://heygrady.com/text-shadow-for-internet-explorer
http://www.fetchak.com/ie-css3/

I’d recommend this one: https://github.com/heygrady/textshadow

I’ve done some reasonably intricate things with it, and it has proven itself to be stable and reliable.

Hi,

The fix is easy and more or less obvious :slight_smile:

You have offset the duplicated text by 7px to the left and therefore it will wrap 7px later than the text it is associated with. The behaviour is consistent in IE and indeed Firefox if you try this manually. The solution is to offset the offset by adding 7px right padding to the span.

This works ok for me in a short example.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style>
h2 {
	position: relative;
	zoom: 1;
	z-index: 1;
	width:50%;
	line-height:30px;
}
h2 span.shadow {
	position: absolute;
	color: #000000;
	left: -7px;
	padding-right:7px;
	top: -2px;
	z-index: -1;
 filter: progid:DXImageTransform.Microsoft.Glow(Color=#000000, Strength=2) progid:DXImageTransform.Microsoft.blur(pixelradius=5, enabled='true');
	-ms-filter: "progid:DXImageTransform.Microsoft.Glow(Color=#000000,Strength=2) progid:DXImageTransform.Microsoft.blur(pixelradius=5,enabled='true')";
}
</style>
</head>

<body>
<h2>This is test shadow This is a test This is a-test This is a test <span class="shadow">This is test shadow This is a test This is a-test This is a test</span></h2>
</body>
</html>


You’ll have to test with your more complicated scenario but the logic seems sound :slight_smile:

(If it works you can link back here from Stack overflow to show how its done :))

Paul O’B: I’ve been hoping for an obvious solution like this too, though prior disappointment suggests it’s a browser bug: the ugly MS filters vs. the CSS positioning model. I am still on the lookout for such a workaround, and have added your padding line to the CSS on the live site http://area11aa.ie:

h1 span.shadow { ...
  left: -7px;
  padding-right: 7px;
  top: -2px; ... }

The filter elements are still flowing into the empty space as the window increases in size. As far as I can tell the behaviour is exactly as before, which I think favours the idea that it’s a positioning bug rather than the size of the padding box.

thanks, ralph.m: my solution above is an implementation of method #2 (it’s the link in my original posting). #1 and #4 are the same method, the code looks well supported and usage is clearly documented with reported problems being fixed on Github for a while. The review from Force Flow is also encouraging. Next time around I would definitely give heygrady/textshadow a go. (The remaining two don’t look maintained.)

I was worried about using CSS Sandpaper because of the number of JavaScripts and my difficulty understanding how they all worked together or which ones to use.

I’ll report as soon as I can on heygrady/textshadow, and in the meantime I am still looking for an explanation of this problem & an elementary workaround. If there is any feedback from the other forum or practical experience I will summarise here.

It’s not a problem with the filters because as I mentioned above Firefox will do exactly the same thing if you give it the same code. The demo I gave above works fine in IE8 so its likely to be the percentage padding and margin you have applied to the h2 that is confusing things again.

I suggest that you sidestep the padding issue and place the appended span into the anchor and then you only have the offset to cater for.

This is a rough version of your code with the span moved and seems to work fine in IE8 right until it gets very small. If you move the span outside the anchor you get the same behaviour as before with the shadow wrapping at different steps.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style type="text/css">
body {
	color: #000000;
	font-family: Verdana, Arial, Helvetica, sans-serif;
	font-size: 0.81em;
	line-height: 1.5;
}
#componentHead h2 { padding-right: 10px; }
h2 { font-weight: bold; }
h2, h3, h4 {
	font-family: "Trebuchet MS", Verdana, Arial, sans-serif;
	line-height: 1.1em;
}
.page-header h2 {
	color: #D3D3D3;
	font-family: "Trebuchet MS", Verdana, Arial, sans-serif;
	font-size: 2.4em;
	margin-top: 0;
}
.page-header h2 { font-size: 4em; }
h2 {
	position: relative;
	text-shadow: 0 5px 5px #000000;
	z-index: 1;
}
#componentHead {
	background: -moz-linear-gradient(left center, #294159, #7AB9FF) repeat scroll 0 0 transparent;
	border-bottom-right-radius: 40px;
	box-shadow: 5px 5px 10px 0;
	margin-bottom: 5px;
	margin-right: 5%;
	padding-bottom: 10px;
	padding-left: 33.33%;
	padding-top: 10px;
}
.page-header h2 a, .page-header h2 a:hover, .page-header h2 a:active { color: #D3D3D3; }
.page-header h2 a, .page-header h2 a:hover, .page-header h2 a:active { color: #0000CD; }
a, a:hover, a:active { text-decoration: none; }
h2 {
	text-shadow: #000000 0px 5px 5px;
	position: relative;
	zoom: 1;
	z-index: 1;
}
h2 a {
	display:block;
	zoom:1.0;
	position:relative;
	background:#f2f2f2
}
h2 span.shadow {
	color: #000000;
	position: absolute;
	left: -7px;
	padding-right: 8px;
	top: -2px;
	z-index: -1;
	zoom: 1;
 filter: progid:DXImageTransform.Microsoft.Glow(Color=#000000, Strength=2) progid:DXImageTransform.Microsoft.blur(pixelradius=5, enabled='true');
	-ms-filter: "progid:DXImageTransform.Microsoft.Glow(Color=#000000,Strength=2) progid:DXImageTransform.Microsoft.blur(pixelradius=5,enabled='true')";
}
</style>
</head>

<body>
<div id="componentHead" class="item-page">
		<div class="page-header">
				<h2> <a href="/"> A.A. Meetings, South&#8208;East Dublin, Ireland<span class="shadow"> A.A. Meetings, South&#8208;East Dublin, Ireland</span></a></h2>
		</div>
</div>
</body>
</html>

I’m sure the solution is as mentioned although it may need fine tuning. :slight_smile:

Intriguing problem and solution.

There may be a typo in one of the offset values… as written, I see a 1px wrapping difference. Fine-tuning the padding-right from 8px to 7px to match the p:a offset makes Paul’s solution render perfectly on my PC (FF, Chrome, Opera, IE8).


h2 span.shadow {
	color: #000000;
	position: absolute;
	left: -7px;
	padding-right: [color=red]7px[/color];    /* changed from 8px */
	top: -2px;

Well spotted Ron.:slight_smile: Yes the 8px was a value I was testing to make it break and I should have returned it to 7px when posting the code but I forgot:blush:

dear Paul: I really appreciate your time in addition to publishing an additional iteration of your demonstration code. This proves that the percentage widths on the containing element aren’t the problem, as you suggested earlier if I understood correctly. And it proves that a correct implementation is possible, though my primary question is to find out why the problem is happening on the production site! :slight_smile:

I’ve adjusted the jQuery so it adds the shadow <span> inside the anchor, so the HTML ends up the same as yours above:

<h2> <a href="/"> A.A. Meetings, South&#8208;East Dublin, Ireland<span class="shadow"> A.A. Meetings, South&#8208;East Dublin, Ireland</span></a> </h2> 

The offset is added exactly as in your code (7px). And all relevant parts of the CSS are the same as far as I can tell. So why I am I still seeing this problem on the live site (http://area11aa.ie) in IE9? What have I missed?

Hi,

You omitted the stacking context so effectively nothing changed.

i.e. You need to add this:


h2 a {
	display:block;
	zoom:1.0;
	position:relative;
}

Here’s it all working in IE9 with most of your code:

http://www.pmob.co.uk/temp/test-text-shadow.htm

I didn’t add the IE8 media query support but it should work in your full code.

Dear Paul: I am truly grateful for your persistence with me. Yes, I’d missed the rule set that establishes a new stacking context for the <a> element. It now works perfectly with that section added, on the live site. Thank you for helping me understand what the issue was, although I still don’t know what general design principle would have avoided the problems in the first place.

There are some clues on the design page for jQuery Textshadow, in the two sections for [URL=“http://heygrady.com/blog/2011/03/10/css-text-shadows-in-internet-explorer#glow”]Glow and [URL=“http://heygrady.com/blog/2011/03/10/css-text-shadows-in-internet-explorer#blur”]Blur (the two effects used in this design). Both sections describe adjustments that must be made to element positioning, as well as nested <span> elements each creating a new stacking context.

May the Force be with you all… /robert

Glad we got there in the end :slight_smile: