Contents
The @prototype rule allows document authors to structure and abstract meaningful layers in their CSS selector architecture. It also allows browsers to parse far less code, because base classes will not be redefined in every instance of an object. The prototype name is a class selector that identifies the prototype being declared. The '@prototype' keyword must be followed by the prototype name and a declaration block.
The following example defines a prototype based on standard module format:
@prototype .mod {
margin: 10px;
}
Examples:
.weatherMod {
extends: .mod;
}
A preprocessor would output the following code:
.mod, .weatherMod{ ... }
.mod .inner, .weatherMod .inner { ... }
.weatherMod { ... }
UAs should respect the original cascade order of the rules declared for both mod and weatherMod when processing @prototype rules. Unlike @mixin property value pairs are not copied to the current location in the code. UAs may choose to process the html as though all elements with the class name weatherMod also had the class name mod.
@@@Prototypes are then modified by any selector which includes the prototype class name. Any subnodes in modifying rulesets become shadow nodes of the prototype and can only be modified by objects that extend the prototype.
.mod .inner {
position: relative;
}
Inner is now a subnode of the mod prototype. It cannot exist idependently from mod and cannot be modified by any class which does not extend mod.@@@
Subnodes become shadow nodes, which means they belong to the prototype object. When the prototype is extended, subnodes are also affected.
UAs should not allow classes which do not extend a prototype to modify subnodes belonging to the prototype. All subnodes do not belong to a prototype, but rather only those which have been included in a selector string containing the class name associated with that prototype. Consider the following invalid example.
.leftCol .inner {
color:red;
}
UAs should ignore this invalid rule because left col does not extend mod and therefore cannot style inner because it is a subnode of the mod prototype. If a developer API is provided by the UA, a warning should be issued indicating that this rule was ignored.
.leftCol h3 {
color:red;
}
This rule, while bad form, is valid because h3 is not a property node of the mod object, even if h3 happens to be inside a module within the left column.
Value: | <simple selector> | <group> |
Initial: | none |
Applies to: | all |
Inherited: | no |
Percentages: | N/A |
Media: | all |
Computed value: | as specified |
This property specifies whether an element extends another element. Its goal is to limit the number of classes which need to be applied to an HTML element for proper code abstraction and to pull the abstraction layer into the CSS where it can more easily be managed or modified throughout the life of the site. Values have the following meanings:
UAs must apply the 'extends' property each time the value matches the selector of another rule. Any portion of the document tree matching the value should be duplicated for the selector on which the extends property was invoked. The specificity and cascading order should exactly match that of the original document tree.
Consider the following example of a main navigation list which extends a base-class nav. Here is the source:
<ul class="mainNav">
<li>Home</li>
<li>About</li>
<li>Products</li>
</ul>
Here is the style sheet controlling the extends property:
.nav{background-color: #e2e2e2; border: solid 1px gray;}
.mainNav{background-image: url(nav.png); extends:.nav;}
If correctly implemented, the following CSS and CSS/HTML solutions would produce the same result as the extends example above. Preprocessors or compilers could be implemented to achieve this result for UAs that do not support the extends property.
The comma-delimiter equivalent quickly becomes unreadable and unmaintainable on style sheets of even average complexity, but is useful as part of a preprocessor or POC.
A preprocessor would output the following code:
.nav, .mainNav{background-color: #e2e2e2; border: solid 1px gray;}
.mainNav{background-image: url(nav.png);}
The multiple class equivalent uses multiple class names to achieve the same rendering. Unfortunately it leads to extraneous and often abstract class names and a dependency on HTML to define CSS abstractions.
Mulitiple class equivalent:
<ul class="nav mainNav">
<li>Home</li>
<li>About</li>
<li>Products</li>
</ul>
Style sheet:
.nav{background-color: #e2e2e2; border: solid 1px gray;}
.mainNav{background-image: url(nav.png); }
Only simple selectors may be used to identify or extend prototypes. These simple selectors are limited to class names.
.foo{extends: .bar} .bar{extends: .foo}
When extends is declared twice the last definition overwrites the first according to normal rules of the cascade.
.bar {extends: .foo; extends: .moo}
In the example above, bar would extend only moo and would not extend foo.
Value: | required | optional | integer | inherit |
Initial: | optional |
Applies to: | all |
Inherited: | no |
Percentages: | N/A |
Media: | all |
Computed value: | as specified |
This property allows a document author to indicate that the last node in a selector string must be present in the HTML. It can only be used when the node is a subnode of an @prototype. Values have the following meanings:
UAs must add the missing nodes to the prototype if they are not present in the HTML. (@@@Good idea???)