The www-style CSS FAQ

This document aims to answer some frequently asked questions on the W3C’s www-style mailing list with regard to CSS, how it works and why certain things are the way they are.

What this is not: a general FAQ on how to use and learn CSS. This is for advanced users who want to understand more about the backgrounds of CSS.

I aim to keep this FAQ a work-in-progress, and add new items every once in a while. If you have any comments, feel free to send me an email, or to the www-style mailing list.

There is a Belarusian translation of this FAQ, thanks to Bohdan Zograf.

Table of contents

Frequently Asked Questions

Q: How long does it take for new CSS features to be available

It is important to realise that it takes years for new features to be fully specified, implemented and have enough user coverage before you can use it.

Every feature starts with a proposal. There isn’t anything specified yet, and as soon as it is it will have to receive input from various parties in the form of a number of WDs. Once it is mature enough to go to CR, it will still take years before browsers implement it, and more years before those new browser versions are used by enough people that you can actually depend on them.

How long that takes exactly depends on many things, like the CSS adoption rate and the market position of the browsers, and how fast the standardisation process and user migration will be. Say, 2 years for specification, 3 years before adoption by all common browser engines, and another 5 years before the majority of users have upgraded. That adds up to 10 years. Depending on the circumstances, this could be better or it could be worse. In more optimistic scenarios, those 10 years could be 7 years, or perhaps even 5, but I think 10 years is fairly realistic. You’re talking about many years in any case.

As an example, think of display: table. It has been specified (as a Recommendation) for seven years now, but the browser with currently the biggest market share still has not implemented it. Assuming that the upcoming IE7 will implement this, how many more years will it take before IE6 support can be dropped? Inline-block, which would also be immensely useful, has a similar story in Mozilla.

These are rather extreme examples and there are of course many parts of CSS 2 which have been implemented, but it is a fact that the upcoming IE7 will not implement any CSS3, and no word on a next version after that, nor the feature set it will have.

And those are just part of CSS 2.1. Even though CSS3 has a number of modules that have advanced to Candidate Recommendation, it is still very much a work in progress. CSS3 will not be supported for IE7, has little support in Opera, and even though Mozilla supports some CSS3, it is far from complete.

But it also depends on your environment, what you want to use CSS for. For example, look at ‘Prince’, a rendering engine to transform XML + CSS to PDF. If you use Prince for publishing online or on paper, you are only using a single layout engine for which development is relatively cutting-edge, and you don’t need to wait for user adoption. So in that case much of CSS3 can already be implemented and ready for you to use in two or three years, when the specifications have matured.

Anyways, the point of this section is to say that in CSS there are no short-term solutions or quick fixes. Things have to be thought out well and be solid, because it will take long for them to be usable, and once they are specified and implemented they are going to be around for a long time.

Therefore, any proposal will never solve your direct problem.

Q: What is Candidate Recommendation vs. Recommendation

In the past, Recommendation (R) meant that a spec was finished (this was the case for CSS2.0). Nowadays, Candidate Recommendation (CR) means that a spec is finished and that there is a call for implementations. Those implementations are evaluated, if there are two complete interoperable implementations of the specification, it becomes a Recommendation.

Q: Under what constraints is CSS designed?

  1. Incremental rendering (avoid reflows)

    Rendering web sites incrementally while they are being loaded is an important asset; while doing that, reflows are undesirable because they are slow and look ugly.

    Especially in CSS3 this is not always obeyed (e.g. with :nth-last-child()), but nevertheless, if you look at how CSS works and the choices that were made in its design, you will see the influences of this rule all the time.

    It also means that proposals which consider incremental rendering have a higher chance of being adopted than ones which don’t.

  2. No circular references

    Circular references means that two items (e.g. properties and/or selectors) depend on each other’s state. This can lead to infinite loops in trying to resolve their final state, and even if loop detection is performed their resulting value is unknown.

Q: What is incremental rendering

Incremental rendering is the ability to display the contents of a document which is still being loaded. This is a valueable asset, because users do not have to wait for the entire document to load, which can take a fair amount of time depending on the size of the document, the bandwidth of the client, the bandwidth of the server, the locations of the client and the server, etc.

An important part of incremental rendering is to avoid reflows. A reflow of the entire document means it has to be drawn all over again, which is a very slow process, and thus has to be avoided whenever possible.

Thus, incremental rendering and avoiding reflows is important to CSS because it keeps things fast and simple. Especially on lower-end systems such as mobile phones, webtv, and browsers on old computers such as the MSX reflows are extremely costly operations. But also on modern systems such as desktop PCs they have a considerable performance impact, resulting in very slow responsiveness while loading, and often also ugly visible ‘snaps’ when the location of things change as more content is loaded (you can often see this in table-based layouts).

Q: What are the restrictions on selectors

To avoid CSS implementations performing badly and keep selectors simple, there are a number of restrictions set on what the CSS selectors can do. After all, they have to be evaluated for all the elements in a document.

  1. Must evaluate in O(1) time.

    That means that they must always be able to run in a fixed amount of time, and may not take longer in bigger documents. The reason for this is computability.

  2. They work from an element point of view

    That means: “I have this element here, which styles apply to it?” (CSS selectors), and not “I have this query, which elements does this style apply to” (XPath).

    The reason for this is computability. Using XPath-like selectors, all styles would have be re-evaluated when the document is dynamically changed (e.g. by incremental loading).

  3. Evaluation must be possible incrementally.

    This so that documents can load incrementally without the need for reflows.

    There are already a number of CSS3 selectors which break this premise: :last-child and :nth-last-child().

  4. May not depend on properties

    The fundamental problem with this is that you can very easily create circular references, which are difficult to detect, can cause infinite loops if not caught, and have unknown behaviour if found.

    Additionally, selectors are resolved before the properties are. Therefore it is not possible to know an element’s property values at the time selector matching is done.

Q: Why does CSS have no versioning mechanism?

Many people wonder why CSS does not let the author specify a version number for the stylesheets they create, because surely that would help compatibility in the future? I will list a number of reasons for the lack of versioning information below.

There are no versions

There is only a single version of CSS. The numbers in CSS1, CSS 2.1 and CSS3 refer to the level of the specification, that is, the progress. You can call it milestones, or deliverables as well. It is probably easiest to quote Bert Bos:

CSS is too big to develop in one go. Also, to get it accepted 10 years ago in the midst of the browser wars, it had to be very simple. That's why we have levels. But levels are just conceptual distinctions, meant for us, the developers. You can see them as profiles, if you wish, just like the mobile profile or the print profile, but in reality they aren't even that.

CSS is designed to avoid the need for versioning

Primarily, the basic design of CSS contains a number of properties that make it resilient to future changes. One of those is the cascading, which makes it possible for the user to specify fallback styling in case a certain feature is not supported. Another is CSS its strict error recovery rules, which ensure that a CSS parser will ignore what it does not know in a specified manner.

Additionally, the specification process of CSS is based on publishing working drafts and asking for input from both the public and working group members, which are professional industry experts from various companies. Because of that process, most unfeasible features and design flaws are recognised early on, and removed or improved.

Of course there are occasions when a feature that made it into a final specification turns out to be sub-optimal. In those cases there is always room for creative solutions. For example, properties can be introduced to set different modes (e.g. the proposed box-model property), and properties can be turned into shorthands (numerous occasions of this in CSS3, e.g. display, display-model and display-role).

Versioning has undesirable properties

Most importantly: versioning will break forwards compatibility. For versioning to be useful, styles with unsupported versions must be ignored. The undesirable result: a new version will only be usable when it is commonly implemented, so the turnaround time between specification and sufficient user propagation will increase a lot. The user cannot use features from a newer version in a stylesheet for an older version without increasing the version number, causing it to stop working in older user agents. The only workaround is to create some kind of fallback system.

It also introduces additional complexity for implementors to deal with, having to disable certain features and changing their behavior for different versions. Creating good test suites for different versions and how they interact with eachother is very difficult. Similarly, maintaining different versions within an implementation also results in a lot of extra work and problems.

There no good reasons that versioning is desirable

If you look at the reason why people want versioning information in their CSS, you can broadly distinguish three cases:

  1. To allow for fundamental and breaking changes, e.g. grammar elements.
  2. To let the stylesheet work on a particular browser.
  3. To let the stylesheet conform to a some policy, e.g. company policy or school assignment.

In the given example of the first case, where grammar elements are changed (e.g. XML syntax, replacing CSS selectors with XPath, or changing all positioning models), you are really changing the language itself. In such a case it is doubtful whether it can still be called ‘CSS’. Quoting Bert Bos again:

In particular, if there is a need for a new style sheet language, we will make one, but it won't be called "CSS version 2." That would be just confusing. It will be called KASWI or HAPA or TUBIU or something else that can't be confused with "CSS."

An often-heard argument is that it is desirable that deprecated properties can be removed from the language. But in reality, existing CSS on the web won’t disappear for a long long time, so removing support for a certain property will break a lot of pages. That is something an implementor will never do, and something that CSS doesn’t desire to do either.

The second case is the most common reason for version information proposals. This may be unintentional, and be covered up in a syntax which does not directly relate to explicit browser names and version numbers (instead e.g. testing for ‘support’ of certain properties), but that is what it usually turns out to be. Facilitation for matching differences in implementations is not desirable, because it will encourage stylesheets authored towards only a specific number of user agents. It will also give implementors an excuse to not fix incorrect behavior.

The final case is about validation of compliance with a policy, not about changing what the stylesheet expresses. The validatìon criteria in such a case are known on beforehand, and any value specified in the stylesheet should be ignored because it is irrelevant what the author of the stylesheet thinks, nor can the value be depended on. The check for validating is done with a validator which is given the profile it has to check agains. So in this case, a version number can at best be classified as meta-information, and is rejected for the same reason as @author "Grauw", etc.

Finally, if CSS ever needs versioning, an @version "6.0"-ish rule can be introduced anytime. Until then, a versioning mechanism is not necessary and thus not desirable.

See also: Re: [CSS21] Versioning of CSS by Bert Bos, containing additional information with regard to the CSS working group’s position on versioning.

Q: How will CSS address layout?

The current layout methods using floats and faux columns are not sufficient and very hackish. This is partially given that the IE browser does not entirely support position: absolute, but more generally spoken CSS has unsufficient features for layout.

Bert Bos (CSS WG chair) wrote in a message to this list a while ago that the CSS WG was thinking about a grid layout: Re: position:fixed and same-document references

See also: The device-independent browser: CSS and grid layout

For the time being, you can use absolute positioning and the table display methods (be sure to use table-layout: fixed too) to achieve many layouts, or in more realistic scenarios (because of lack of browser support for display: table), one of the many faux columns methods.

Q: What about method X to create document order independence?

Most if not all methods that are proposed have problems with incremental rendering. If the document has two parts, A (navigation) and B (content), and the document order changing method says that B has to be rendered before A, then the browser has to reflow the entire document every time an additional part of B is loaded.

This is also the case for the abovementioned proposed grid layout, and something that table display and absolute positioning in CSS 2 were meant to avoid.

Note that you can currently already change the document order in two major browsers by means of XSLT. Although XSLT is not a really good candidate, as it can not handle incremental rendering and dynamic changes.

Also read Håkan W. Lie’s Formatting Objects considered harmful, about why Opera does and will not support XSLT (which back then was combined with XSL-FO).

Q: Why are only a few properties supported on table columns?

Only the following properties are supported for display: table-column and table-column-group elements: border, background, width and visibility. One might ask, why wouldn’t more properties be supported on table columns? It would be convenient to be able to style entire columns of a table in one go.

The answer to this is that the properties you specify on a table-column element do not get inherited by the table cells. Inheritance in CSS is done by document structure, properties can be inherited from the parent element, and in no other way. Changing this would affect incremental rendering, create the possibility of circular references, etc. In other words: complicate things and create more opportunities for UAs to behave inconsistently.

Instead, width is used by the table widths algorithm, border is handled by the special case rules for borders on tables, background is really rendered onto the column and not on the separate table cells, and is only visible because usually table cells have a transparent background, and for visibility only the table-specific collapse value has any effect.

Nevertheless, styling per column can be achieved by using td:nth-child(n). Problem with this are that this is 1. not compatible with column spans (although it could be, using [colspan=n] selectors in a verbose way), and 2. it cannot work on columns with different indexes but the same class. A selector like :nth-column() is not a solution, because it would depend on the properties set, creating circular dependencies. Also, such a selector does not address the second concern mentioned above.

Q: Why is there no align for blocks, instead having to use margin: auto?

Alignment is done by adjusting the block margins. A theoretical align: center would do the same as making both margins equal in width. And align: right would be the same as making the right margin zero, and let the left one take the remaining space.

What the CSS WG could have done is define align as a shorthand property which sets the margin-left and margin-right properties to either auto auto, 0 auto or auto 0 for center, left and right values. But that would have added additional complexity for the specification, and it already works well the way it does now.

Grauw