Posts in the CSS Category

line-height: abnormal

Published 16 years, 6 months past

When I first wrote Cascading Style Sheets: The Definitive Guide, the part that caused me the most difficulty and headaches was the line layout material.  Several times I was sure I had it all figured out and accurately described, only to find out I was wrong.  For two weeks I corresponded with Ian Hickson and David Baron, arguing for my understanding of things and having them show me, in merciless detail, how I was wrong.  I doubt that I will ever stop owing them for their dedication to getting me through the wilderness of my own misunderstandings.

Later on, I produced a terse description of line layout which went through a protracted vetting process with the CSS Working Group and the members of www-style.  At the time it was published, there was no more detailed and accurate description of line layout available.  Even at that, corrections trickled in over the years, which made me think of it as my own tiny little The Art of Computer Programming.  Only without the small monetary reward for finding errors.

The point here is that line layout is very difficult to truly understand—even given everything I just said, I’m still not convinced that I do—and that there are often surprises lurking for anyone who goes looking into the far corners of how it happens.  As I’ve said before, my knowledge of what goes into the layout of lines of text imparts a sense of astonishment that any page can be successfully displayed in less than the projected age of the universe.

Why bring all this up?  Because I went and poked line-height: normal with a stick, and found it to be both squamous and rugose.  As with all driven to such madness, I now seek, grinning wildly, to infect others.

Here’s the punchline: the effects of declaring line-height: normal not only vary from browser to browser, which I had expected—in fact, quantifying those differences was the whole point—but they also vary from one font face to another, and can also vary within a given face.

I did not expect that.  At least, not consciously.

My work, let me show it to you: a JavaScript-driven test file where you can pick from a list of fonts and see what happens at a variety of sizes.  (Yes, the JS is completely obtrusive; and yes, the JS is the square of amateur hour.  Let’s move on, please.  I’m perfectly happy to replace what’s there with unobtrusive and sharper JS, as long as the basic point of the page, which is testing line-height: normal, is not compromised.  Again, moving on.)

When you first go to the test, you should (I hope) see a bunch of rulered boxes containing text using the very common font face Webdings, set at a bunch of different font sizes.  The table shows you how tall the simple line boxes are at each size, and therefore the numeric equivalent for line-height: normal at those sizes.  So if a line box is using font-size: 50px and the line box is 55 pixels tall, the numeric equivalent for line-height: normal is 1.1 (55 divided by 50).

On my PowerBook, Webdings always yields a 1:1 ratio between the font-size and line box height.  The ten-pixel font size yields a ten-pixel-tall line box, and so on.

This is actually a little surprising by itself.  The CSS 2.1 specification says:

normal
Tells user agents to set the used value to a “reasonable” value based on the font of the element. The value has the same meaning as <number>. We recommend a used value for ‘normal’ between 1.0 to 1.2. The computed value is ‘normal’.

This is basically what CSS has said since its first days (see the equivalent text in CSS1 or in CSS2 for confirmation) and there’s always been a widespread assumption that, since 1.0 is probably too crowded, something around 1.2 is much more likely.

So finding a value of 1 was a surprise.  It was an even bigger surprise to me that this held true in Camino 1.5.2, Firefox 2.0.0.14, and Safari 2.0.4, all on OS X.  Firefox 3b5 didn’t render Webdings at all, so I don’t know if it would do the same.  I actually suspect not, for reasons best left for another time (and, possibly, a final release of Firefox 3).

Various browsers doing the same thing in an under-specified area of the spec?  That can’t be right.  It’s pretty much an article of faith that given the chance to do anything differently, browsers will.  The sailing was so unexpectedly smooth that I immediately assumed was that a storm lurked just over the horizon.

Well, I was right.  All I had to do was start picking other font faces.

To start, I picked the next font on the list, Times New Roman, and the equivalent values for normal immediately changed.  In other words, the numeric equivalents for Times New Roman are different than those for Webdings.  The browsers weren’t maintaining a specific value for normal, but were altering it on a per-face basis.

Now, this is legal, given the way normal is under-specified.  There’s room to allow for this behavior.  It’s actually, once you think about it, a fairly good thing from a visual point of view: the best default line height for Times New Roman is probably not the best default line height for Courier New.  So while I was initially surprised, I got over it quickly.  The seemingly obvious conclusion was that browsers were actually respecting the fonts’ built-in metrics.  This was reinforced when I found that the results were exactly the same from browser to browser.

Then I looked more closely at the numbers, and confusion set back in.  For Times New Roman, I was getting values of 1.1, 1.12, 1.16, 1.15, 1.149, and 1.1499.  If you were to round all of those numbers to two decimal points, you’d get 1.10, 1.12, 1.16, 1.15, 1.15, 1.15.  If you round them all to one decimal place, you’d get 1.1, 1.1, 1.2, 1.2, 1.1, 1.1.  They’re inconsistent.

But wait, I thought, I’m trying to compare numbers I derived by dividing pixels by pixels.  Let’s turn it around.  If I multiply the most precise measurement I’ve gotten by the various font sizes, I get… carry the two… 11.499, 28.7475, 57.495, 114.99, 1149.9, 11499.  As compared to the actual values I got, which were 11, 28, 58, 115, 1149, and 11499.

Which means the results were inappropriately rounded up in some cases and down in others.  28.7475 became 28 and 1149.9 became 1149, whereas 57.495 became 58.  Even though 11.499 became 11 and 114.99 became 115.

This was consistent across all the browsers I was testing.  So again, I was suspecting the fonts themselves.

And then I switched from Times New Roman to just plain old Times, and the storm was full upon me.  I’ll give you the results in a table.

Derived normal equivalents for Times in OS X browsers
font-size Camino 1.5.2 Firefox 2.0.0.14 Safari 2.0.4
10 1 1.2 1.3
25 1 1 1.16
50 1 1 1.18
100 1 1 1.15
1000 1 1 1.15
10000 1 1 1.15

Much the same happened when comparing Courier New with plain old Courier: full consistency on Courier New between browsers, albeit with the same strange (non-)rounding effects as seen with Times New Roman; but inconsistency between browsers on plain Courier—with Camino yielding a flat 1 down the line, Firefox going from 1.2 to 1, and Safari having a range of values above the others’ values.

Squamous!  Not to mention rugose!

Now it’s time for the stunning conclusion that derives from all this information, which is: not here.  Sorry.  So far all I have are observations.  I may turn all this into a summary page which shows the results for all the font faces across multiple browsers and platforms, but first I’ll need to get those numbers.

I do have a few speculations, though:

  1. Firefox’s inconsistency within font faces (see Times and Courier, above) may come from face substitution.  That’s when a browser doesn’t have a given character in a given face, so it looks for a substitute in another face.  If Firefox thinks it doesn’t have 10-pixel Times, it might substitute 10-pixel something else serif-ish, and that face has different line height characteristics than Times.  I don’t know what that other face might be, since it’s not Times New Roman or Georgia, but this is one possibility.  It is not the minimum font size setting in the preferences, as I’ve triple-checked to make sure I have that set to “None”.

  2. Another possibility for Firefox’s line height weirdness is a shift from subpixel font rendering to pixelly font rendering.  10-pixel text in Firefox is distinctly pixelly compared to the other browsers I tested, while sizes above there are nice and smooth.  Why this would drive up the line height by two pixels (20%), though, is not clear to me.

  3. Much of what I’ve observed will likely be laid to rest at the doorsteps of the font faces themselves.  I’d like to know how it is that the rounding behaviors are so (mathematically) messed up within faces, though.  Perhaps ideal line heights are described as an equation rather than a simple ratio?

Again, this was all done in OS X; I’ll be very interested to find out what happens on Windows, Linux, and other operating systems.  Side note for the Mac Opera fans warming up their flamethrowers: I’ve left Opera 9.27 for OS X out of this because it seems to cap font sizes at a size well below 1000, although this limit varied from one face to another.  Webdings and Courier capped at 507 pixels, whereas Courier capped at 574 pixels and Comic Sans MS stopped at 707 pixels.  I have no explanation, though doubtless someone will, but the upshot is that direct comparisons between Opera and the other browsers are impossible.  For sizes up to 100 pixels, the results were exactly consistent with Camino, if that means anything.

The one tentative conclusion I did reach is this: line-height: normal is a jumbled terrain of inconsistent behaviors, and it’s best avoided in any sort of precision layout work.  I’d already had that feeling, but at least now there’s some evidence to back up the feeling.

In any case, I doubt this is the last I’ll have to say on this particular topic.

Update 7 May 08: I’ve updated the test page with a fix from Ben Lowery so that it works in IE.  Thanks, Ben!  Now all I need is to add a way to type in any arbitrary font-family’s name, and we’ll have something everyone can use.  (Or else a way to use JavaScript to suck up the names of all the fonts installed on a machine and put them into the dropdown.  That would be cool, too.)


Crafting Ourselves

Published 16 years, 7 months past

My referrers lit up recently due to Jonathan Snook’s article about CSS resets and how he doesn’t use them.  To Jonathan and all the doubters and nay-sayers out there, I have only one thing to say:

Good for you.

Seriously; no sarcasm or passive-aggressiveness intended.  If I thought my reset styles, or really anything I’ve ever published or advocated, was a be-all end-all ultimate solution for every designer and design that’s ever been and could ever be, I’d be long past due for six rounds on the receiving end of a clue-by-four.

Reset styles clearly work for a lot of people, whether as-is or in a modified form.  As I say on the reset page, those styles aren’t supposed to be left alone by anyone.  They’re a starting point.  If a thousand people took them and created a thousand different personalized style sheets, that would be right on the money.  But there’s also nothing wrong with taking them and writing your own overrides.  If that works for you, then awesome.

For others, reset styles are more of an impediment.  That’s only to be expected; we all work in different ways.  The key here, and the reason I made the approving comment above, is that you evaluate various tools by thinking about how they relate to the ways you do what you do—and then choose what tools to use, and how, and when.  That’s the mark of someone who thinks seriously about their craft and strives to do it better.

I’m not saying that craftsmen/craftswomen are those people who reject the use of common tools, of course.  I’m saying that they use the tools that fit them best and modify (or create) tools to best fit them, applying their skills and knowledge of their craft to make those decisions.  It’s much the same in the world of programming.  You can’t identify a code craftsman by whether or not they use this framework or that language.  You can identify them by how they decide which framework or language to use, or not use, in a given situation.

Craftsmanship is something I’ve been thinking about quite a bit recently, as has Joshua Porter.  I delivered a keynote address on that very topic just a few days ago in Minneapolis, and my thinking infuses both of the talks I’m giving next week at An Event Apart New Orleans.  I’ve started looking harder for evidence of it, both in myself and in what I see online, and I believe striving toward being a craftsman/craftswoman is an important process for anyone who chooses to work in this field.

Because this isn’t a field of straightforward answers and universal solutions.  We are often faced with problems that have multiple solutions, none of them perfect.  To understand what makes each solution imperfect and to know which of them is the best choice in the situation—that’s knowing your craft.  That’s being a craftsman/craftswoman.  It’s a never-ending process that is all the more critical precisely because it is never-ending.

So it’s no surprise that we, as a community, keep building and sharing solutions to problems we encounter.  Discussions about the merits of those solutions in various situations are also no surprise.  Indeed, they’re exactly the opposite: the surest and, to me, most hopeful sign that web design/development continues to mature as a profession, a discipline, and a craft.  It’s evidence that we continue to challenge ourselves and each other to advance our skills, to keep learning better and better how better to do what we love so much.

I wouldn’t have it any other way.


Notacon: Not to be Missed

Published 16 years, 8 months past

In just under a couple of weeks, the fifth annual NOTACON will be held right here in beautiful Cleveland, Ohio.  You’re going, I know; you’re super-über-cool like that, and you don’t need to be reminded of your coolness.  But I’d like to mention the show here for posterity, so that our descendants will know just how completely they missed out.

Notacon straddles, like a Colossus built entirely out of recycled motherboards, backtech chips, and loops of soldering wire, the middle ground between regular conferences and BarCamps (though Notacon predates BarCamp by a couple of years).  It’s not free to attend, but it is very inexpensive.  What it lacks in slick advertising and corporate sponsors, it makes up ten times over in raw, unfiltered geekiness and fascinating material.  This is the kind of event where presenters will hold forth on the depths of digital security, the physics of wireless networking, homebrew chip architecture, the coolness of HyperCard, online society dynamics, and more.  There’s a running contest called Anything but Ethernet, where you get bonus points for having one of the links in your network architecture incorporate barbed wire.

Yeah.  It’s like that.

The speakers will be as wildly diverse as the audience.  The lead engineer for the C64 Direct-to-TV (a C64 in a joystick!); the man behind The Daily WTF; some of the folks putting out 2600 magazine; the woman behind CrochetMe.com; and many more.  I’ll be there as well, talking about the bleeding edge of CSS and web design, ripping apart some recent projects of mine at top speed while discussing where I think we’ll be in three years.  Plus Drew Curtis of FARK fame will be back, as he always is, this year sponsoring a FARK party.  The mind fairly boggles.  Boggles!

As you’re no doubt gathering by now, it’s hard to describe Notacon in a quick, concise summary—and that’s a big part of what makes it so awesome.  For my contemporaries: see you there!  To you future historians: okay, you missed out, but drop everything right now to find out when the next one is and I’ll see you there!


CSS Tools: Reset and Diagnostics

Published 16 years, 9 months past

I’ve hinted and teased and promised, and I’ve yet to make good on any of it.  I’m sorry.  Can I make it up to you?

Okay, then, here you go: a permanent home for my reset styles.  It takes up residence in a new “CSS” subsection of the Toolbox section of the site, along with my efforts to create a generic set of diagnostic styles.  In the case of the resets, I’ll increment the version number and date whenever I make changes, and probably maintain an archive of previous versions.  Not that I expect that to happen with any frequency, but you never know.

The diagnostics are a lot more experimental and thus aren’t so formal as to have things like version numbers.  If I change anything of specific interest there, I’ll try to write a post about it.  I should get around to writing about the shown-in-page stylesheet one of these days, though I figure anyone can view source and work out the particulars without too much effort.


Non-Quotidian Problems

Published 16 years, 9 months past

After I published the latest iteration of the reset styles, Paul Chaplin pointed out that my simplification of the quote-suppressing rules actually broke the intended effect in Safari 2, Gecko variants , and so on.  This happened because I assumed support for quotes: none, and it just isn’t there in most browsers.  Apparently, I was testing IN THE FUTURE! that day.

“Well, no problem,” I thought to myself, “I’ll use content: none instead”.  Nope.  Even in browsers that support generated content, support for the content value none appears to have fallen through the cracks.  Using it completely fails to suppress the generation of content, so far as my testing can determine.  Even more amusingly, content: normal prevents the insertion of quotation marks in Camino (and probably other Geckos), but not Safari.

So we’re back to explicitly forcing the assignment of empty content boxes in order to stop the insertion of quote marks: content: '';.  Oh, joy.  Paul had come to the same conclusion, and worked out a nice little fallback set that reminds me of the cursor trick that gets you a hand-pointing icon in both IE and the rest of the world, only his trick is completely valid.  So I’ll be adding that in, along with some thanks to Paul.

For my next magic trick, maybe I’ll base a reset rule on :nth-child() and see what people invent to simulate the intended effect.


Structured Timeline

Published 16 years, 10 months past

I wasn’t going to do it.  It would take too long, draw too much energy and attention.  Too many other things needed to be done first.  But it tasked me.  It tasked me!

So: here’s a browser timeline built out of a table.  I’ll say it now: this does not work in IE6 and IE7.  I’m not sure it’s possible to do, at least not cleanly, given the markup I used.  I’ll explain what I mean in a bit.

In order to structure this data, a table seemed to make the most sense, although even it wasn’t perfect.  There really wasn’t anything that seemed an exact fit, to be honest.  Definition lists didn’t really fit the bill (is a browser defined by its release dates?).  Plain old (un)ordered lists were a little better, but not enough.  In the end I just kind of ran with the idea that time sat on one axis and browsers sat on the other axis—like a table.

Given that decision, I needed to decide exactly how to group the data.  After a moments’ thought, I decided that I wanted to group the release dates by browser instead of by year.  Given the way tables are structured, that means every row corresponds to a browser, each data cell in the row represents a year, and the contents of each cell are the versions released in that year.

So here’s an example of a table row:

<tr title="Internet Explorer for Windows">
<th scope="row">
   <img src="icons/msie.png" alt="Internet Explorer for Windows" />
</th>
<td class="y1996"><p title="August 1996">3.0</p></td>
<td class="y1997"><p title="October 1997">4.0</p></td>
<td class="y1998"></td>
<td class="y1999"><p title="March 1999">5.0</p></td>
<td class="y2000"><p title="July 2000">5.5</p></td>
<td class="y2001"><p title="August 2001">6.0</p></td>
<td class="y2002"></td>
<td class="y2003"></td>
<td class="y2004"></td>
<td class="y2005"></td>
<td class="y2006"><p title="October 2007">7.0</p></td>
<td class="y2007"></td>
<td class="y2008"></td>
<th class="end"></th>
</tr>

(And yes, that’s drawn straight from the example, with no simplification and very minimal formatting.  I really wanted to pare the markup down as far as I could.)

The other choice was to have each row represent a year, and each cell represent a browser.  The non-graphical Wikipedia timeline has each row represent a month, not a year, but same general idea.  I totally understand why the Wikipedia timeline is top-to-bottom: it’s much, much easier to update and have render within the Wikipedia layout.  A new month is a new row in the table.  Easy peasy.  Fair enough, but I’m not here to do what’s easy.

Then there was the question of how to structure the version numbers within each year.  I resisted using ordered lists because in most cells there would be only one version number, and there’s nothing in the world of semantic markup that rubs me the wrong way more than a one-item list.  So I went with paragraphs.  I don’t particularly like that either, but short of inventing my own elements and writing a new DTD to support them, I couldn’t come up with much better.

One thing I’m still uncertain about is my decision to title the dates while having the actual content be only the version numbers.  Would it be better to put the dates into content and wrap distinct elements around the date and version numbers?  I’m honestly not sure.

Anyway, having settled on that structure, I had to answer the question of what to put on which axis in the layout.  Should I put the axis of time across the top, as I did originally; or down the side, as in the non-graphical Wikipedia timeline?  Put another way, should the timeline layout be horizontal or vertical?

I went with horizontal.  For whatever reason, I have a strong preference toward timelines scrolling left-to-right, not top-to-bottom.  Yes, even though it invokes that dread abomination, the horizontal scrollbar.  As it happened, given my structural decision, the same effect occurs even in an “unstyled” state.  If I’m just looking at the table with no author styles applied, I see the browsers down the left and the time across the top, proceeding from past to future from left to right.  That might seem convenient from a final layout point of view, except for the fact that I ended up completely ripping the table apart and, in effect, reassembling it with positioning.  This wouldn’t have been necessary had browsers allowed table cells to become containing blocks when they’re set to position: relative.  But they didn’t.

Frankly, I don’t have room here to go through all of the techniques I used and decisions I made.  Doing so would probably require a very long article, or else a very small book.  I did want to spotlight a few things:

  • In keeping with my desire to minimize the markup, I cut way back on classes.  In fact, the only classes I use indicate which year a cell represents, such as y1999, and end to indicate that a cell is at the end of a row.  (I could have dropped all those classes as well, but chose to keep them for reasons too varied to explain here.)  The paragraphs containing the version numbers, as an example, are completely unclassed, nor do they have IDs.  And yet I was still able to position them appropriately within each year.  How?  Check the markup sample to see if you can figure it out; I’ll give the answer later on.

  • I used ems for the sizing of just about everything, so this should be extremely tolerant of changes in text size.  The icons get a bit weird at extreme deltas, but I’m willing to accept that.  Anyway, we all may have full-zooming browsers within a year or three and will leave text-zooming to history.  The nice thing about using ems here, though, is that no matter which flavor of zooming you have to hand, the timeline will accommodate you.

  • I came across at least two things that were of “is this a bug?” interest.

    1. Assigning position: relative to table cells failed to make them containing blocks for absolutely-positioned descendant elements, as I mentioned before.  Changing their display to block allowed them to be containing blocks, but completely shattered the table layout—elements have to have a display of table-cell to act like table cells.  That makes sense, but the lack of containment when relatively positioning the table cells did not.  Turns out that’s permissible as per CSS2.1: 9.3.1: “The effect of ‘position:relative’ on table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption elements is undefined.”  Oh well.

    2. Where two elements overlap and both have :hover styles, only the “topmost” (the element higher up on the Z index) of the two gets its hover styles, at least in the browsers I tested.  The handling of hover styles has been an area of debate in the CSS community for quite a while—the CSS2.1 specification does a remarkable job of defining hovering without ever explaining how it should or shouldn’t work—but this single-event model seems unnecessarily restrictive after all these years.

  • Speaking of bugs, I ran into an apparently insoluble problem with Explorer: its allergies over the combination of display and table markup.  Yes, I know, I built bar graphs out of table markup, and that worked fine (even in IE6).  Not so here.  In fact, I couldn’t even get the table element to generate an element box once I’d positioned most of its descendants and converted them all to display: block.  I mean, no matter what I did, it would not show anything.  No height, no width, no borders, no nothing.  I can’t even figure out what’s happening to the display role of the cells, most of which position but some of which still act like they’re cells.  I think.

    Anyway, I was able to get IE7 to recreate 99% of the layout but couldn’t stop the overlap of the table and the following text (“Sources”, et cetera) without throwing in an extra div after the table and using a CSS hack to set its height in only IE7 so as to force the text below the timeline.  No thank you.  So I took the hacks out.  I admit I’m disappointed this doesn’t work as it should in IE7, but I have to remind myself that the fact that it even got close (and it did) is reason for hope.  And if anyone figures out how to fix the layout problems in IE7 (I tried zooming and relatively positioning the table element; neither worked), please let me know how you did it so I can update the CSS and credit you.

    Were I to change the markup to nested lists or divs or something, I suspect it would all come together just fine in IE7.  Not IE6, though… for reasons I’ll explain momentarily.

    Update: Sam Rayner pointed out that an adjacent-sibling-based rule targeted at IE7 would provide a decent fix for the overlap, so I added it in.  The above commentary still stands, except now we have a way to work around the major oddities.  Thanks, Sam!

  • One of the requests for the original timeline was to have an indication of actual dates and browser names.  Yeah, that’s not going to happen with images.  In this version, I was able to use title attributes to add in that kind of information, revealable in tooltips.  It also seemed like an accessibility win, although I’m not sufficiently expert in that field to know whether titles on things like table rows and paragraphs would really help.

  • Regardless, that’s the answer to the question I posed earlier: instead of using classes, I selected elements based on the contents of their title attributes.  So, for example, I place all of the August releases within their respective years by declaring #timeline p[title~="August"] {left: 62%;}.  For another example, I dropped IDs from the table rows, and used the title information instead.  This is an extra reason why the layout fails in IE6 and earlier: no support for attribute selectors.  I suspect IE6 would do okay with the layout if I’d used classes (and non-table markup) instead, but the goal here was to flex my creative-code side and push the envelope to its edges.  So to speak.

    This approach did make my CSS a bit longer.  Selecting on attribute values can be a longer-winded process than on class names, which tend to be compacted to the point of being cryptic.  On the other hand, using attribute selection allowed the markup to be a lot simpler, which is a benefit when adding browsers and new release data to the timeline.  Which, I should note, is now a whoooole lot easier than when I was scaling down JPGs generated from PNGs that I’d saved out of Keynote after using it to draw the dots and lines and such.

No doubt you’ll have noticed that the structured timeline looks different than the graphical one.  I believe I could have recreated the original’s look, but I kind of like this one better.  It’s more interactive, certainly, and having those descending lines (between the top of the timeline on the release dots) might clutter things up too much when looking for information to hover.  If you get what I’m saying there.

I’ve also considered that it would be possible to do a dependency timeline like the SVG-based timeline available on Wikipedia.  Doing so would require an entirely different markup structure; there, nested ordered lists make all kinds of sense.  Once that’s in place, the rest shouldn’t be terribly challenging to work out.  Tedious, perhaps, but not challenging.  But don’t expect me to do it any time soon: it would take too long, and draw too much energy and attention from other things that need to be done.


Resetting Again

Published 16 years, 10 months past

I’ve been pondering reset styles over the past few months, and come to a bit of a shift in my thinking.  Here’s the result of that thinking.

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, font, 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 {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	font-size: 100%;
	vertical-align: baseline;
	background: transparent;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}

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

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

/* tables still need 'cellspacing="0"' in the markup */
table {
	border-collapse: collapse;
	border-spacing: 0;
}

The small changes involve a paring down of the possible quotation around blockquotes and qs.  Before, I was explicitly pushing in empty generated content boxes with content: "", but there was no need.  A simple quotes: none; takes care of suppressing any automatic quotation marks on those elements.

The much bigger change, the shift in thinking, is the removal of the inherit values in the first rule—the ones that wiped out any boldfacing, italicizing, or font variants in browsers other than Explorer.  (You can see them in the “reloaded” post.)  I know, I know, I already defended that practice:

[The inherit] effects, as seen in my development environment, will still serve the purpose of reminding me to build up the styles I actually want, and not use the browsers’ defaults as a crutch. There is the possibility of my forgetting that (for example) IE/Win italicizes em when I don’t want it to, but that’s something I’ll catch during the browser testing phase.

But over time, I’ve come to realize that this is more than just a throwaway development tool.  It really is the beginning of a baseline style sheet.  (Or can be.)  Things like boldfacing and italics are some of the most obvious textual effects readers will see, and to have reset styles that treat them inconsistently across browsers doesn’t make sense.

Of course, browsers might treat elements differently when it comes to boldness and decoration and such.  But unfortunately, without inherit as a viable solution (due to the lack of support in Explorer), we’re stuck accepting browser defaults.  This is one area where defaults are pretty well consistent across the board, so it’s a small risk to be taking.  And this certainly doesn’t preclude anyone from adding to these styles to create their own reset that explicitly handles elements like em and strong.

Which leads me to why I explicitly set ins and del.  In some browsers, inserted text is underlined.  This leads to confusion, because most people expect underlined text to be a link.  I decided to explicitly switch that off and leave a note about it, much as I did with :focus styles.

And why am I not zeroing out deprecated elements, like center?  Because they shouldn’t even be in the markup.  The way to handle deprecated elements is with something like Marco Battilana’s Big Red Angry Text, not silently neutering them.

Comments and suggestions are, as ever, welcomed.  I’m going to shift the end result to its own URL, as I promised I would long ago, so that there will be a permanent home outside of the various postings.  Hopefully that will happen before the week is out.


Diagnostic Styling

Published 17 years, 2 months past

On stage at An Event Apart Chicago, I made reference to recent efforts I’ve been making to develop a set of “diagnostic” styles.  I’d hoped to have them ready for presentation in Chicago, but didn’t get it done in time.

Well, they’re still not really done, but as I’ve now torn them apart and rebuilt them three or four times, with no real end to that cycle in sight, it’s time for me to get them off of my hard drive and into the public eye.  It’s a little bit complicated, so rather than post the whole thing in this entry, I’m going to link to a demonstration page.  I first want to say a few things about it, though.

The primary goal here is to have a set of rules that can be applied during the development phase of a new layout.  These rules’ aim is to visually highlight problems in the markup.  For example, here’s one of the rules:

a[href="#"] {background: lime;}
a[href=""] {background: fuchsia;}

That brings some eye-watering attention to any link that has an empty href, or is (most likely) being used as a JavaScript trigger with no fallback.

Where things got tricky was when I wanted to do things like higlight images that didn’t have alt or title attributes.  In a perfect CSS3 world, I could just say img:not(img[alt]) to select non-alted images.  At least, I think that’s what I would say—:not() syntax makes my temples throb.  Since I was developing these with the idea of releasing them to a more general development audience, though, I decided to use regular old non-:not selectors.

So what I ended up doing, in slightly simplified form, was this sort of thing:

img {outline: 5px solid red;}
img[alt][title] {outline-width: 0;}
img[alt] {outline-color: fuchsia;}
img[alt], img[title] {outline-style: double;}
img[alt=""][title], img[alt][title=""] {outline-width: 3px;}
img[alt=""][title=""] {outline-style: dotted;}

The logic works out like so:

  1. Set all images to have a big red outline.
  2. If an image has both alt and title attributes, set the outline width to zero.
  3. If an image has an alt attribute, set the outline color to fuchsia.  This means the outline of any image that doesn’t have an alt attribute will stay red.
  4. As long as an image has either an alt or a title attribute, make its outline style double.
  5. If an image has an empty alt with any kind of title, or vice versa, make the outline’s width three pixels.
  6. If an image’s alt and title attributes are both empty, then make the outline dotted.

Whew.  Maybe I piled a few too many conditions in there, but I wanted to get some finer granularity on the results, which you can see demonstrated (along with several other things, like highlighting table headers without scope attributes and tables without summary attributes) at the diagnostic demonstration page.  On that page, you’ll see a number of examples and the style sheet that drives them all.  If it’s getting in the way of seeing what’s going on, move the mouse over it to mostly clear it away without actually removing it.  Mouse back out to bring it back.  (Maybe I should reverse those states—what do you think?)

Admittedly, much of what these styles do can be replicated with tools like the Web Developer Toolbar.  The advantage I find with writing my own diagnostic styles is that I can tune them to present exactly the way I want them.  Outlining deprecated elements is fine, but what if I’d rather make them lime-green on cyan to really drive the point into my optic nerves?

Anyway, I don’t for an instant think that these constitute a replacement for the WDT.  They’re just another handy tool to have in the toolbox.

A final note: when actually using diagnostic styles, all of the declarations should be marked !important so as to ensure their application.  I left those directives out of the demo page for clarity’s sake.  If you’re going to use diagnostic styles of this sort in your own projects, remember that you’ll need to add them.

I’m putting these out for comment, suggestions, and general community improvement.  Anyone see things we could add or upgrade?  Let us know!


Browse the Archive

Earlier Entries

Later Entries