Some new CSS features in Firefox 3

Friday, 2008-06-13,
14:52-0700

Our developer documentation already has a list
of the new CSS features in Firefox 3. I'd like to talk in some more
detail about some of the more interesting or useful ones.

inline-block and inline-table

We now support the inline-block (CSS 2.1) and
inline-table (CSS 2.0) values of the display
property. These values map to formatting objects that are like blocks
or tables on the inside, but participate in inline layout.

This example may not look all that interesting, but I think these
properties will end up proving more useful in complicated situations,
where having these additional basic tools will help authors get the
layout they want. This was also a value where we'd been lagging behind
other browsers and we've now caught up, so inline-block
should actually become usable to authors writing Web pages for multiple
browsers in the near future.

Note that the default value of vertical-align is
baseline. Baseline-alignment for inline-blocks refers
to the last line of the block, while baseline-alignment for
inline-tables refers to the first row of the table. Many uses of both
may need other values for vertical-align.

font-size-adjust

font-size-adjust
is a property in CSS 2.0 (which was dropped from CSS 2.1 due to lack of
implementations), originally proposed by Todd Fahrner. There are a few
different ways to think about what it does, but the way I like to think
about it is that is a way for style sheets to pick font size by the size
of the x-height
rather than the size of the font. This is useful for languages like
English that have bicameral scripts (i.e., have both uppercase and
lowercase letters); it's probably a bad idea to use it for Chinese.

Since there are existing browsers that don't support
font-size-adjust, it has to do this in a backwards-compatible way. So
the way it works is that the author specifies a number that is
multiplied by the font size:

Note that I'm specifying font sizes in pixels (px) to
make the math easier. Users who have changed the default font size
in their browser preferences probably did so because they want larger or
smaller text, and actually using pixel font sizes gets in the way of
this.

Anyway, why would you want to use this?
Largely because, on the Web, you don't actually know what font is going
to be used. Different machines, especially when running different
operating systems, have different fonts on them. Even the same font
might be used slightly differently on different operating systems. The
lowercase letters in different fonts take up a different proportion of
the font's size. How big text appears and how much width it takes up is
often more closely related to the size of the lowercase letters than the
uppercase. More specifically, this can be useful for things like:

specifying a font like Verdana (which has very large lowercase
letters) as a first-choice font, and not wanting the text to be too
small if Verdana isn't available

making different fonts (for example, a proportional font and a
monospace font) appear to have the same size

I'll give an example of the latter by looking at the
Web page I mentioned at the beginning. It wants the proportional
and monospace text to be the same size. Currently, it compensates for
Firefox's smaller monospace font size preference (incidentally,
something I'd like to get rid of in the future using the same
infrastructure we use for font-size-adjust) by
specifying:

code { font-size: 1.2em; }

Depending on what my default monospace font is, I get different
results:

The first example is probably roughly what the author intended; in
the second example the monospace text is clearly too small.

If I add font-size-adjust: 0.6 to the body and change to
code { font-size: 1em; }, I end up with the following
result:

Here the fonts are consistent, but probably too large, partly since
monospace fonts tend to appear bigger because many of the characters are
wider. So let's try again, this time with code { font-size: 95% }:

Now the results are roughly the size I think the author intended, and
they're consistent between different fonts.

Unfortunately, I'm afraid the monospace font size preference is still
interfering with things, so this may not be as useful as it could
be.

rgba() and hsla() colors

We now support the rgba() (Red-Green-Blue-Alpha) and
hsla() (Hue-Saturation-Lightness-Alpha) color values from
css3-color. (I'm
actually the new editor of this specification, and a new last call
working draft should be out within a few weeks.)

These are in addition to the existing opacity
property (which we've supported since Firefox 0.9 or Mozilla 1.7), which
can be used to make an element and all of its descendants partially
transparent as a single unit. These new color values are different
because they specify alpha that is used right when the things with that
color are drawn.

I'm sure people who are better at visual design than I am have lots
of pretty uses for these, but I'll give some rather plain-looking
examples, just to show the difference between compositing the entire
element as a unit and doing each drawing operation separately.

For a start, let's look at a div containing a header,
with the following styles (see HTML):

In this case, where the header is on top of the div, the header's red
background completely covers the lime green background of the div, so no
green shows through there. But the whole thing (the unit, in which the
red completely covers the lime) is drawn at 50% opacity against the
body's blue background, so the blue shows through both.

In this case, both of the backgrounds are partly transparent. But,
unlike the first time, they're drawn separately rather than one unit, so
the green is visible behind the red, making the background of the
heading look brown. The text is still fully opaque.

New values for width,
min-width, and max-width

We support four new values for the
width,
min-width, and
max-width
properties: -moz-max-content, -moz-min-content,
-moz-fit-content, and -moz-available. These values
are planned
to be part of the css3-box specification.

Like the new values of display that I wrote about above,
these are likely to be basic tools that authors find particularly useful
in complicated situations. But they do allow a few simple demos as
well.

I'll start with a little bit of background: pieces of content have
two intrinsic widths that are used in CSS layout engines. In a very
simple example, a paragraph containing text (and no line breaks), the
larger of these intrinsic widths is the length of the text when laid out
all on one line, and the smaller of these intrinsic widths is the width
of the longest word in the text. (For more complicated examples, the
definitions of these widths are more complicated.)

The values -moz-min-content and
-moz-max-content specify those two intrinsic widths.
They're not particularly useful on the width property, but
they may be more useful on the min-width and
max-width properties.

The value -moz-available allows specifying the width
that normal blocks (but not floats, tables, or inline-blocks) already
have with width: auto: using the width of their
container. Again, this probably isn't all that useful for the
width property, but it's probably more useful for
max-width.

The most useful of these values for the width property
is -moz-fit-content, which gives the sizing algorithm used
to size tables and floats. This sizing algorithm is pretty simple,
actually: it's just the larger of (1) -moz-min-content or
(2) the smaller of -moz-max-content or
-moz-available.

This value actually does let authors do some things that previously
weren't possible without tables, such as putting a backround on headings
that doesn't fill the whole width of the container unless the heading
does, but is a single rectangle if the heading breaks to multiple
lines (see HTML):

white-space: pre-wrap

We now support the pre-wrap value of the
white-space property. (We'd long supported the
-moz-pre-wrap value, but now our implementation has been
updated to the CSS 2.1 specification, which introduces
pre-wrap, and the value has been renamed.)

This allows displaying preformatted text in a way that wraps when the
text doesn't fit in the width of its container. This can be useful for
things like source code samples and mailing list archives. For example,
if you look at this
historic message in the W3C mailing list archive, it looks like
this:

But if you make the window much narrower, the text still doesn't
require horizontal scrolling:

Many people contributed to the work involved
in adding these new features and the many other
new CSS features in Firefox 3. The work in rewriting our graphics
architecture was particularly important, and led to a number of these
new features (and should lead to more new features in the near future).
These contributions include a lot more than just writing code. I'd like
to thank everybody who filed bug reports, analyzed bugs and wrote
testcases, fixed them, and documented the new features for their
contributions to the features that I described above and the
architecture work that they depend on, and to getting all of that work
into a state that we can be proud of shipping as Firefox 3.
I'd particularly like to thank
Uri Bernstein,
John Daggett,
Daniel Holbert,
Bernd Mielke,
Simon Montagu,
Masayuki Nakano,
Robert O'Callahan,
Mats Palmgren,
Stuart Parmenter,
Jesse Ruderman,
Eric Shepherd,
Karl Tomlinson,
Ryan VanderMeulen,
Vladimir Vukićević,
Martijn Wargers,
Boris Zbarsky,
and the cairo team.