Posts in the CSS Category

Unitless line-heights

Published 19 years, 6 months past

I’d like to share something that will be old news to readers of CSS: The Definitive Guide and all of my other books, but nonetheless needs to be said out loud, in public, for everyone to hear.

The property line-height can accept unitless number values.  You can also give line-height united values, though generally you shouldn’t.  But unitless numbers are just fine for this property.

So what’s the difference?  When you define a united value, like 1em, you’re setting things up to pass along the computed result to any descendants.  For example, suppose the following CSS is applied to a document containing the following markup fragment:

ul {font-size: 15px; line-height: 1em;}
li {font-size: 10px;}
small {font-size: 80%;}

<ul>
  <li>I'm a list item with <small>small text</small>.</li>
</ul>

The ul element has its line-height computed to be 15px because for line-height, em-based values are calculated using the computed font-size of the element itself.  I declared the font-size directly, so we know its computed size in pixels.

(Yes, yes, I know, pixel-sized text is evil and wrong, but it makes explaining how all this works a lot simpler.)

So that computed value of 15px is what’s passed on to the descendent elements.  The li and small elements will inherit a line-height value of 15px.  End of story.  They don’t change it based on their own font sizes; in fact, they don’t change it at all.  They just take that 15px and use it, exactly the same as if I’d said:

ul {font-size: 15px; line-height: 1em;}
li {font-size: 10px; line-height: 15px;}
small {font-size: 80%; line-height: 15px;}

Okay, now suppose I take the em off that line-height value, so that the styles now read:

ul {font-size: 15px; line-height: 1;}
li {font-size: 10px;}
small {font-size: 80%;}

Now what’s passed on is that raw number, which is used by descendent elements as a scaling factor—a multiplier, if you will–and not the computed result.

Thus every element that inherits that value of 1 will take that value and multiply it with their computed font-sizes.  The list item, with its declared font-size: 10px, will have a computed line-height of 10px.  Then it will pass that 1 on to the small element, which will multiply it with its computed font-size.  That’s 8 pixels; therefore, its line-height will also be 8 pixels.

The end result is exactly the same as if I’d written:

ul {font-size: 15px; line-height: 1;}
li {font-size: 10px; line-height: 10px;}
small {font-size: 80%; line-height: 8px;}

That’s a pretty major difference.  This is why it’s always strongly recommended that you use unitless numbers if you’re going to set a line-height on something like the html or body elements, or indeed on any element that is going to have descendant elements.

The fact that the CSS validator has a bug that causes it to generate parse errors on unitless number values for line-height (see report #2307) rather confuses things; we get an occasional jeering e-mail over at A List Apart as a result, since running CSS validation on the site gets an error due to my use of line-height: 1;.  Jeffrey points the correspondents to that bug report, and usually we never hear anything back.

And if anyone reading this feels motivated to fix the validator, please do.  As it says in the bug report, all they really need is a patch for review.  I might do it myself when I have some free time.  That’ll be in, oh, 2009 or so.

Again: the property line-height can accept unitless number values, and they’re a better choice than united values in 99 out of 100 cases anyway.  Okay?  Thank you.

[Addendum 26 Aug 06: Roger Johansson points out a bug in older Gecko browsers relating to unitless line-heights.]


Charting IE7b2

Published 19 years, 6 months past

So IE7 beta 2 is out.  As you might expect in a beta, it has some things that don’t work as one might hope, whether due to long-standing behaviors or brand new bugs.

I’ve said it before, and I’ll say it again: don’t panic.  Trying to fix a site that’s “broken” in IE7b2 is kind of like deciding to raze your profitable gas station just because you heard car companies are experimenting with hydrogen fuel cells.  When the final version of IE7 comes out, then you can worry about what to do.  Maybe your site won’t be “broken” any more, and you won’t have to do anything.

In the meantime, what you should do is figure out what’s causing the problem you’re seeing in b2, create a very minimal test case that causes the problem, and submit that to Microsoft.  By doing that, you give them a chance to identify the problem and fix it before IE7 goes final… at which time, you won’t have to do anything about your site, because it won’t be broken.

That’s if they fix the bug in question.  They might not; they don’t have infinite time and energy.  But I can absolutely guarantee that they’ll never get around to fixing a bug nobody told them about.

In the CSS world, there are some points of concern, including bugs that are new to IE7b2.  The css-discuss community has started collecting information over on the wiki, and if you have test cases that demonstrate CSS bugs in IE7, you should feel free to add information and links to that page.

Before you do, though, make sure to observe the following (adapted from my post to css-discuss):

  1. Make absolutely certain you’re testing IE7 beta 2.  IE7b1, which is available for download on various sites, had no known CSS enhancements.  It did not support CSS2.1 selectors, or fix any bugs on which CSS hacks depend, or just about anything else.  If you test with IE7b1, you’re wasting your time.  Again, be SURE you’re testing with IE7b2.

  2. If you’re testing property, value, or behavioral support in IE7, make absolutely certain that your test case uses no hacks, filters, conditional comments, or other measures.  If you’re testing float margin-doubling, for example, but you still have in a CSS hack targeted at IE6, you might get completely spurious results. Make your tests as simple as humanly possible while still showing the problem.

  3. If you’re testing support for hacks, filters, or conditional comments in IE7, try to make sure you’re testing using simple effects. For example, here’s how I’d test for IE7 support of a child combinator:

       p {color: red; font-style: italic; font-weight: normal;
          text-transform: none;}
       div>p {color: green;}
       div > p {font-style: normal;}
       #test>p {font-weight: bold;}
       #test > p {text-transform: uppercase;}
    
       <div id="test"><p>Bold uppercase green</p></div>
       <p>Italic normal case red</p>
    

    This approach uses property/value combinations that we all know IE/Win has supported for a long, long time.  If I tried to test with widths and margins and padding, I’d be concerned that a box model bug was sneaking in and making me think there was a selection bug.  With the color-font-text approach, this is far less likely.  (Not non-zero, but close.)

    Similarly, to test arbitrary-element hover, I’d do nothing more exciting than:

        p:hover {color: green; background: cyan;}
    
  4. If you find a new bug, as Al Sparber has with the a:hover/@import problem, absolutely document it with a basic test case (as Al did) and feel free to ask others for confirmation.  But remember the previous points when you construct your test case.

The goal of all this isn’t just to make sure Microsoft knows about every CSS bug under the sun, though that certainly wouldn’t hurt.  What I also hope to see happen is that we get an idea of what’s new, what’s broken, and what absolutely must be fixed.  To pick a hypothetical example, suppose it was discovered that in fixing float margin-doubling, IE7 broke clearing behavior.  That would absolutely have to get fixed before IE7 final.  Doing so would be far more critical than, say, adding support for generated content, or even fixed positioning.

Again, don’t panic, but please do help find any bugs or other problems in IE7b2, so that we have a chance of seeing the problems corrected.

Addenda: so just after I posted this, I found out about the IEblog post What’s New for CSS in Beta 2 Preview? and the in-progress MSDN technical note Cascading Style Sheet Compatibility in Internet Explorer 7.  Those might come in handy as a baseline of “here’s what I should see” while you work to find out what you actually see.


Tables to Bar Graphs

Published 19 years, 7 months past

In “Bar Graphs With Style“, I took a set of nested lists and some divs and turned them into a vertical bar graph using CSS.  Jan Brašna pointed out that the actual information I was presenting would probably be better represented as a table instead of nested lists.  I don’t think there’s anything wrong with using the lists, but I do agree with him that a table might be a better base represention of the data.  Maybe you agree.  If so, then here you go: CSS Vertical Bar Graphs using a table as the markup basis.

The demo works fine in Safari, and in Firefox I got it to work by explicitly setting the table element to display: block (when I left it as display: table, the bars were badly misplaced).  In IE/Win, everything’s fine except for the actual placement of the bars; they’re fine as a group but way out of place.  I think the IE/Win problem is a simple refusal to give a table element dimensions when all of its descendants have been positioned, no matter what display value it’s given.  Perhaps some intrepid soul can figure out a way to defeat this. [Update: some intrepid soul did, and the demo has been updated; it now works in IE/Win as well as most other browsers.]

(I considered the idea of positioning all the bars with top instead of bottom, thus sidestepping the table-sizing problem, but that would mean a different way to place the ‘ticks’ and in the end it was different enough from what I’d done that I just couldn’t be bothered.  Feel free to run with the idea, though, or come up with a better one.)

I must admit that when I first assembled this table-based chart demo, it was with some trepidation.  From a CSS point of view, of course, it doesn’t matter what elements you position, nor how: a td is no different than a div or any other element.  Historical browser behavior, though, has been to put table markup into its own special category and treat it as being extra-special—as witness IE/Win’s handling of the original demo.  I was honestly afraid that, in overriding the display values for table elements (by positioning them), I’d crash a browser.  So far, no crashes, but proceed at your own risk!


Bar Graphs With Style

Published 19 years, 8 months past

A lot of the time, when I’m sharing a technique or effect I’ve devised, I’ll say something like “I doubt I’m the first to think of this…” or “it may not be original, but it’s original to me…”.  This might strike some as an annoying quirk, some sort of pseudo-modesty that I should either embrace fully or just drop already.

However, I do it because I know it’s true.  Even some of the most radical experiments I’ve published, like those on css/edge, were prefigured or anticipated by others.  I didn’t steal anyone’s ideas, of course.  Every one of those demos was an original creation born of my knowledge and thinking.  They just weren’t necessarily the very first instance of those techniques ever published anywhere.  Other ideas, like Universal Child Replacement, were devised before I hit upon them but were never documented.

I bring this up because the door swings both ways: from time to time, I see someone else publish a technique or idea that I’d had but never documented.  A recent case in point was the appearance of “CSS for Bar Graphs” at Apples to Oranges, which showed a vertical bar graph created out of CSS and a list.  I’d done something very, very similar almost three months before the AtO article’s publication date while creating an invoice-tracking system for myself, and never gotten around to publishing an example.

This almost certainly means that they and I were creating basically the same thing at the same time.  Who got the idea first?  Who cares?  It’s a nifty idea no matter who thought it up.  Plus it’s a near-certainty that somebody else did it long before three months ago, and never got around to documenting it.

I often wonder how many really cool techniques and ideas are lost simply because the inventors don’t have the time or energy to publish them.

Since my approach varies a bit from AtO’s, I’ve put up a css/edge demonstration for people to poke.  The major difference is, I think, my use of empty divs to create the horizontal strata instead of a background image.  This let me have strata that were scaled to the figures being output.  For example, if the strata are increments of $10,000 and the highest bar is $55,055, then I can write out enough “bar divs” to make the top of the chart $60,000.  If the tallest bar only goes to $38,522, then I can stop at $40,000.

This also meant calculating and writing out the bars’ heights as inline styles.  What you see in the markup of my demo is the end result of all that back-end calculation.  There are doubtless better ways to go about creating the strata and setting the bar heights, most obviously using DOM scripting to write in said bar divs instead of dirtying up the XHTML with them.  The same would be true for the inline heights of the bars themselves, which could be dropped in favor of dynamic setting.  Heck, you could even make it so the chart could be zoomed in or out.

Someone else can do the necessary scripting if they like; I’m content to get the example out there, however late to the party I may be.  The more such examples there are, the better.

Followup: Tables to Bar Graphs, in which the same chart is created out of a table instead of nested lists.


Adium: Chatting With Style

Published 19 years, 8 months past

Tim Bray, that dashing man-about-town, recently sang the praises of Adium, a multi-service chat client for OS X.  I’d tried it a while back, and been only marginally impressed.  At the time, its presentational inflexibility was too annoying for me to take it seriously.  Okay, yes: it was a damn sight better than Messenger for OS X, which is the only reason I even kept it on my hard drive.  But I hardly ever log onto MSN any more, as everyone I know is on AIM.  So I’d stuck with iChat AV.

Still, Tim’s word is always gold (or at least high-grade palladium) with me, and he said the magic words (“highly skinnable”), so I downloaded the latest copy and poked around for a bit.

Boy howdy!  Adium has definitely come a long, long way since last I visited.  You can change the appearance of your chat sessions (with “message themes”), the dock icons, the contact list, and much more.  Since none of the default message themes really did it for me, I went looking for others.  There are quite a few available at the Adium Xtras site, but none of them were really what I wanted either.  In iChat, I cranked the graphic frippery down to zero so that the chat sessions were as compact as possible, but I still had the text look nice.  If I could recreate that in Adium, it would make the migration much, much simpler.

So I dug into the package contents of a promising message theme… and found out that themes are based on nothing more than XHTML and CSS.

Seriously.  The entirety of an Adium chat window is an XHTML document that’s being dynamically updated via DOM scripting—all of it pumped through WebKit, of course.  In creating a message theme, you define what markup will be used, and write CSS to style it.  You can even define variants on your theme by writing additional style sheets.

So with some quick hacking, I not only radically improved the markup generated during a chat (the markup I saw in the packages I downloaded was, um, sub-optimal), but I basically replicated my old iChat theme with some simple CSS.  And then I created some variants that slightly modify it in various ways, mostly to prove that I could.

I’m now wondering if I could write and attach JavaScript that would make chat sessions even more interactive, more robust.  (Update: Phil says yes.)  Click on a line to copy the whole line to the clipboard, say, or dynamically change the in-session presentation by hitting a button.  Adium may block that kind of thing, but if not, then it’s a chat client extensible beyond anything I’ve so far imagined.

And given how much I love to tinker with my software, that’s like waving a bulging suitcase of money in front of a senator.

Granted, there are some things I’d like to change.  For example, the markup you define in a theme is not used in saving the chat log.  In a log, you just get some basic markup with a case of classitis and very, very poor semantics.  It would be a lot cooler if you could define the log markup (or the log just used the markup you generate during a chat session) and the CSS to present it.

A chat log is also something that, it seems to me, cries out for a microformat.  The markup I’m using for my theme is also a first effort in that direction, recycling some other microformats’ concepts (I stole a bit from hCalendar and am planning to graft in some hCard as well) and setting up some basics.  If I can take this far enough, I might consider pushing to upgrade the markup Adium generates in its logs.  They’re dropping a lot of information on the floor when they write out the logs, and I think that’s a shame.

But then, I can make the effort to fix that and actually have a chance of it paying dividends.  The joys of open source, you know?

I’ll still use iChat AV for videoconferences, which are an essential tool for family cohesiveness when I’m on the road, as well as to keep close to my father down in Florida.  For text, though—which accounts for at least 90% of my instant messaging activity—Adium is my new chat buddy.


Multi-Unit Any-Order Columns

Published 19 years, 9 months past

During last week’s workshop in Chicago, I was asked to discuss Alex Robinson’s One True Layout.  This presented a bit of a challenge, since the article and its contents are rather new.  While I’ve read through it all and grasped the main points, I wasn’t entirely sure I grasped the nuances.  For that matter, I’m still not entirely certain that I do.  And I tend to be wary of speaking about things I don’t fully understand.  Still, the audience was interested, so I took the plunge, figuring that I could stick to the bits I knew relatively well.

The Any Order Columns seem straightforward enough, once you get that it’s using margins to shift elements around.  The Equal Height Columns aren’t really, perhaps more properly being called “Extremely Tall But Clipped Columns”, but they simulate the job well enough to count.  And then there is the case of Vertical Grids, which I’m still pondering.

But as an illustration of why I say I’m not sure I grasp all the nuances, it was literally while presenting on this topic during the workshop that I hit on an extension of Any Order Columns (AOC) that allows for AOC to be used with columns of mixed width measures.  It came in response to a question about that very thing.  I’d been showing how to do AOC with columns sized with consistent units, like all with percentage widths or all with pixel widths.  But, an attendee asked, what if you wanted to have one column with an em width and another with percentages?

Say, for example, you wanted the first and second blocks (to use the terminology from Alex’s examples) to be the center and right columns, respectively, and the third block as the leftmost column.  Furthermore, suppose you want the left column to be 10em wide, the center column 40em wide with 1em ‘gutters’, and the right column to be 200 pixels wide.  I’m using pixels because it’s a commonly-used unit, but if it makes you feel better, assume there are Flickr images there or something similar in that column.

All right.  So we have to move the third block leftwards by 40em of center width, 2em of gutters, 10em of the space it will occupy, and 200 pixels of the rightmost column—the second block.  That’s 52em + 200px, which is exactly the sort of thing CSS doesn’t allow for a variety of reasons, some more reasonable than others.  IE/Win allows expressions, but only with a proprietary value syntax that nobody else supports.  And it potentially could be done with JavaScript, which would require pulling some font-size information in order to compute various em widths.

Or… we could relatively position a float, using the float’s margin to handle one of the measures, and the relative positioning to handle the other.  So you start like this:

#block3 {float: left; margin-left: -200px;}

That will get the third block to sit right on top of the second.  That’s taken care of the 200 pixels, but what about getting it the rest of the way?  Add the following:

#block3 {float: left; margin-left: -200px;
  position: relative; left: -52em;}

This puts the third block right where we want it.

There’s one exception: IE5/Mac, which doesn’t pay attention to the relative positioning when the element’s been floated.  So far as I’ve been able to discern, this is the one reduction of browser support from Alex’s original AOC.

With a little bit of math, you can make this work so long as the elements to the left of the shifted column use no more than three different units in their sizing.  To handle two types of units, you could do something like this:

#block1, #block2, #block3 {float: left;}
#block1 {width: 35em; padding: 0 20px; margin-left: 9em;}
#block2 {width: 12em; padding: 0 15px 1em 5px;}
#block3 {width: 8em; padding: 0 0.5em;
   margin-left: -60px; position: relative; left: -56em;}

(code example with browser workarounds)

This approach would permit the ability to drop in pixel-sized decorations, like separators or drop shadows or whatever, while preserving em-width column contents in order to scale with font sizes.

Now suppose you have a mixture of all three unit types, which is a case I didn’t tackle in the workshop.  I might even have said it wasn’t possible to handle, but if I did say that, I was wrong.  With the addition of a negative right margin on the second column, we can handle all three units, as seen here:

#block1, #block2, #block3 {float: left;}
#block1 {width: 50%; margin-left: 11em; margin-right: 1em;}
#block2 {width: 200px; margin-right: -200px;}
#block3 {width: 10em; margin-left: -50%;
  position: relative; left: -12em;}

(code example with browser workarounds)

Note that I’m not saying that you’d necessarily want to mix fixed-width columns with fluid-width columns.  Doing so is a potentially volatile mix when using CSS-driven design, and this technique doesn’t make it any more or less volatile.  If you want to do it, though, this is a powerful approach.

In the examples to which I pointed, I came across some intermittent appearances of the double-margin float bug in IE5.5/Win, though oddly not in IE6/Win.  I didn’t try to work around these inconsistencies beyond using the display: inline hack from Alex’s original examples, but I’m sure they’re surmountable.  It’s probably as good a case as any for using conditional comments to serve up fixes to pre-IE6 versions of IE/Win.

You may have noticed that, if the browser window is reduced in width, the columns start dropping in the two-unit example.  That’s something that could likely be handled with a sufficiently wide container, although doing that risks the dread horizontal scrollbar.  You’d get the same scrollbar with either older CSS layout approaches or with table-driven design, though.

I suspect there are even more combinations and nuances to be found in the AOC technique, and still more in the column and grid ideas Alex has laid out.  Hopefully I’ve made a good start here.  For any omissions or inaccuracies there may have been in my Chicago presentation, I hope the attendees and organizers will accept my apologies.


Layout Revolution

Published 19 years, 9 months past

Recently, Alex Robinson published an article titled “In Search of the One True Layout“, and it basically turns the conventional wisdom about what CSS layouts can and can’t accomplish on its ear.

One of the article’s primary aims is nothing less than enabling multi-column layout using no extra markup (beyond a div to enclose each column’s content) and allowing the columns to be in any document source order.  Impossible?  No.  It appears to have done just that in all current browsers, and several non-current browsers as well.

Assuming this technique stands up over time, and I see little to no reason why it would not, this is a truly major development (and that’s an understatement).  There is a problem in recent versions of Gecko-based browsers which you can read about in Bugzilla entry 312777.  The problem has been fixed in very recent builds, but the question is whether or not the fix will make it into Firefox 1.5.  In comment 40 of that entry, one of the engineers indicates that having web developers put in their thoughts on the importance of this fix would be welcome.

Now, we don’t want to create a stampede here.  However, if you have a Bugzilla account and your assessment of the importance of the bug varies from the comments posted, or you have something new to add to the comments, then by all means contribute.

Getting back to Alex’s article, it also tackles the desire for equal-height columns in a tableless design environment.  Then, just to pile it on, Alex knocks out a way to create vertical grids without tables.  Later on, he ties it all together into one neat, shiny package.

So that’s basically killing three long-standing frustrations of standards-oriented design with one stone.  Any one of them is notable in its own right; put the three together, and I’m pretty much emerald green with envy over here.  It might just be time for me to consider hanging up my spurs, folks, ’cause it looks like there’s a new sheriff in town.  And he’s packin’.


Selling Out Again

Published 19 years, 10 months past

I noticed this morning, after the power finally came back on, that the graphic next to the information on the Carson Workshops home page about the CSS/XHTML workshop I’m doing in a couple of weeks has a “LAST FEW” banner over it, so it looks like those seats are going fast as well.  If you were interested in that one but hadn’t yet gotten around to registering, now might be a good time.


Browse the Archive

Earlier Entries

Later Entries