Now that the CSS2 specification has become a W3C recommendation, there is a great deal to learn. Web Review's CSS guru, Eric Meyer, reported on many of these changes in a February 1998 article. Since then, however, there have been many changes to the specification. Thus, we present now an updated version of A Quick Tour of CSS.
You're no doubt aware that Cascading Style Sheets (CSS) are a developing web technology that promises a great deal in the way of web page presentation. Browser authors are still working to implement Cascading Style Sheets, level 1 (CSS1), and they seem to get closer with each new version.
Meanwhile, never content to rest on its accomplishments, the CSS&FP Working Group of the World Wide Web Consortium (W3C) has published the next level of style sheets. Logically enough, this standard is called Cascading Style Sheets, level 2 (CSS2). Illogically enough, both Navigator and Internet Explorer attempt to support some of the things which are new in CSS2, even though they haven't finished implementing CSS1 yet.
So what is new in CSS2? I'm so glad you asked. Let's take a quick tour, shall we?
Additions to CSS1 Properties
Only a few CSS1 properties have gained new values, so let's deal with them right off the bat. The first is display
. Now, in addition to block
, inline
, line-item
, and none
, we have run-in
, compact
, and marker
, as well as a number of values specific to tables (which we'll get to in a bit).
compact
has an effect similar to<DL compact>
(assuming your browser supports that bit of HTML). Basically, if an element is set to{display: compact;}
, then it will appear in the margin of the next element, assuming there is enough room for it. Otherwise, the elements will be treated as block-level elements. Think of a "compacted" element as one which is floated, but only if there is room for it to be displayed without altering the formatting of the following element.run-in
, on the other hand, has the effect of turning an element into an inline element at the beginning of the following element. Confused yet? This should make it simple:
<H4 style="display: run-in;">A Heading.</H4> <P>This is a paragraph of text....</P>
The result will look something like this:
A Heading. This is a paragraph of text which has a run-in heading at its beginning. It doesn't look like an H4, does it?
However, this should only work if the next element is block-level, and is not floating or positioned absolutely (more on that in a bit). So, for example, if you try to set a list item to run-in
, and the next element is another list item, the items shouldn't run together.
marker
is used to define an element as being a marker, such as a bullet in an unordered list or a number in an ordered list. This doesn't get used terribly often, but it does hook up with a new element to control positioning of the markers. We'll cover all that when we talk about generated content, so hold tight.- As part of the internationalization effort by the W3C,
list-style-type
gained the following values:hebrew
,armenian
,georgian
,cjk-ideographic
,hiragana
,hiragana-iroha
,katakana
, andkatakana-iroha
. These values allow authors to specify that ordered lists will use counting systems other than decimal and Roman. If you don't know what these values mean, you probably don't need to use them; conversely, if you need them, you probably already know which ones you need. font
also picked up a few new values:caption
,icon
,menu
,messagebox
,smallcaption
, andstatusbar
. The effects these values will have is to apply a font family, size, weight, etc., which matches the computer's settings for such things in its own environment. For example, icons on a Macintosh are typically labelled using 9-point Geneva. Assuming that hasn't been changed by the user, then anyfont
declaration with a value oficon
will result in the use of 9-point Geneva for that element.- Finally, there is one very important new feature of CSS2: the value
inherit
. If you were to ask the question, "OK, to which properties didinherit
get applied?" the answer would be, "Every last one of them." Before you ask the next question,inherit
is used to explicitly declare that a given computed value should be inherited from its parent. In other words, if thefont-size
forBODY
is computed to be 14 points, then the declarationP {font-size: inherit;}
would set all paragraph text to 14 points in size.
A Wide Range of Selectors
Perhaps the biggest area of expansion over CSS1 is in selectors. The CSS2 specification contains a number of new selectors, including the ability to include tag attributes (and their values) in the selectors.
For example, A[href]
would match any A
with an href
attribute, regardless of the value of that href
.
If, on the other hand, you want to match those elements which have a certain attribute set to a certain value, you can do that as well. Let's say you want to highlight any hyperlink which points to the W3C's home page. You would then declare:
A[href="http://www.w3.org/"] {background-color: yellow;}
This way, no matter how many hyperlinks you have on your page, only those which point to the given URL will be highlighted with a yellow background.
Speaking of referring to class names, some changes have happened there as well. It is possible to set multiple class names on a given element, such as <P class="footnote example reference">
. In CSS1, you could only refer to one of these values, such as P.example
, which is the same as P[class="example"]
in CSS2. Well, in CSS2 you can modify this selector so that the class name must be an exact match, or set it up so that only one of the values has to match. Given the above three-class paragraph, P[class="example"]
wouldn't match it, because the values are different (example
isn't the same as footnote example reference
). On the other hand, P[class~="example"]
would match, because this selector has to match only one of the values in the class
attribute. The only difference is the tilde character ( ~
), but what a difference!
Incidentally, class and ID names can now begin with digits, which they couldn't under CSS1. So .1world
is legal, although in some cases you'll have to escape out the number, like this: ./5in
. This keeps the browser from getting confused about what look like units in the class name.
Here's another one: the "any-child" selector, which is represented with the greater-than sign ( >
). This lets you assign styles to any element which is a direct child of the first element, such as:
DIV.main > OL {margin-left: 1in;}
In this case, any ordered list which is a direct child of the DIV
with a class of main
, but not an ordered list which is a grandchild (or later) descendant of DIV.main
. Thus, an ordered list which is nested inside another list, or found inside a table, would not have a one-inch left margin as a result of the above rule.
Another interesting selector is the "immediately-follows" selector, which is a plus sign ( +
). Using this, you can set up a style for any element which immediately follows the first element. As an example:
H1 + P {margin-top: 0;}
With this rule, you state that any time a paragraph is the next element after an H1, then that paragraph has a top margin of zero. Any other element will not match this rule, even paragraphs which occur after an H1, although not immediately after it. Here's a quick breakdown:
Will match: | Will not match: | |
---|---|---|
<H1>H-1</H1> <P>para-1</P> |
<H1>H-1</H1> <OL>list-1</OL> |
<H1>H-1</H1> <H2>H-2</H2> <P>para-1</P> |
Just in case you find these a little too limiting for your purposes, there is a universal selector now, which is the asterisk (*
). This lets you set styles on a whole range of elements, while sort of bypassing the inheritance mechanism. For example:
* {color: black;}
is the same as listing every element in the document in a grouped selector, and then assigning the color black to them. It can also be used in conjunction with the other selectors, like this:
H1 + * {margin-top: 0;}
This will cause any element following an H1 to have no top margin, no matter what element follows the H1. Therefore, all of the examples given in the "Will match/Will not match" table above would match this rule, since the element following the H1 doesn't matter.
Finally, there is the language selector, which works like this:
P[lang|="en"] {text-align: left;}
This will match any paragraph whose lang
attribute has en
(English) as one of its values. This is most useful when defining styles for a document which has multiple languages.
You can also string all of these selectors together to create some highly specific criteria for applying styles. Given the large number of combinations and the complexity this introduces, however, I'll have to leave that subject for a future article.
New Pseudo-Classes and -Elements
Joining such famous (and unimplemented) pseudo-elements as :first-letter
and :first-line
, we have a whole brace of new stuff to talk about.
:hover
is intended to affect display of an element while the mouse is over it. For example, you could set anchors to have no underlining, except while the mouse is over the anchor, by declaring A:hover {text-decoration: underline;}
. While this is usually done in conjunction with anchors, the specification says you can use it with any element, even things like paragraphs and images. Whether browsers will support this behavior is another story, of course.
Similar to :hover
is :focus
, but the difference is that :focus
is used to apply styles to whatever element is the current focus of input. This might not be the same as the element over which the mouse is hovering. You will most likely see this in forms, where you can use the tab key to move from input field to input field without touching the mouse. You might decide, for example, to change the color of the current form input with:
INPUT:focus {background-color: yellow;}
There are also four new properties which relate to focus: outline-color
, outline-style
, outline-width
, and the shorthand outline
. These let you define an outline for a focus element. These are obviously similar to borders, but the difference here is that the outlines can come and go and the focus changes, and they don't cause the document to redraw. They just appear, overwriting anything which may be already there, and then disappear.
:first-child
is an interesting new pseudo-class. It's used to apply a given style to the first child of an element, which is pretty nifty. Let's say, for example, that you have a document in which all of the paragraphs have atext-indent
of half an inch. However, you want the first paragraph of the document to have no indentation of its first line, plus it should have a half-inch left margin and be italicized. You would then declare:
BODY:first-child {text-indent: 0; margin-left: 0.5in; text-style: italic;}
Thus, the first child element of BODY
will have a text indent of 0, plus a left margin of half an inch and italicized text. Remember, though, that this will be applied no matter what element is the first child. If the first child element is an H1, then that H1 will have no text-indent. If it's a paragraph, then that paragraph will have no text-indent.
- The
:lang
pseudo-class is used in conjunction with languages, and works something like the|=lang
selector we discussed before. In this case, you would declare something like:
P:lang(en) {text-align: left;}
The difference between this and the language selector lies mostly in the syntax. Functionally, they're the same.
Finally, there are the pseudo-properties:
:first
:left
:right
:before
:after
We'll get to those in the sections on paged media and generated content.
Fun with text and fonts
First, there is text-shadow
, which has the effect you'd probably expect from its name: You can define a drop-shadow of a given color for text. You can even set an offset and a blur radius, which means you can get cool fuzzy shadows, or even glow effects, using this property. (I fully expect to see this property heinously abused the instant it's supported by any browser.)
The font section gained two new properties. font-size-adjust
is intended to help browsers make sure text will be the intended size, regardless of whether or not the browser can use the font specified in the style sheet. It is often a problem that authors will call for a font that the user doesn't have available, and when another font is substituted, it's either too big or too small to read comfortably. This new property addresses that very problem, and should be very useful for authors who want to make sure that their documents are readable no matter what font gets substituted.
The other new font property is font-stretch
. This gives you a range of values which let you stretch the characters in a font horizontally, making them wider or narrower, depending on the value you choose. They range from ultra-condensed
to normal
(the default), to ultra-expanded
, with eight absolute levels, and two relative levels, of stretching all told.
It's also worth mentioning that there is a whole slew of properties that are used to describe, match, and even synthesize fonts. Since it would take a very long article just to explain them all, and most of you wouldn't be interested anyway, I've simply listed them in a sidebar for you to explore on your own if you're interested.