- From: Ian Hickson <py8ieh@bath.ac.uk>
- Date: Wed, 6 Oct 1999 19:52:43 +0100 (BST)
- To: www-style <www-style@w3.org>
SUMMARY: Add a way of making a declaration supplement the cascade instead of replacing it as now. This would let the following: * { counter-increment: elements; } H1 { counter-increment: headers ! supplement; } ...be equivalent to the following: * { counter-increment: elements; } H1 { counter-increment: headers elements; } THE PROBLEM: One problem in CSS at the moment is that the cascade is sometimes a little too drastic. For example, if you have more than one counter, then there is strictly no way of setting a counter to count all elements -- for example, * { counter-increment: elements; } H1 { counter-increment: headers; } ...will result in all elements *except* H1s increasing the "elements" counter. I mentioned this back when the CSS2 drafts were coming out, but I could not think of a solution at the time ([1], [2]). This problem is now getting more and more important, since the following properties either now take multiple values or have had multiple-value proposals: 'counter-increment' 'counter-reset' 'string-set' 'quotes' 'text-decoration' 'text-shadow' 'content' (to cope with broken/unsupported url() inclusions) 'height'/'width' (to cope with multiple 'content's) 'font-family' etc... THE SOLUTION: What we need is a way of indicating that a certain value should not "overwrite" the "current" value of the property, but should be appended to it. For example, the example quoted above would currently result in this cascade for H1 elements: origin | value | specificity | weight -------+----------+-------------+-------- author | elements | 000 | normal author | headers | 001 | normal ...which would result in the 'counter-increment' property getting the value "headers" for H1 elements. However, if we could say that the values should be appended to the values from other declarations, instead of replacing them, then we would could make the value of 'counter-increment' first be "headers", and then add the previous matching declaration's value ("elements"), which would result in 'counter-increment' having the value "headers elements", which would allow us to count all the elements. THE SEMANTICS: The semantics of the supplemental cascade must of course be defined. Here is what I believe to be the most useful system: 1. Sort the applicable rules as per CSS2 section 6.4.1. 2. Assign the value from the winning declaration to the property. 3. If that value was marked !supplement, then take the value from the rule which would have won, had the winning rule not been present, and append it to the property. 4. Repeat step 3 until you reach a value which was not marked as supplementing the cascade. Append that value to the property. (For those who manage Apache servers, this is similar to the way that the Options directive works with +/- prefixes.) THE SYNTAX: There are several ways of extending the current CSS syntax in a manner compatible with the forwards-compatible parsing of CSS1 to specify that the cascade should be supplemental and not replacing. Here is one, which uses syntax similar to the proposal for specifying minimum and maximum values: property : values values ! supplement; /* e.g., counter-increment */ property : values, values ! supplement; /* e.g., font-family */ Another is to fiddle with the colon: property +: values values; /* e.g., counter-increment */ property +: values, values; /* e.g., font-family */ Personally, I prefer the first syntax; it is more CSS-like as there is a precedent (the !important declaration). From here on I am going to assume that the !supplement syntax is used, although of course which syntax is used is not at all as important as the semantics of the syntax. SOME EXAMPLES: Assuming you had stylesheets where the following rules matched a particular element: /* ua.css: */ X { property: a; } /* author.css: */ X { property: b ! important ! supplement; } X.class { property: c; } X { property: d; } X#id { property: e ! supplement; } X X { property: f ! supplement; } ...you would, using the type of tables I've been using above, get the following results in the cascade: origin | value | specificity | weight | cascade type -------+----------+-------------+--------+-------------- ua | a | 001 | normal | author | d | 001 | normal | author | f | 002 | normal | supplement author | c | 011 | normal | author | e | 101 | normal | supplement author | b | 001 | imprnt | supplement The first value selected would be "b", which is marked supplemental. We set the value to this. The next value selected would be "e". We append this to the current value. This declaration is also marked supplemental, so we continue: The next value selected is "c", so we append this to the value. This declaration was not marked 'supplement' and so we stop here. The resulting value is therefore "c e b". POSSIBLE EXTENSIONS: One possible extension is that instead of !supplement, we use !append and !prepend, and the values are appended or prepended to the property as specified. This means, for example, that one could add new inner quotes as well as new outer quotes: Q { quotes: "'" "'"; } Q { quotes: "<<" ">>" ! prepend; } Q { quotes: '"' '"' ! append; } ...would be functionally equivalent to: Q { quotes: "<<" ">>" "'" "'" '"' '"'; } ...except that of course the three rules could be in three different stylesheets. (The first might be a UA rule, the second a user rule, and the third an author rule from a very polite author.) NOTES: If this proposal is used, then it would then be useful if each property definition would say whether or not it supported supplemental cascading: 'property-name' Value: legal values & syntax ... Cascading: whether this property supports supplementary cascading or limits (minimum/maximum values) For example: 'counter-reset' Value: [ <identifier> <integer>? ]+ | none | inherit Initial: none Applies to: all elements Inherited: no Percentages: N/A Media: all Cascading: supports supplementary cascading ...but 'visibility' Value: visible | hidden | collapse | inherit Initial: inherit Applies to: all elements Inherited: no Percentages: N/A Media: visual Cascading: does not support any special cascading ...and 'height' Value: [ <length> | <percentage> | auto ]+ | inherit Initial: auto Applies to: all elements but non-replaced inline elements, table columns, and column groups Inherited: no Percentages: see prose Media: visual Cascading: supports supplementary cascading and limits Comments? --- References --- [1] http://lists.w3.org/Archives/Public/www-style/1998May/0003.html [2] http://lists.w3.org/Archives/Public/www-style/1998May/0039.html -- Ian Hickson : Is your JavaScript ready for Nav5 and IE5? : Get the latest JavaScript client sniffer at : http://developer.netscape.com/docs/examples/javascript/browser_type.html
Received on Wednesday, 6 October 1999 14:52:47 UTC