Posts in the CSS Category

Reset Revisited

Published 14 years, 5 months past

It was close to four years ago now that I first floated (ha!), publicly refined, and then published at its own home what’s become known as the “Eric Meyer Reset”.  At the time, I expected it would be of interest to a small portion of the standards community, provoke some thought among fellow craftspeople, and get used occasionally when it seemed handy.  Instead, it’s ended up almost everywhere.

(This occasionally backfires on me when people use it in the CSS of e-mail campaigns, it’s exposed by older mail clients, and people then mail me to demand that I unsubscribe them from the mailing list.  But that’s not the worst backfire — I’ll get to that in just a minute.)

Four years is long enough for a revisit, I’d say.  I spent a little time working on and thinking about it over the holidays.  Here’s where I ended up.

/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0b1 | 201101 
   NOTE: WORK IN PROGRESS
   USE WITH CAUTION AND TEST WITH ABANDON */

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
	display: block;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}

/* remember to define visible focus styles! 
:focus {
	outline: ?????;
} */

/* remember to highlight inserts somehow! */
ins {
	text-decoration: none;
}
del {
	text-decoration: line-through;
}

table {
	border-collapse: collapse;
	border-spacing: 0;
}

Some of you may be thinking: “Hey, it’s the HTML5 Doctor reset!”  Actually, no, though I did use their work as a check on my own.  I felt like that one went a bit far, to be honest.  What I have above is simply the reset I had before with the following changes:

  • Removed font from the selector of the first rule.  It’s been long enough now, I think.  We can let that one go.
  • Removed background: transparent from the declaration block of the first rule.  I don’t think it really served any purpose in the long run, given the way browsers style by default and the CSS-defined default for background-color (which background encompasses, of course).  Its removal will also stop causing table-appearance glitches in old versions of IE, if that’s of interest.
  • Added font: inherit to the declaration block of the first rule.  There are still older versions of IE that don’t understand inherit, but support is now widespread enough that I feel this can go in.  I left font-size: 100% as a sop to older browsers, and override it with the next declaration in those browsers that understand.
  • Added HTML5 elements to the selector of the first rule.  While this is probably unnecessary right now, those elements being about as styled as a common div, it’s in the spirit of the thing to list them.
  • A separate rule to make blocks of those HTML5 elements that generally default to blocks.  This is more backward-looking, as the comment suggests, and it’s a prime excision candidate for anyone adapting these styles to their own use.  However, if you’ve ever known the pain of HTML5 markup shattering layouts in, say, older versions of Firefox, this rule has a place.
  • Removed the “cellspacing” comment near the end.  It used to be the case that lots of browsers needed the support, but that’s a lot less true today.
  • And then the big one, trying to correct the biggest backfire of the whole enterprise: I commented out and subtly altered the commentary on the :focus rule without removing it entirely.

On that last point, defining an invisible focus was the biggest blunder of the original reset.  In hindsight, it’s really a obvious unforced error, but when I published the reset I literally had no conception that it would be just copied (or, worse, hotlinked) blindly in a thousand sites and frameworks.  As the new advocacy site outlinenone.com points out, I did say right in the style sheet that one should define a focus style.  I put in a value of 0 in the same spirit I zeroed out paragraph margins and set the body element’s line-height to 1: by taking everything to a “plain baseline”, the thoughtful craftsperson would be reminded to define the focus style that made most sense for their site’s design.

Instead, focus outlines were obliterated wholesale as lots and lots of people, not all of them craftsmen, just copied the reset and built on top of it without thinking about it.  I can’t find it in my heart to fault them: most construction workers don’t think about how beams and rivets or even riveters are made.  They just bolt ’em together and make a building.

Perhaps some of the pain would have been eased if I had said in the comment, as I do now, “remember to define visible focus styles”.  But I doubt it.

So in this revision, I’ve altered the rule and commentary to raise its visibility, but more importantly I’ve commented out the whole rule.  This time, copiers and hotlinkers won’t destroy focusing.  Some may still uncomment it and change the value back to 0, of course, but that could happen anyway.  With luck, this change will help educate.

As was the case in 2007, comments and suggestions are most welcome, and may well result in changes that make it into the final version.  Also, my thanks to the HTML5 Doctor crew for publishing their variant, which I used as a sanity check; and Michael Tuck, whose research into the history of resets got me looking back and interested in moving things forward.

Addendum 3 Jan 11:  as the previous paragraph says, and the version number (2.0b1) heavily implies, this is not a final version.  It may well change, either due to errors on my part (one of which has already come to light) or changes of mind due to discussions in the comments.  You can take this version and use it if you want, but I don’t particularly recommend it because—again—changes are likely.

Translations


Smashing CSS

Published 14 years, 6 months past
Smashing CSS cover

Well, I done did it again: I wrote a book.  This time, it’s Smashing CSS: Professional Techniques for Modern Layout, published by Wiley and Sons and available as of some time last week.  (Just in time for the holiday gift-giving season!  Buy one for everybody in the family!  Don’t delay—act now!)

What’s different about this book as compared to others I’ve written is that this is a collection of short tips, tricks, and techniques for using CSS in everyday work.  Many of them involve making changes and seeing the results, similar to my New Riders books, but where those books had chapter-long projects these are usually only a page or three in length.  Well, okay, a few get up towards ten pages, but only on occasion.

Another difference is that Smashing CSS spans the spectrum from basic tools and browser features that can speed your development and debugging to some cutting-edge ideas and a taste of the latest CSS3 hotness.  I really do hope there’s something in it for everyone, and with something like a hundred entries, I think my odds are pretty good.

I’m especially happy that it’s in full color, which allowed me to do lots of screenshots as well as color-hinting of the markup and CSS, and personally I think it looks awesome.  I hope you’ll agree.  Check out the official catalog page at Wiley or comparison-shop at ISBN.nu, and thanks!

Update 19 Nov 10:  Kindle, ePub, and PDF versions of the book should be available within the next week.  They’re all in the hands of Wiley’s ebook distributor, so now it’s up to the distributor to get the files into the hands of ebook sellers.  On behalf of all you ebook fans, I hope it will happen soon!  (Is “ebook” the way we write that now?  I’m a little light on the lingo.)

Update 6 Dec 10: So far I’ve found the Kindle (mobi) and Nook (ePub) versions of the book.  Finding a good (read: legal) PDF version is proving difficult, so if anyone’s seen it out there, let me know so I can link away!


Vendor Prefix Lists

Published 14 years, 8 months past

At the prompting of an inquiry from a respected software vendor, I asked The Twitters for pointers to “canonical” lists of vendor-prefixed properties, values, and selectors.  Here’s what the crowd sourced at me:

Lists more than just prefixed properties, values, and so on.

While there’s no guarantee of completeness or accuracy, these are at least what the vendors themselves provide and so we can cling to some hope of both.  I was also pointed to the following third-party lists:

If you know of great vendor-prefix lists that aren’t listed here, particularly anything from the vendors themselves, please let us know in the comments!

Somewhat if not obviously related: does anyone know of a way to add full Textile support to BBEdit 9.x?  Having it be a Unix filter is fine.  I know BBEdit already supports Markdown, but since Basecamp uses Textile and lots of people I work with use Basecamp, I’d like stick to one syntax rather than confuse myself trying to switch between two similar syntaxes.


In Defense of Vendor Prefixes

Published 14 years, 11 months past

…that having been the original working title for “Prefix or Posthack“, my latest article for A List Apart.  (Sort of like Return of the Jedi had a working title of Blue Harvest.)  In a fairly quick read, I make the case that vendor prefixes are not only good, they have the potential to be great and to deliver greater interoperability and advancement of CSS.

So far the reaction has been overwhelmingly positive, which frankly came as a bit of a surprise.  The annoyance factor of prefixes is undeniable, and it’s been my experience that annoyance dramatically hardens opposition regardless of whether or not there are good reasons to oppose.  I could flatter myself that the agreement is due to the Obvious Rightness of my argument, but I suspect it’s actually that I merely articulated what most people had already instinctively decided for themselves.  Which isn’t a bad place to be.

Anyway, if you haven’t already, feel free to decide for yourself by reading the article — which, I feel like mentioning for no clear reason, is only the fourth piece I’ve ever written for ALA.


Fixed Monospace Sizing

Published 15 years, 4 months past

Monospace text sizing is, from time to time, completely unintuitive and can be quite maddening if you don’t look at it in exactly the right way.  Fortunately, there is a pretty simple workaround, and it’s one you might want to consider using even if you weren’t aware that a problem existed.

But first, allow me to lay some foundations.  Assuming no other author styles beyond the ones shown, consider the following:

span {font-family: monospace;}

<p>This is a 'p' with a <span>'span'</span> inside.</p>
All right, what should be the computed font-size of the span element?  Remember, there are no other author styles being applied.

The savvier among you will have said: “It depends, but most likely 13px.”  That’s because here, the size of the monospace text is controlled by the browser’s preferences.  The vast majority of users, of course, have never touched their default settings of “16” for proportional fonts and “13” for monospace/fixed fonts.  For them, then, the answer is 13px.  Similarly, if I’d asked about the p element’s computed font-size, the answer would be: “It depends, but most likely 16px.”

So let’s add a bit more and see where we land.

span {font-family: monospace; font-size: 1em;}

<p>This is a 'p' with a <span>'span'</span> inside.</p>

As before: bearing in mind that there are no other author styles, what should be the computed font-size of the span element?

In this case, building on the previous question and answer, you might say, “It depends, but most likely 16px.”  The reasoning here is pretty straightforward:  since the computed font-size of the p element is 16px, the font-size: 1em; assigned to the span will result in it having the same size.

And that’s true… in two of five browsers I tested: Opera 10 and Internet Explorer 8.  In the other three I tested—Firefox 3.6, Safari 4, and Chrome 4—the computed (and rendered) font-size of the span is 13px, the same as in our first example.  This result holds true if the rule is changed to use font: 1em monospace; instead of the two separate properties.  The behavior continues to persist even when adding specific font families, like Courier New, Courier, Andale Mono, and so on to the rule.  It also persists if 1em is converted to 100%.

So in other words, even though I have written CSS that explicitly says “Make the font-size of this element the same as its parent”, three of five browsers apparently ignore me.

I say “apparently” because what’s happening is that those browsers are allowing the span to inherit the default font-size from its parent (and thus, indirectly, all its ancestors), but the default font-size is medium.  If you go look up medium, you find out that it doesn’t have a defined numeric size. So what those browsers do is equate medium with the preference settings, which means it’s different for monospace fonts than for everything else.

In other words, those three browsers are doing something like this:

  1. This span needs to have the same font-size as its parent element.
  2. The parent’s font-size is medium, even though when my web inspector (or an author’s DOM script) asks, I report the 16px I used to output the text.  So the span‘s font-size is actually medium.
  3. This medium-sized span is using a monospace font.  The preference setting for monospace is “13”, and I equate medium with the preference setting, so I’ll output the span using 13-pixel text.

Opera 10, as I said, doesn’t do this, even if your monospace font preference setting is the default value of “13” or indeed different from the preference for non-monospace fonts.  And IE8 doesn’t appear to do it either, although you can’t set numeric font size preferences in IE8 so what it’s actually doing is open to interpretation.  Oh, IE8, you inscrutable little scamp, you.

All that might seem reasonable enough, but it turns out that’s not the whole story.  No, the three resizing browsers are being a good deal more “clever”, if that’s actually the word I want, than that.  In fact, what those browsers do makes it seem like they use the two preference settings to create a ratio, and that ratio is used to scale monospace text.  That’s not actually what’s happening, but it looks that way at first.  To see what I mean, let’s consider:

span {font-family: monospace; font-size: 2em;}

<p>This is a 'p' with a <span>'span'</span> inside.</p>

Again: in the absence of other author styles, what should be the computed font-size of the span element?

The answer: “It depends, but most likely 26px as long as we aren’t talking about Opera 10 or IE8.  If it is one of those two, then most likely 32px.”  Why?  Because the resizing browsers see the font-size: 2em; declaration as “twice medium” and twice 13 is 26.  Opera 10 and IE8, as previously established, don’t do the resizing.  Or else they simply interpret medium as being equal to the proportional font size preference setting.  Whatever.

Okay.  So what all this means is that in many browsers, you can declare that an element’s font size should be twice the size of its parent’s and have it actually be 1.625 times the size — or, if you want to look at it another way, 0.8125 times the size you expected it to be.  The 0.8125 comes from 26/32, which of course reduces to 13/16.  If you were to adjust your browser’s preferences so the monospace setting is “15”, then monospace fonts would be 0.9375 (15/16) times the expected size.

But — and here’s where things get really fun — this is not always so.  See, you may not have run into this problem if you’ve been declaring specific font families with no generic fallback.  Consider this variation (note that I dropped back to 1em for the font-size):

span {font-family: "Courier New"; font-size: 1em;}

<p>This is a 'p' with a <span>'span'</span> inside.</p>

This time, in every one of the five browsers I mentioned before, assuming the browser defaults, the computed (and rendered) font-size of the span will be 16px.  Not 13px.  And the only difference is that we switched from a generic font family to a specific one.

“Hey presto!” you shout.  “We’ll just tack the generic family on the end there and be right as rain!”  Sadly, no.  For if you do this:

span {font-family: "Courier New", monospace; font-size: 1em;}

<p>This is a 'p' with a <span>'span'</span> inside.</p>

…then the answer to the question I keep asking will be:  “It depends, but given browser defaults it will be 16px, unless we’re talking about Safari.  In that case, it’s 13px.”

Really.  Alone among the browsers I tested, Safari goes back to doing the resizing when you provide a generic fallback to your specific family.  Or even multiple families.  Do your best to make sure the user at least gets a fixed-width font, and you get a size smaller than you’d intended.  (You can get the back story on this in a late-2006 post on the Surfin’ Safari blog.)

So what do we do?  Get creative.  That’s what the ARIA folks did in their specification’s style sheet, where they declare two font stacks: the first with a generic fallback, and the second without it.  That works, but it’s ugly.  I didn’t like that at all.  And then, halfway through writing up this post, a fix came to me like a shot in the dark.  Check this out:

span {font-family: "Courier New", monospace, serif; font-size: 1em;}

<p>This is a 'p' with a <span>'span'</span> inside.</p>

This time around, the answer is:  “It depends, but given browser defaults, 16px.”

Really!  Even in Safari!  And in all tested browsers, it falls back to a generic monospace font at the requested size even if the specific family (or families) we declare aren’t available!  This can be verified by altering the specific font family to something that doesn’t actually exist:

span {font-family: "Corier Neu", monospace, serif; font-size: 1em;}

<p>This is a 'p' with a <span>'span'</span> inside.</p>

Monospacey goodness at the intended, parent-matching size.  It’s enough to make a body believe in monotheism.

Since I generally assume that anything I devise was already invented by someone else, I went Googling for prior art.  And wouldn’t you know it, the Wikipedia folks had worked it out around the end of last year.  This, of course, supports my contention that Wikipedia is the new Steve Allen.  I also found some claims that ending the font stack with monospace, monospace would have the same effect, but that wasn’t borne out in my testing.  Perhaps it worked in older versions of browsers but no longer does.

I did leave out another way to make monospaced fonts behave as expected, which you may have already figured out from the preceding: declare the font-size for any parent of a monospaced element to be a length value, along the lines of body {font-size: 12px;}.  That will pass the length value down the document tree to the monospaced element via inheritance, which will use it without resizing it in every browser I tested.  Though you may have heard that page zooming makes pixel-sized text okay, I’m not really convinced.  Not yet.  There are too many people who don’t know how to zoom, and too many whose browsers aren’t advanced enough to zoom pages.  Even in page-zooming browsers, there are problems with pixel text.  So I’m still on the ems-and-percentages bandwagon.

In fact, there are a fair number of details and extra browser oddities that I left out of this, as it’s already way more than long enough, and besides you don’t really want to hear the gory details of manually stepping through 37 different preferences settings just to verify a theory.  Plus you already heard about the font-size rounding investigation that spawned off of this one, about halfway through.  I think that’s more than enough for the time being.

I should also lay down a caveat: it’s possible that this behavior will be interpreted as a bug by the Safari team and “fixed”, if that’s the word I want, in a future release.  I really hope not — and if they’re looking for ways to improve how they handle monospace font sizing, I have a few suggestions — but it is possible.  Adjust your expectations accordingly.

And with that, I’m going to stop now.  I hope this will be useful to you, either now or in the future.


Rounding Off

Published 15 years, 4 months past

In the course of digging into the guts of a much more complicated problem, I stumbled into an interesting philosophical question posed by web inspection tools.

Consider the following CSS and HTML:

p {font-size: 10px;}
b {font-size: 1.04em;}

<p>This is text <b>with some boldfacing</b>.</p>

Simple enough.  Now, what is the computed font-size for the b element?

There are two valid answers.  Most likely one of them is intuitively obvious to you, but take a moment to contemplate the rationale for the answer you didn’t pick.

Now, consider the ramifications of both choices on a situation where there are b elements nested ten layers deep.

If you hold that the answer is 10px, then the computed font-size of the tenth level of nesting should still be 10px, because at every level of nesting the mathematical answer will be rounded down to 10.  That is: for every b element, its computed font-size will be round(10*1.04), which will always yield 10.

If, on the other hand, you hold that the answer is 10.4px, then the computed font-size of the tenth level of nesting should be 14.802442849px.  That might get rounded to some smaller number of decimal places, but even so, the number should be pretty close to 14.8.

The simplest test, of course, is to set up a ten-level-deep nesting of b elements with the previously-shown CSS and find out what happens.  If the whole line of text is the same size, then browsers round their computed font-size values before passing them on.  If the text swells in size as the nesting gets deeper, then they don’t.

As it happens, in all the browsers I’ve tested, the text swells, so browsers are passing along fractional pixel values from level to level.  That’s not the interesting philosophical question.  Instead, it is this:  do web inspectors that show integer font-size values in their ‘computed style’ windows lie to us?

To see what I mean, load up the font size rounding test page in Firefox and use Firebug to inspect the “1(“, which is the first of the b elements, in the first (1.04em) test case.  Make sure you’re looking at the “Computed Styles” pane in Firebug, and you’ll get a computed font-size of 10.4px.  That makes sense: it’s 10 × 1.04.

Now try the inspecting that same “1(” in Safari or Opera.  Both browsers will tell you that the computed font-size of that b element is 10px.  But we already know that it’s actually 10.4px, because the more deeply-nested layers of b elements increase in size.  These inspectors are rounding off the internal number before showing it to us.  Arguably, they are lying to us.

But are they really?  The reason to doubt this conclusion is that the values shown in those inspectors accurately reflect the value being used to render the characters on-screen.  To see what I mean, look at the last example on the test page, where there’s sub-pixel size testing.  The “O” characters run from a flat 10 pixels to a flat 11 pixels in tenths (or less) of a pixel, all of their font-sizes assigned with inline style elements to pin the characters down as much as possible.  In Safari, you can see the size jump up one pixel right around the text’s midpoint, where I wrote font-size: 10.5px.  So everything from 10px to 10.49px gets drawn at 10 pixels tall; everything from 10.5px to 11px is 11 pixels tall.  Safari’s inspector reflects this accurately.  It’s telling you the size used to draw the text.

A comparative illustration of the many-O test case in three different browsers showing three different results.  The browsers used to create the illustration were Safari, Opera, and Firefox.

In Opera 10.10, you get the same thing except that the jump from 10 to 11 pixels happens on the very last “O”, both visually and in the inspector (Dragonfly).  That means that when it comes to font sizes, Opera always rounds down.  Everything from 10px to 10.9px — and, presumably, 10.99999px for as many nines as you’d care to add — will be drawn 10 pixels tall.  Brilliant.

In Firefox for OS X, there’s no size jump.  The “O” characters look like they form a smooth line of same-size text.  In fact, they’re all being drawn subtly differently, thanks to their subtly different font-size values.  If you use OS X’s Universal Access screen zooming to zoom way, way in, you can see the differences in pixel shading from one “O” to the next.  Even if you don’t, though, the fact that it’s hard to tell that there is an increase in size from one end of the line to the other is evidence enough.

In Firefox for XP, on the other hand, the size jump occurs just as it does in Safari, going from 10 pixels to 11 pixels of text size at the 10.5 mark.  But Firebug still reports the correct computed font-size values.  Thus, its reported value doesn’t match the size of the text that’s been output to the screen.  Arguably, it’s lying just as much as Safari and Opera,  in a different way.

But, again: is it really?  The computed values are being accurately reported.  That there is a small variance between that fractional number and the display of the text is arguably irrelevant, and can lead to its own confusion.  Situations will arise where apparent rounding errors have occurred — I see people complain about them from time to time — when the apparent error is really an artifact of how information is delivered.

I have my own thoughts about all this, but I’m much more interested in the thoughts of others.  What do you think?  Should web inspectors report the CSS computed values accurately, without regard to the actual rendering effects; or should the inspectors modify the reported values to more accurately reflect the visual rendering, thus obscuring the raw computed values?

Addendum 10 Feb 10: I’ve updated the test page with a JS link that will dynamically insert the results of getComputedStyle(el,null).getPropertyValue("font-size") into the test cases.  The results are completely consistent with what the inspectors report in each browser.  This tells us something about the inspectors that most of us probably don’t consciously realize: that what they show us rests directly on the same JS/DOM calls we could write ourselves.  In other words, inspectors are not privileged in what they can “see”; they have no special view into the browser’s guts.  Thus another way to look at this topic is that inspectors simply repeat the lies that browsers tell the world.


Pseudo-Phantoms

Published 15 years, 7 months past

In the course of a recent debugging session, I discovered a limitation of web inspectors (Firebug, Dragonfly, Safari’s Web Inspector, et al.) that I hadn’t quite grasped before: they don’t show pseudo-elements and they’re not so great with pseudo-classes.  There’s one semi-exception to this rule, which is Internet Explorer 8’s built-in Developer Tool.  It shows pseudo-elements just fine.

Here’s an example of what I’m talking about:

p::after {content: " -\2761-"; font-size: smaller;}

Drop that style into any document that has paragraphs.  Load it up in your favorite development browser.  Now inspect a paragraph.  You will not see the generated content in the DOM view, and you won’t see the pseudo-element rule in the Styles tab (except in IE, where you get the latter, though not the former).

The problem isn’t that I used an escaped Unicode reference; take that out and you’ll still see the same results, as on the test page I threw together.  It isn’t the double-colon syntax, either, which all modern browsers handle just fine; and anyway, I can take it back to a single colon and still see the same results.  ::first-letter, ::first-line, ::before, and ::after are all basically invisible in most inspectors.

This can be a problem when developing, especially in cases such as having a forgotten, runaway generated-content clearfix making hash of the layout.  No matter how many times you inspect the elements that are behaving strangely, you aren’t going to see anything in the inspector that tells you why the weirdness is happening.

The same is largely true for dynamic pseudo-classes.  If you style all five link states, only two will show up in most inspectors—either :link or :visited, depending on whether you’ve visited the link’s target; and :focus.  (You can sometimes also get :hover in Dragonfly, though I’ve not been able to do so reliably.  IE8’s Developer Tool always shows a:link even when the link is visited, and doesn’t appear to show any other link states.  …yes, this is getting complicated.)

The more static pseudo-classes, like :first-child, do show up pretty well across the board (except in IE, which doesn’t support all the advanced static pseudo-classes; e.g., :last-child).

I can appreciate that inspectors face an interesting challenge here.  Pseudo-elements are just that, and aren’t part of the actual structure.  And yet Internet Explorer’s Developer Tool manages to find those rules and display them without any fuss, even if it doesn’t show generated content in its DOM view.  Some inspectors do better than others with dynamic pseudo-classes, but the fact remains that you basically can’t see some of them even though they will potentially apply to the inspected link at some point.

I’d be very interested to know what inspector teams encountered in trying to solve this problem, or if they’ve never tried.  I’d be especially interested to know why IE shows pseudo-elements when the others don’t—is it made simple by their rendering engine’s internals, or did someone on the Developer Tool team go to the extra effort of special-casing those rules?

For me, however, the overriding question is this: what will it take for the various inspectors to behave more like IE’s does, and show pseudo-element and pseudo-class rules that are associated with the element currently being inspected?  And as a bonus, to get them to show in the DOM view where the pseudo-elements actually live, so to speak?

(Addendum: when I talk about IE and the Developer Tool in this post, I mean the tool built into IE8.  I did not test the Developer Toolbar that was available for IE6 and IE7.  Thanks to Jeff L for pointing out the need to be clear about that.)


Handling an Explicit-Width Bug in Internet Explorer

Published 16 years, 2 months past

In creating the combo-bar charts for the survey report, I stumbled into an Explorer bug that I didn’t remember ever seeing before, and Google didn’t turn up anything that seemed to be related.  This could easily mean that I’m the only person who ever did something this insane and thus found the bug.  It could just as easily mean that my Google-fu has failed.  Either way, I’ll write it up here so it can enter the collective memory.  (And surely someone has already noted that Google is positively Jungian?)

You can see both the problem and two workarounds if you visit this test page using IE6 or IE7.  In brief, the problem occurred when I had a table cell containing a paragraph with an explicit width set.  I did this through the style attribute, though tests show that for this bug, it doesn’t matter whether you use the attribute or assign it via a style sheet.  Around these explicit-width paragraphs were div elements with width: 200%;, for bar-drawing purposes (it’s a little complicated).  Everything was fine in 99% of cases.  But as soon as the header text at the beginning of the row went to two lines of text, the explicit-width paragraphs doubled in width.  What was 80.1% wide would be drawn as though it were 160.2% wide.

My hopefully understandable reaction was to say, “Whuh?”.  I threw a few hasLayout triggers at the offending paragraph (relative position, zoom, etc.) and got nowhere.  In the end I worked around the problem by telling IE6 and IE7 to not wrap text in the row headers of combo charts.  (The bug is not present in IE8.)

I mentioned all this in my announcement post, and the ever-awesome Dan Wilkinson discovered that the problem could be fixed by setting all of the table rows to, say, height: 3em.  Armed with that breakthrough, I experimented a little more and found that I could actually set the offending table row’s height to 2.75em and still have things work as intended.  Below that and the paragraph widths doubled.

Then I lowered the line-height of the headers to 1 and found that I could take the overall row’s height as low as 2.33em before triggering the bug.  And that’s when it dawned: the bug was triggered by the layout height of the header cell’s content being taller than the content of the cell containing the paragraph, and not explicitly declaring styles that would make the data cell as tall as or taller than the height needed to have the header cell contain its content.

Okay, that’s a little dense.  Let me step through the symptoms and two found workarounds to see if that clears it up:

  1. The data cell always has a single line of text.  The bug is triggered by having the header cell go to two lines of text, whereas it is not if the header cell has a single line of text.
  2. If the row’s height is explicitly set to a value equal to or greater than the header cell’s content, the bug is not triggered.
  3. Alternatively, if the height of the data cell is set or forced to be equal to or greater than the height of the header cell, the bug is not triggered.  This can be done with an explicit height or with added top and bottom padding or by adding top and bottom margins to the paragraphs in the cell.

Some side tests I did indicate that the header cell is not needed to trigger the bug.  In other words, the problem could happen even if there are only data cells in the row.  Furthermore, I found that the width-scaling was directly affected by the width of the wrapping div, and thus the widths were doubling only because I had the div‘s width set to 200%.  If I set it to 150% instead of 200%, then the paragraphs only got half again as wide instead of doubling.  That seems to make sense until you see it in action.  When I say the paragraphs got half again as wide, I mean that instead of being 75% as wide as the div, they were 112.5% as wide as the div.  If I set the div‘s width to 200%, then they were 150% the width of the div.

So.  As I say, this bug does not affect IE8, so that’s good, and it can be worked around in IE6 and IE7, which is even better.  The problem would be if you didn’t know how tall your cells might get—in my case, I can be (reasonably) sure that the tallest a cell’s content will ever get is two lines of text, and by setting an explicit line-height on the headers I can know how tall I have to make the rows in order to avoid the bug.

Another day, another workaround!


Browse the Archive

Earlier Entries

Later Entries