, ( ) , ( ) , TeX, Microsoft Word . : ", ".
— , 1994
When Tim Berners-Lee announced the creation of HTML in 1991, there was no way to style pages. The way HTML tags were rendered was determined by the browser and was significantly influenced by user preferences. However, it seemed like a good idea to create a standard tool that allows pages to "hint" about their preferred stylistic rendering.
But before the advent of CSS, it was still five years, and another ten years before it was fully implemented. It was a period of hard work and innovation that led to the creation of many competing stylizations that could well become standard.
While these languages are obviously not widely used today, it is interesting for me to reflect on what the world might be like. Even more surprising, many of these languages have features that developers would happily use in CSS even today.
First candidate
In early 1993, the Mosaic browser did not even reach version 1.0, and all existing browsers only worked with HTML. There was no way to specify the HTML style, so you saw the tag
<h1>
the way the browser decided to show it.
In June of the same year, Robert Reisch submitted a proposal to the www-talk mailing list to create an “easily parsed format for conveying stylistic information along with web documents,” which he called RRP.
@BODY fo(fa=he,si=18)
It's quite forgivable if you don't understand what this code does. In the pre-gzip era, when connection speeds were typically less than 14.4 kbps, it was logical to keep the content of this new format as compact as possible. Specifically, this rule selects
fa
Helvetica ( he
) as the font family ( ) and sets the font size ( si
) to 18 points.
Curiously, Reisch's proposal lacked units, all numbers were interpreted based on context (for example, all font sizes were in points). This is because RRP was designed more as a “set of tips and tricks for the renderer” rather than a specification. This was considered necessary because the same stylesheet was supposed to work in regular text-mode browsers (likeLynx ), and in the increasingly popular graphical browsers.
Lynx Browser Screenshot
Interestingly, RRP includes a way to specify columnar layout - this was not possible in CSS until 2011. For example, three columns, each 80 units wide, would look like this:
@P co(nu=3,wi=80)
It's a bit tricky to parse, but probably not much more difficult than
white-space: nowrap
.
It's worth noting that RRP did not support any of the "cascading" that we associate stylesheets with today. Any document could have no more than one active style sheet at a time, which is quite logical in the case of styling documents, although it is unusual for us today.
Marc Andreessen (creator of Mosaic, which eventually became the most popular browser) knew about the RRP proposal, but never implemented it in Mosaic. Instead, Mosaic almost immediately took the path of using HTML tags for styling (which is pretty tragic), adding tags like
<FONT>
and <CENTER>
.
Viola and the Proto Browser Wars
“Then why not just implement one of the many stylesheet proposals out there. With the right structure, this would almost completely solve the problem. "
Then I would have to tell people, "Okay, you need to learn this language to write a document, and then learn another language to make the document look the way you want it." Oh, they would just love it.
- Mark Andreessen, 1994
Contrary to popular belief, Mosaic was not the first graphical browser. It was preceded by ViolaWWW , a graphical browser originally written by Pei-Yuan Wei in just four days.
Screenshot of Viola Browser
Pei-Yuan created a stylesheet language that supports the kind of hierarchical structure used in CSS today:
(BODY fontSize=normal
BGColor=white
FGColor=black
(H1 fontSize=largest
BGColor=red
FGColor=white)
)
In this case, we are applying colors to the body of the document (body) and, in particular, we are styling
H1
that are inside the body. Instead of repeating selectors to control this nesting, PWP used the parenthesis system, which makes us think of the indentation systems used in languages like Stylus and SASS, which some developers still prefer over CSS today. This potentially makes PWP syntax better in at least one respect than CSS, which has evolved over time into the universal language of the web.
PWP is also notable for the fact that it has a way to refer to external stylesheets, which we still use today:
<LINK REL="STYLE" HREF="URL_to_a_stylesheet">
Unfortunately, ViolaWWW was written primarily to work with the X Window System , which was only popular on Unix systems. When Mosaic was ported to Windows, it quickly brought Viola to dust.
Style sheets before the web
HTML is the kind of thing that only a computer scientist can fall in love with. Yes, it expresses the internal structure of a document, but documents are not only structured text databases; they have a visual impact. HTML completely destroys any graphic creativity a document developer might have.
- Roy Smith, 1993
The need for a language capable of expressing the style of documents is much older than the Internet itself.
As you probably know, the HTML we know was originally based on a pre-Internet language called SGML. In 1987, the US Department of Defense decided to test whether SGML could be used to simplify the storage and transfer of its huge volumes of documentation. Like any good government project, the first thing they did was come up with a name. The team was originally named Computer-Aided Logistics Support team, then Computer-aided Acquisition and Logistics Support team, and then, finally, Continuous Acquisition and Life-cycle Support initiative. In any case, the initials were CALS.
The CALS team created a language for styling SGML documents called FOSI. She publisheda language specification that is as detailed as it is incomprehensible. It included my favorite of the most meaningless infographics that have ever existed on the web.
One rule of the Internet that has no exceptions is that you always get more done if you can prove someone wrong in the process. In 1993, just four days after Pei-Yuan's proposal, Stephen Heaney proposed that instead of reinventing the wheel, it would be better to use the FOSI version of styling the web.
The FOSI document itself is written in SGML, which is a pretty logical move given the familiarity of web developers with a version of SGML called HTML. An example document looks like this:
<outspec>
<docdesc>
<charlist>
<font size="12pt" bckcol="white" fontcol="black">
</charlist>
</docdesc>
<e-i-c gi="h1"><font size="24pt" bckcol="red", fontcol="white"></e-i-c>
<e-i-c gi="h2"><font size="20pt" bckcol="red", fgcol="white"></e-i-c>
<e-i-c gi="a"><font fgcol="red"></e-i-c>
<e-i-c gi="cmd kbd screen listing example"><font style="monoser"></e-i-c>
</outspec>
Perhaps you do not understand what it is
docdesc
or charlist
, just as the members did not understand it www-talk
. The only contextual information is what e-i-c
"element in context" means. However, FOSI is notable for the first time it introduced the unit of measurement em
, which has now become the preferred way of sizing in CSS.
The resulting conflict of languages was in fact as old as programming itself. It was a battle between functional lisp-style syntax and syntax in more declarative languages. Pei-Yuan himself described his syntax as "LISP-like", but it was only a matter of time before the true LISP version appeared on the scene.
Turing-complete style sheet
Despite its complexity, FOSI was actually perceived as an intermediate solution to the problem of document formatting. The long-term plan was to create a language based on the functional programming language Scheme, capable of implementing the most powerful document transformations imaginable. This language was named DSSSL. Let's give the floor to one of the developers of the language, John Bosak:
Don't mistake DSSSL as a scripting language. Yes, DSSSL is Turing complete; yes, it is a programming language. But a scripting language (at least in my interpretation of the term) is procedural; and DSSSL is definitely not. DSSSL is fully functional and completely free of side effects. Nothing ever happens in the DSSSL stylesheet. A stylesheet is one huge function, the value of which is an abstract, device-independent, non-procedural description of a formatted document, as a specification (a declaration, if you wish) of the regions to be rendered, passed to the underlying renderers.
In its simplest form, DSSSL is indeed a pretty logical styling language:
(element H1
(make paragraph
font-size: 14pt
font-weight: 'bold))
Since it was a programming language, you could even define functions in it:
(define (create-heading heading-font-size)
(make paragraph
font-size: heading-font-size
font-weight: 'bold))
(element h1 (create-heading 24pt))
(element h2 (create-heading 18pt))
And use mathematical constructs when styling, for example, to make table rows stripes:
(element TR
(if (= (modulo (child-number) 2)
0)
... ;even-row
...)) ;odd-row
To make you even more jealous, let's say that DSSSL could treat inherited values as variables and perform mathematical operations on them:
(element H1
(make paragraph
font-size: (+ 4pt (inherited-font-size))))
Unfortunately, DSSSL had a fatal flaw common to all Scheme-style languages: too many parentheses. In addition, its specification was overly complete at the time of final release, which intimidated browser developers. The DSSSL specification included over 210 individual styled properties.
Further development work led to the creation of XSL - an equally convoluted, but much more popular document transformation language.
Why stylesheet won
CSS does not have parent selectors (a way to style a parent based on the children it contains). This fact has been plaguing Stack Overflow users for a long time , but it turns out there is a pretty good reason for their absence. In the early days of the Internet, it was considered critical that a page could be rendered before the document was fully loaded. In other words, it was necessary to be able to render the top-of-page HTML before the end-of-page HTML was fully loaded.
Having a parent selector would mean that the styles need to be updated as the HTML document is loaded. Languages like DSSSL were completely ruled out because they could perform operations on the document itself, which was not fully available at the time of rendering. Bert Bose was the
first to bring up this problem in March 1995 and propose a working language to solve it. His proposal also contains an early version of the emoticon "smiley" :-).
The language itself was rather "object-oriented" in syntax:
*LI.prebreak: 0.5
*LI.postbreak: 0.5
*OL.LI.label: 1
*OL*OL.LI.label: A
The symbol
.
denoted the nearest children, and the *
ancestors.
Bose's language had another interesting property: it was possible to specify how elements like links work in the stylesheet itself:
*A.anchor: !HREF
In the example above, we specified that the link element's navigation address is the value in its attribute
HREF
. This idea that the behavior of elements like links should be controlled has been popular in many other proposals. In the pre-JavaScript era, there was no way to control such aspects, so it seemed logical to include them in these proposals.
In one draft of a functional language, proposed in 1994 by a gentleman named S.M. Sperberg-McQueen, the same behavior is implemented functionally:
(style a
(block #f) ; format as inline phrase
(color blue) ; in blue if you’ve got it
(click (follow (attval 'href))) ; and on click, follow url
His language also introduced the keyword
content
as a way to manipulate the content of an HTML element from a stylesheet. This concept was later added in CSS 2.1.
What could the web be
Before talking about the language that actually became CSS, it is worth mentioning one more language proposal, if only for the reason that it, in a sense, was the dream of the first web developers.
PSL96 was, as the name suggests, the 1996 version of the Presentation Specification Language. At its core, PSL looks like CSS:
H1 {
fontSize: 20;
}
However, things quickly get much more interesting. For example, it was possible to express the position of an element not only depending on the size (
Width
) given to it , but also on the true ( Actual Width
) size in which it is rendered in the browser:
LI {
VertPos: Top = LeftSib . Actual Bottom;
}
You can see from the example that you could also use the left sibling as a constraint.
Boolean expressions could also be added to styles. Here's an example of styling only anchor elements that have
href
:
A {
if (getAttribute(self, "href") != "") then
fgColor = "blue";
underlineNumber = 1;
endif
}
This styling could be extended to all sorts of aspects, for which we use classes today:
LI {
if (ChildNum(Self) == round(NumChildren(Parent) / 2 + 1)) then
VertPos: Top = Parent.Top;
HorizPos: Left = LeftSib.Left + Self.Width;
else
VertPos: Top = LeftSib.Actual Bottom;
HorizPos: Left = LeftSib.Left;
endif
}
Supporting this functionality would probably make it possible to finally realize the dream of separating content from style. Unfortunately, this language is too extensible, that is, there was a high probability that its implementation would be very different in different browsers. In addition, it was published in a series of articles in the scientific world, and not on the www-talk mailing list, where the bulk of the constructive work took place. It has never been integrated into any popular browser.
Ghost of the past CSS
The language that could directly lead to the creation of CSS (at least as the name suggests) was CHSS (Cascading HTML Style Sheets). It was proposed in 1994 by Håkon W Lie.
Like most good ideas, the initial proposal was pretty crazy.
h1.font.size = 24pt 100%
h2.font.size = 20pt 40%
Pay attention to the percentages at the end of the rules. This percentage means how much "ownership" the current style sheet has over that value. For example, if the previous style sheet
h2
had a font size specified 30pt
for 60%
"ownership", and the style sheet h2
specified a style for for 20px 40%
, then the two values can be combined based on their percentage of ownership to produce a value of about 26pt
.
It is quite understandable why such a proposal was made in the era of documentary HTML pages: such a design based on trade-offs would not be understood in our application-oriented world. Be that as it may, it came up with the fundamental idea of the need for a cascading style sheet structure. In other words, the idea that multiple style sheets are needed on the same page.
In its original formulation, this idea was generally recognized as important because it gave the end user control over what they saw. The original page could have one style sheet, and the web user could have their own style sheet and they could be combined to render the page. Supporting multiple stylesheets was seen as a way to preserve personal freedom on the web, not as a way to support developers (who still hand-coded every single HTML page).
The user might even be able to control the degree of control he gave to the page author's recommendations; such control in a language sentence was described by an ASCII scheme:
User Author
Font o-----x--------------o 64%
Color o-x------------------o 90%
Margin o-------------x------o 37%
Volume o---------x----------o 50%
Like many of these assumptions, this project contained features that appeared in CSS only decades later, if not at all. For example, it had the ability to write logical expressions based on the user's environment:
AGE > 3d ? background.color = pale_yellow : background.color = white
DISPLAY_HEIGHT > 30cm ? http://NYT.com/style : http://LeMonde.fr/style
In a rather optimistic sci-fi vision of the future, it was assumed that the browser would know how relevant each piece of content is to the user, allowing it to be displayed at a larger size:
RELEVANCE > 80 ? h1.font.size *= 1.5
We all know what happened next
Microsoft is fully committed to open standards, especially on the Internet.
- John Ludeman, 1994
Haakon Lee continued to work on simplifying his proposal, and jointly with Bert Bose published the first version of the CSS specification in December 1996. He ended up writing his Ph.D. thesis on creating CSS and this document helped me tremendously in writing this article.
Compared to many other proposals, the notable aspect of CSS was its simplicity. It's easy to parse, easy to write and easy to read. As has often happened in the history of the Internet, the winner is the technology that is easiest for a beginner to master, and not the one that turned out to be the most powerful for specialists.
This in itself is a reminder of how random innovation can be. For example, support for contextual selectors (
body ol li
) was only added because Netscape already had a way to remove borders from images that were hyperlinks, and it seemed necessary to do everything the popular browser could do. The functionality itself caused a significant delay in the implementation of CSS, because at the time, most browsers did not store a "stack" of tags when parsing HTML. This meant that the parsers needed to be redesigned to fully support CSS.
Because of these issues (and the widespread use of non-standard HTML tags for styling), CSS was not usable until 1997, and was not fully supported by any browser until March 2000. As any developer will tell you, browser support was very far from being standards-compliant and that changed just a few years ago, fifteen years after CSS was released.
Netscape 4 CSS,<body>
, , IE4<body>
, , CSS ? CSS. , IE4 , Netscape 4.
—
Internet Explorer 3 is famous for being released with (rather terrible) CSS support. It was decided that in order to be able to compete in Netscape 4, there must also be support for this language. However, instead of redoubling efforts to implement this third language (after HTML and JavaScript), it was decided that it should be implemented by converting CSS to JavaScript and then executing it. Worse, it was decided that this intermediate JavaScript Style Sheet should be available to web developers .
The syntax was plain JavaScript with the styling API added:
tags.H1.color = "blue";
tags.p.fontSize = "14pt";
with (tags.H3) {
color = "green";
}
classes.punk.all.color = "#00FF00"
ids.z098y.letterSpacing = "0.3em"
It was even possible to define functions whose values were calculated upon encountering each occurrence of a tag :
evaluate_style() {
if (color == "red"){
fontStyle = "italic";
} else {
fontWeight = "bold";
}
}
tag.UL.apply = evaluate_style();
The idea of simplifying the dividing line between styles and scripts is quite reasonable, and today it is even being reborn in the React community .
JavaScript itself was a very young language at the time, but thanks to reverse engineering, support for it was added in IE3 (in the form of JScript). A much bigger issue was that the community was already rallying around CSS at the time, and Netscape was viewed as an offender by most of the standards community at the time . When Netscape proposed JSSS to the standards committee, it turned a deaf ear. Three years later, Netscape 6 dropped support for JSSS and it gradually died.
What could await us
Thanks to public censure from the W3C, Internet Explorer 5.5 was released with almost full CSS1 support in 2000. Of course, as we now know, browser implementations of CSS have been terribly buggy and difficult to work with for at least another decade. Fortunately, today the situation has improved significantly, which finally made it possible to realize the dream of developers that you can write code once and it will function (almost) the same in different browsers.
Personally, I drew from all of this how arbitrary and contextual the decisions that govern our modern tools were. If CSS was designed to be compatible with the constraints of 1996, then maybe twenty-odd years later that gives us permission to do things a little differently.