Subscribe to receive notifications of new posts:

The Languages Which Almost Became CSS

2017-08-02

12 min read

This was adapted from a post which originally appeared on the Eager blog. Eager has now become the new Cloudflare Apps.

In fact, it has been a constant source of delight for me over the past year to get to continually tell hordes (literally) of people who want to – strap yourselves in, here it comes – control what their documents look like in ways that would be trivial in TeX, Microsoft Word, and every other common text processing environment: “Sorry, you’re screwed.

— Marc Andreessen 1994

When Tim Berners-Lee announced HTML in 1991 there was no method of styling pages. How a given HTML tag was rendered was determined by the browser, often with significant input from the user’s preferences. To many, it seemed like a good idea to create a standard way for pages to ‘suggest’ how they might prefer to be rendered stylistically.

But CSS wouldn’t be introduced for five years, and wouldn’t be fully implemented for ten. This was a period of intense work and innovation which resulted in more than a few competing styling methods that just as easily could have become the standard.

While these languages are obviously not in common use today, we find it fascinating to think about the world that might have been. Even more surprisingly, it happens that many of these other options include features which developers would love to see appear in CSS even today.

The First Proposal

In early 1993 the Mosaic browser had not yet reached 1.0. Those browsers that did exist dealt solely with HTML. There was no method of specifying the style of HTML whatsoever, meaning whatever the browser decided an <h1> should look like, that’s what you got.

In June of that year, Robert Raisch made a proposal to the www-talk mailing list to create a “an easily parsable format to deliver stylistic information along with Web documents” which would be called RRP.

@BODY fo(fa=he,si=18)

If you have no idea what this code is doing you are forgiven. This particular rule is setting the font family (fa) to helvetica (he), and the font size (si) to 18 points. It made sense to make the content of this new format as terse as was possible as it was born in the era before gzipping and when connection speeds hovered around 14.4k.

Some interesting things missing from this proposal were any mention of units, all numbers being interpreted based on their context (font sizes were always in points for example). This could be attributed to RRP being designed more as a “set of HINTS or SUGGESTIONS to the renderer” rather than a specification. This was considered necessary because the same stylesheet needed to function for both the common line-mode browsers (like Lynx, and the graphical browsers which were becoming increasingly popular.

Interestingly, RRP did include a method of specifying a columnar layout, a feature which wouldn’t make it to CSS until 2011. For example, three columns, each of width ‘80 units’ would look like this:

@P co(nu=3,wi=80)

It’s a little hard to parse, but not much worse than white-space: nowrap perhaps.

It’s worth noting that RRP did not support any of the ‘cascading’ we associate with stylesheets today. A given document could only have one active stylesheet at a time, which is a logical way to think about styling a document, even if it’s foreign to us today.

Marc Andreessen (the creator of Mosaic, which would become the most popular browser) was aware of the RRP proposal, but it was never implemented by Mosaic. Instead, Mosaic quickly moved (somewhat tragically) down the path of using HTML tags to define style, introducing tags like <FONT> and <CENTER>.

Viola and the Proto-Browser Wars

Then why don't you just implement one of the many style sheet proposals that are on the table. This would pretty much solve the problem if done correctly.

So then I get to tell people, "Well, you get to learn this language to write your document, and then you get to learn that language for actually making your document look like you want it to." Oh, they'll love that.

— Marc Andreessen 1994

Contrary to popular perception, Mosaic was not the first graphical browser. It was predated by ViolaWWW, a graphical browser originally written by Pei-Yuan Wei in just four days.

[IMAGE]

Pei-Yuan created a stylesheet language which supports a form of the nested structure we are used to in CSS today:

(BODY fontSize=normal
      BGColor=white
      FGColor=black
  (H1   fontSize=largest
        BGColor=red
        FGColor=white)
)

In this case we are applying color selections to the body and specifically styling H1s which appear within the body. Rather than using repeated selectors to handle the nesting, PWP used a parenthesis system which is evocative of the indentation systems used by languages like Stylus and SASS which are preferred by some developers to CSS today. This makes PWP’s syntax potentially better in at least one way than the CSS language which would eventually become the lingua franca of the web.

PWP is also notable for introducing the method of referring to external stylesheets we still use today:

<LINK REL="STYLE" HREF="URL_to_a_stylesheet">

ViolaWWW was unfortunately written to work chiefly with the X Windowing System which was only popular on Unix systems. When Mosaic was ported to Windows it quickly left Viola in the dust.

Stylesheets Before the Web

HTML is the kind of thing that can only be loved by a computer scientist. Yes, it expresses the underlying structure of a document, but documents are more than just structured text databases; they have visual impact. HTML totally eliminates any visual creativity that a document’s designer might have.

— Roy Smith 1993

The need for a language to express the style of documents long predates the Internet.

As you may know, HTML as we know it was originally based on a pre-Internet language called SGML. In 1987 the US Department of Defense decided to study if SGML could be used to make it easier to store and transmit the huge volume of documentation they deal with. Like any good government project, they wasted no time coming up with a name. The team was originally called the Computer-Aided Logistics Support team, then the Computer-aided Acquisition and Logistics Support team, then finally the 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 which is an initialism which undoubtedly stands for some combination of four words. They published a specification for the language which is as comprehensive as it is incomprehensible. It also includes one of the best nonsensical infographics to ever exist on the web.

One inviolate rule of the Internet is: more will always get done if you can prove someone wrong in the process. In 1993, just four days after Pei-Yuan’s proposal, Steven Heaney proposed that rather than “re-inventing the wheel,” it was best to use a variant of FOSI to style the web.

A FOSI document is itself written in SGML, which is actually a somewhat logical move given web developers existing familiarity with the SGML variant 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>

If you’re a bit confused what a docdesc or charlist are, so were the members of www-talk. The only contextual information given was that e-i-c means ‘element in context’. FOSI is notable however for introducing the em unit which has now become the preferred method for people who know more about CSS than you to style things.

The language conflict which was playing out was actually as old as programming itself. It was the battle of functional ‘lisp-style’ syntax vs the syntax of more declarative languages. Pei-Yuan himself described his syntax as “LISP’ish,” but it was only a matter of time until a true LISP variant entered the stage.

The Turing-Complete Stylesheet

For all its complexity, FOSI was actually perceived to be an interim solution to the problem of formatting documents. The long-term plan was to create a language based on the functional programming language Scheme which could enable the most powerful document transformations you could imagine. This language was called DSSSL.

In the words of contributor Jon Bosak:

It’s a mistake to put DSSSL into the same bag as scripting languages. Yes, DSSSL is Turing-complete; yes, it’s a programming language. But a script language (at least the way I use the term) is procedural; DSSSL very definitely is not. DSSSL is entirely functional and entirely side-effect-free.

Nothing ever happens in a DSSSL stylesheet. The stylesheet is one giant function whose value is an abstract, device-independent, nonprocedural description of the formatted document that gets fed as a specification (a declaration, if you will) of display areas to downstream rendering processes.

At its simplest, DSSSL is actually a pretty reasonable styling language:

(element H1
  (make paragraph
    font-size: 14pt
    font-weight: 'bold))

As it was a programming language, you could even define functions:

(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 in your styling, for example to ‘stripe’ the rows of a table:

(element TR
  (if (= (modulo (child-number) 2)
        0)
    ...   ;even-row
    ...)) ;odd-row

As a final way of kindling your jealousy, DSSSL could treat inherited values as variables, and do math on them:

(element H1
  (make paragraph
    font-size: (+ 4pt (inherited-font-size))))

DSSSL did, unfortunately, have the fatal flaw which would plague all Scheme-like languages: too many parenthesis. Additionally, it was arguably too complete of a spec when it was finally published which made it intimidating to browser developers. The DSSSL spec included over 210 separate styleable properties.

The team did go on to create XSL, a language for document transformation which is no less confusing, but which would be decidedly more popular.

Why Did The Stylesheet Cross The Wire

CSS does not include parent selectors (a method of styling a parent based on what children it contains). This fact has been long bemoaned by Stack Overflow posters, but it turns out there is a very good reason for its absence. Particularly in the early days of the Internet, it was considered critically important that the page be renderable before the document has been fully loaded. In other words, we want to be able to render the beginning of the HTML to the page before the HTML which will form the bottom of the page has been fully downloaded.

A parent selector would mean that styles would have to be updated as the HTML document loads. Languages like DSSSL were completely out, as they could perform operations on the document itself, which would not be entirely available when the rendering is to begin.

The first contributor to bring up this issue and propose a workable language was Bert Bos in March of 1995. His proposal also contains an early edition of the ‘smiley’ emoticon :-).

The language itself was somewhat ‘object-oriented’ in syntax:

*LI.prebreak: 0.5
*LI.postbreak: 0.5
*OL.LI.label: 1
*OL*OL.LI.label: A

Using . to signify direct children, and * to specify ancestors.

His language also has the cool property of defining how features like links work in the stylesheet itself:

*A.anchor: !HREF

In this case we specified that the destination of the link element is the value of its HREF attribute. The idea that the behavior of elements like links should be controllable was popular in several proposals. In the era pre-JavaScript, there was not an existing way of controlling such things, so it seemed logical to include it in these new proposals.

One functional proposal, introduced in 1994 by a gentleman with the name ‘C.M. Sperberg-McQueen’, includes the same behavior 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 content keyword as a way of controlling the content of an HTML element from the stylesheet, a concept which was later introduced into CSS 2.1.

What Might Have Been

Before I talk about the language which actually became CSS, it’s worth mentioning one other language proposal if only because it is in some ways the thing of an early web developer’s dreams.

PSL96 was, in the naming convention of the time, the 1996 edition of the “Presentation Specification Language.” At its core, PSL looks like CSS:

H1 {
  fontSize: 20;
}

It quickly gets more interesting. You could express element position based on not just the sizes specified for them (Width), but the actual (Actual Width) sizes the browser rendered them as:

LI {
  VertPos: Top = LeftSib . Actual Bottom;
}

You’ll also notice you can use the element’s left sibling as a constraint.

You can also add logical expressions to your styles. For example to style only anchor elements which have hrefs:

A {
  if (getAttribute(self, "href") != "") then
    fgColor = "blue";
    underlineNumber = 1;
  endif
}

That styling could be extended to do all manner of things we resort to classes today to accomplish:

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
}

Support for functionality like this could have perhaps truly enabled the dream of separating content from style. Unfortunately this language was plagued by being a bit too extensible, meaning it would have been very possible for its implementation to vary considerably from browser to browser. Additionally, it was published in a series of papers in the academic world, rather than on the www-talk mailing list where most of the functional work was being done. It was never integrated into a mainstream browser.

The Ghost of CSS Past

The language which, at least in name, would directly lead to CSS was called CHSS (Cascading HTML Style Sheets), proposed in 1994 by Håkon W Lie.

Like most good ideas, the original proposal was pretty nutty.

h1.font.size = 24pt 100%
h2.font.size = 20pt 40%

Note the percentages at the end of rules. This percentage referred to how much ‘ownership’ the current stylesheet was taking over this value. If a previous stylesheet had defined the h2 font size as 30pt, with 60% ownership, and this stylesheet styled h2s as 20px 40%, the two values would be combined based on their ownership percentage to get some value around 26pt.

It is pretty clear how this proposal was made in the era of document-based HTML pages, as there is no way compromise-based design would work in our app-oriented world. Nevertheless, it did include the fundamental idea that stylesheets should cascade. In other words, it should be possible for multiple stylesheets to be applied to the same page.

This idea, in its original formulation, was generally considered important because it gave the end user control over what they saw. The original page would have one stylesheet, and the web user would have his or her own stylesheet, and the two would be combined to render the page. Supporting multiple stylesheets was viewed as a method of maintaining the personal-freedom of the web, not as a way of supporting developers (who were still coding individual HTML pages by hand).

The user would even be able to control how much control they gave to the suggestions of the page’s author, as expressed in an ASCII diagram in the proposal:

       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 proposals, it included features which would not make it into CSS for decades, if ever. For example, it was possible 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 somewhat optimistic sci-fi vision of the future, it was believed your browser would know how relevant a given piece of content was to you, allowing it to show it to you at a larger size:

RELEVANCE > 80 ? h1.font.size *= 1.5

You Know What Happened Next

Microsoft is absolutely committed to open standards, especially on the Internet.

— John Ludeman 1994

Håkon Lie went on to simplify his proposal and, working with Bert Bos, published the first version of the CSS spec in December of 1996. Ultimately he would go on to write his doctoral thesis on the creation of CSS, a document which was heroically helpful to me in writing this.

Compared to many of the other proposals, one notable fact of CSS is its simplicity. It can be easily parsed, easily written, and easily read. As with many other examples over the history of the Internet, it was the technology which was easiest for a beginner to pick up which won, rather than those which were most powerful for an expert.

It is itself a reminder of how incidental much of this innovation can be. For example, support for contextual selectors (body ol li) was only added because Netscape already had a method for removing borders from images that were hyperlinks, and it seemed necessary to implement everything the popular browser could do. The functionality itself added a significant delay to the implementation of CSS, as at the time most browsers didn’t keep a ‘stack’ of tags as they parsed HTML. This meant the parsers had to be redesigned to support CSS fully.

Challenges like this (and the widespread use of non-standard HTML tags to define style) meant CSS was not usable until 1997, and was not fully supported by any single browser until March of 2000. As any developer can tell you, browser support wasn’t anywhere close to standards compliant until just a few years ago, more than fifteen years after CSS’ release.

The Final Boss

If Netscape 4 ignored CSS rules applied to the <body> element and added random amounts of whitespace to every structural element on your page, and if IE4 got <body> right but bungled padding, what kind of CSS was safe to write? Some developers chose not to write CSS at all. Others wrote one style sheet to compensate for IE4’s flaws and a different style sheet to compensate for the blunders of Netscape 4.

— Jeffrey Zeldman

Internet Explorer 3 famously launched with (somewhat terrible) CSS support. To compete, it was decided that Netscape 4 should also have support for the language. Rather than doubling down on this third (considering HTML and JavaScript) language though, it was decided it should be implemented by converting the CSS into JavaScript, and executing it. Even better, it was decided this ‘JavaScript Style Sheet’ intermediary language should be accessible to web developers.

The syntax is straight JavaScript, with the addition of some styling-specific APIs:

tags.H1.color = "blue";
tags.p.fontSize = "14pt";
with (tags.H3) {
  color = "green";
}

classes.punk.all.color = "#00FF00"
ids.z098y.letterSpacing = "0.3em"

You could even define functions which would be evaluated every time the tag was encountered:

evaluate_style() {
  if (color == "red"){
    fontStyle = "italic";
  } else {
    fontWeight = "bold";
  }
}

tag.UL.apply = evaluate_style();

The idea that we should simplify the dividing line between styles and scripts is certainly reasonable, and is now even experiencing a resurgence of sorts in the React community.

JavaScript was itself a very new language at this time, but via some reverse engineering Internet Explorer had already added support for it into IE3 (as “JScript”). The bigger issue was the community had already rallied around CSS, and Netscape was, at this time, viewed as bullies by much of the standards community. When Netscape did submit JSSS to the standards committee, it fell on deaf ears. Three years later, Netscape 6 dropped support for JSSS and it died a (mostly) quiet death.

What Might Have Been

Thanks to some public shaming by the W3C, Internet Explorer 5.5 launched with nearly complete CSS1 support in the year 2000. Of course, as we now know, browser CSS implementations were heroically buggy and difficult to work with for at least another decade.

Today the situation has fortunately improved dramatically, allowing developers to finally realize the dream of writing code once and trusting it will function (almost) the same from browser to browser.

Our conclusion from all of this is the realization of just how arbitrary and contextual many of the decisions which govern our current tools were. If CSS was designed the way it is just to satisfy the constraints of 1996, then maybe that gives us permission 20 years later to do things a little differently.

Cloudflare's connectivity cloud protects entire corporate networks, helps customers build Internet-scale applications efficiently, accelerates any website or Internet application, wards off DDoS attacks, keeps hackers at bay, and can help you on your journey to Zero Trust.

Visit 1.1.1.1 from any device to get started with our free app that makes your Internet faster and safer.

To learn more about our mission to help build a better Internet, start here. If you're looking for a new career direction, check out our open positions.
Cloudflare AppsHistoryDevelopersProgramming

Follow on X

Cloudflare|@cloudflare

Related posts

September 27, 2024 1:00 PM

Our container platform is in production. It has GPUs. Here’s an early look

We’ve been working on something new — a platform for running containers across Cloudflare’s network. We already use it in production, for AI inference and more. Today we want to share an early look at how it’s built, why we built it, and how we use it ourselves. ...

September 27, 2024 1:00 PM

AI Everywhere with the WAF Rule Builder Assistant, Cloudflare Radar AI Insights, and updated AI bot protection

This year for Cloudflare’s birthday, we’ve extended our AI Assistant capabilities to help you build new WAF rules, added new AI bot & crawler traffic insights to Radar, and given customers new AI bot blocking capabilities...