The appearance of the web can be improved by a style sheet mechanism that:
While the proposed style sheet mechanism is general enough to apply to all versions of HTML, it is being developed in conjunction with HTML3 and closely matches its design guidelines. Also, this document should be general enough to apply to other DTDs than HTML.
<HEAD> <TITLE>Title</TITLE> <STYLE notation=css> h1: font.family = helvetica </STYLE> <LINK rel=StyleSheet href="bill.style"> </HEAD>
Typically, a company-wide style sheet will reside in one location and be referenced through a LINK. The author may add style hints in the STYLE element. If conflicts arise, the hints inside STYLE will override those referenced through LINK.
P: font.family = helvetica EM: back.color = red
h1, h2: font.family = helvetica[Note that element groups replaces the previously proposed element regular expressions (h[12]: font.family = helvetica).]
<HTML> <HEAD> <TITLE>Title</TITLE> <STYLE> H1.punk: font.color = #00FF00 </STYLE> </HEAD> <BODY> <H1 class = punk>Way too green</H1> </BODY> </HTML>[Should we add addressing based on other attributes/values?
A{HREF} : font.color = red H1{CLASS = huge} : font.size = 60ptClearly more general]
The document default is addressed with an asterisk:
*: font.family = futuraNote that regular expressions in general are not supported in the style sheet notation.
Character-level elements (i.e. elements that do not cause a paragraph break, as opposed to the block-level elements which do) inherit values from the surrounding block. E.g., If no color value has been assigned to EM, emphasized text will inherit the color from the surrounding text, not from the document-wide default.
Also, elements "inherit" their horizontal and vertical position from ancestors. See the Formatting Model for more on this.
/H1 P/: font.style = boldThe initial "/" indicates the start of a sequential pattern search. All property assignments are performed on the last element of the search pattern. Subclasses can be specified in the search pattern:
/H1 P.ingress/: font.style = boldOnly children of BODY are regarded in sequential search patterns.
By specifying a hierarchical search pattern, one can set properties based on the ancestors of an element. E.g., since headlines often are rendered in bold, one may want to assign a different color to the EM element within an headline:
(H1(EM: font.color = red[Alternative syntax:
(H1 EM: font.color = red (H1(EM)): font.color = red]
Class specifications are also allowed in a hierarchical search pattern.
It is important to syntactically mark the difference between style properties of the environement and HTML elements. One should be careful when picking names. Here are some possibilities:
$HTML-SOURCE: font.family = courier; font.size = 12pt; $CLIENT-WINDOW: width = 600px; height = 800px; $CLIENT-WINDOW: font.family = helveticaAn initial '$' marks envionment elements.
This document suggests a liberal terminology for describing fonts, and a level of detail similar to current desktop publishing applications:
NAME | UNITS |
---|---|
font.size | spatial, index |
font.family | |
font.style | |
font.color | color |
font.leading | spatial |
font.spacing | percent |
H1: font.size = 20pt // points H2: font.size = 15px // pixels H3: font.size = 1.35% // 1.35% of the widthAlso, a font size can be an index into an array of font sizes. The index is in the range of 1-7, the default being 3:
P: font.size = 4; EM: font.size = +2;In the latter example, the font size is expressed relative to the surrounding text.
H1: font.family = futura, helvetica P: font.family = new-century-schoolbook times PRE: font.family = courierList items are separated by white space and/or commas. Spaces in font familiy names are replaced with dashes.
A font style can be one or more these keywords:
H1: font.style = bold, italicIf two keywords are mutually exclusive, they should be regarded as a prioritized list:
P: font.style = demi-bold, boldHere, "bold" is used if "demi-bold" is not available.
Most of the above keywords are well-defined in current literature, but one group of keywords demand explantaions:
KEYWORD | EFFECT |
---|---|
small-caps | All lower-case text in a small caps region is changed to small capital letters. Also, punctuation character adjacent to affected letters are resized to match the small caps. The rendering of the letters uses the undersize.font.* properties. |
big-caps | All capital letters are rendered using the oversize.font.* properties. Also, punctuation adjacent to affected letters is resized. |
big-initial | The initial letter of the element is rendered using the oversize.font.* properties. Also, punctuation characters adjacent to affected letters are resized. |
dropped | All characters displayed using the oversize.font.* properties are dropped below the baseline so that they vertically align with the rest of the text in the element. |
Using these, commonly used typographic effects can be achived:
(Style sheet) EM.first : font.style = dropped big-initial small-caps EM.first : font.size = 12pt EM.first : undersize.font.size = 12pt EM.first : oversize.font.size = 24pt // assuming leading is zero (HTML) <EM class=first>The first</EM> few words of an article in The Economist.. (Output, very primitive version) ___ | HE FIRST few words |of an article in the Economist.The example raises a few issues:
H1: font.weight = bold P: font.slant = obliqueThis is not only syntactic sugar, since the attributes would be expected to inherit independantly of each other.]
H1: font.color = DarkRed; P: font.color = #F00The corresponding property for the background color is back.color. A more detailed description of ways to specify color can be found in the section on units.
P: font.size = 12pt; font.leading = 14pt
P: font.spacing = 120%
Example of use:
H1: font.style = big-caps H1: oversize.font.size = +3 // a la Netscape P: font.style = dropped big-initial P: oversize.font.size = 4x // i.e. cover 4 line's height P: oversize.font.style = sans & italic & bold
NAME | UNITS |
---|---|
margin.left | spatial |
margin.right | spatial |
margin.top | spatial |
margin.bottom | spatial |
[is "space" a better word than "margin"?]
[Also, there should be a way of indicating how much of the margin should have the the same background as the content; the rest of the box should inherit the background from the surrounding box.]
NAME | UNITS |
---|---|
back.color | color |
back.image | url |
NAME | UNITS |
---|---|
add.before | html |
add.after | html |
Example:
H1: add.before = <TABLE BORDER> H1: add.after = </TABLE>[Is "add" a good word? text.header? enclosure.above? ]
NAME | UNITS | COMMENT |
---|---|---|
indent | indentation of the first line, alternative is line.indent or margin.first | |
align | alignent of content in block | |
width | spatial | sets the width of a box (instead of being the area betweens the margins) |
height | spatial | sets the height of a box (instead of being the area betweens the margins) |
Should link properties be attached to the anchor tag? This is in line with the rest of the proposal, but seems less than intuitive:
A: font.color = #00F (H1(A)): font.color = #F00Perhaps a separate property:
html: txtlink.color = #00FThen, one could also set per element link properties:
P: txtlink.color = #00F H1: txtlink.color = #F00[Too much flexibility??]
Should one be able to set different values according to the type of link, e.g. text or image?
P: text.link.color = #00F P: image.link.color = #0F0 P: link.style = 3DWill this mean we'll have to extend the language for each new media type that comes out?
txtlink.color = blue txtlink.color = blue < AGE / 7d < "Background Color" imglink.color = default imglink.size = 3px imglink.style may be line, bevel, default, none txtlink.style may be underline, double underline, inverse, default, none[Check out Kevin's last comments on this]
*: numbering = on|off *: number.style = arabic|lowerroman|upperroman|loweralpha|upperalpha *: number.inherit = on|off
inches (in) pixels (px) centimeters/millimeters (cm/mm) ems (em) ens (en) points (pt) characters(ch) picas (pa)
Different ways to specify red:
EM: font.color = #F00 EM: font.color = #FF0000 EM: font.color = 255, 0, 0 EM: font.color = 1.0, 0.0, 0.0 EM: font.color = redThe conversion of color names ("red") to a corresponding RGB value is often window-system dependant. It would be beyond this specification to sanction a list of color names and their values. It is suggested that color-capable GUI clients, regardless of window systeme, support the basic colors of the english language with light and dark variations:
H1: font.color = Yellow EM: font.color = DarkRed; STRONG: font.color = LightBlue;
h1: font.size = 4 h1: oversize.font.size += 2[There should be a way for the user (only?) to set the array of fonts]
[Index could also be used to set e.g. the weight of a font?]
The following environemnent variables are available for use in style sheets:
Set the left margin to be 1/10 of the window width, but always more than 2em and less than 20em:
html : margin.left = 2em < $WIDTH/10 < 20emLet the color of the background fade from white to yellow as the document ages. After two days (2d), the fading process is complete:
html : color.background = white < $AGE/2d < yellowLet the color of text links change from red to blue as the document loads:
html : text.link = red < $FETCHED < blue[Replace syntax with Metafont's as suggested by Bert.]
h2: font.size = h1[font.size] * 0.8 P : font.size = H1.foo[font.size] - 12 pt[What's the best notation for referencing other values? Previously, this document suggested: "H1.foo:font.size"]
The notation for setting relative values:
h1: font.size = 4 h1: oversize.font.size += 2
define "My Gray" "191, 191, 191" P : font.color = "My Gray"This would be a simple and workable scheme. What do we gain from going one step further and introduce variables?
When the indicated preferences conflict, the style sheet mechanism needs a way to resolve the disagreement. In this proposal, both the reader and the author can associate weight with their preferences:
font.family = helvetica ! important font.color = black ! insist[Bill proposes using a standard notation for the priority, e.g. "h1: font.family=courier ; priority=insist"]
The list below indicates the hierarchy of style hints:
reader lens used for interactive control, e.g. "zoom in" reader insist e.g. to compensate for handicaps author important/insist to indicate special weight reader important author normal default weight, no tagging needed reader normal taken from initial document application default hardcoded fallback valuesIn addition to the important and insist tags, the legal tag indicates that there are legal reasons for the choice of styles, e.g. a font size requirement:
P: font.size = 12pt ! legal "IATA regulations"The optional string following legal gives an explanation for its use. The client should warn the reader, and display the explanation, when style hints tagged "legal" are overridden and this isn't clear from the context.
Contexts where this should be clear:
One should also keep in mind that:
image : img back : background, bg fore : foreground, fg pt : point, points pa : pica, picas etc.
h1: font.size = 12pt; back.color = red h1, h2: font.family = helvetica; font.size = 12pt[possible font-specific grouping:
P: font = 12/14 times bold]
h1: margin.left = 20pt; margin.right = 30pt; p: margin.top = 15pt; margin.bottom = 10pt;Vertically, all boxes are attached to the above box. Note that the abov box doesn't necessarily contain the preceding HTML element. See the last box for an example.
Horizontally, boxes inherit the maximum space after the ancestor's margins have been deducted.
This is a very simple example that shows how an H1 element is followed by a P, and how their margins are added to the ones belonging to BODY:
___________________________________ | | | (BODY margins) | | _____________________________ | | | | | white space = margins | | (H1 margins) | | '.' = white space | | | | ';' = unclaimed territory | | This.is.the.headline!.. | | | |_____________________________| | | | | | | | (P margins) | | | | | | | | This.is.the.paragraph.. | | | | which.is.used.to.convey | | | | how.elements.are.put.on | | | | top.of.each.other...... | | | |_____________________________| | | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |___________________________________|When nested lists are added, the picture becomes a bit more complicated:
___________________________________ | | | (BODY margins) | | _____________________________ | | | | | | | (UL margins) | | <- first level UL element | | ________________________ | | | | | | | | | | | (LI margins) | | | | | | | | | | | | First.item........ | | | | | |________________________| | | | | | | | | | | | (UL margins) | | | <- second level UL element | | | __________________ | | | | | | | | | | | | | | | (LI margins) | | | | | | | | | | | | | | | | Second.item... | | | | | | | |__________________| | | | | | |________________________| | | | |_____________________________| | | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |___________________________________|Note that the left edge of the second-level UL box ends up being aligned with the above LI box since they both are children of the first-level UL element.
Since boxes are stacked vertically, some interesting effects can be achived if sequential boxes don't end up on top of each other. In this way, "hanging headlines" and simple multiple-column layouts can be supported:
__________________________________________ | | | (BODY margins) | | ______________ _____________________ | | | |;| | | | | (H1 margins) |;| (P margins) | | | | |;| | | | | Headline... |;| While.the.paragraph | | | | comes.here. |;| starts.here.and.... | | | |______________|;| continues.below.the | | | ;;;;;;;;;;;;;;;;;| box.to.the.left.... | | | ;;;;;;;;;;;;;;;;;|_____________________| | | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |__________________________________________|The above could be realized through:
h1: margin.left = 10%; margin.right = 60% p: margin.left = 50%; margin.right = 10%The percentages are relative to the width of the canvas