The Evolution of CSS in 3 Decades

Aug 17, 2021#css#history

CSS is a declarative programming language allows web designers, developer, bloggers, and so forth to make websites unique and attractive. CSS gives us the opportunity to play with a page layout, adjust colors and fonts, add effects to images, etc.

CSS has been and will continue to dominate the way we decorate websites

Nowadays web developers rarely write vanilla CSS, they often use CSS preprocessors or frameworks to leverage cooked styles and coordinate more efficiently with dynamic data coming from JavaScript.

History is boring, there’s no doubt about that, but learning history is a powerful step to embrace something and being really good at it. Let me tell you a brief story about CSS history.

A star was born

Fast backwards in 1990 HTML was invented by Berners-Lee to create electronic pages that are displayed on the World Wide Web, each page contains a series of connections to other pages called hyperlinks.

HTML was specifically designed to hold the content of a web page, it needed something else to hold the style and design as a separate concern, something like style sheet which is a collection of style rules that that tells a browser how the various styles are to be applied to the HTML tags to present the document.

CSS (Cascading Style Sheets) was first proposed by HĂĄkon Wium Lie on October 10, 1994 while working with Tim Berners-Lee at CERN and the rest is history. CSS was not the only styling language in development at the time, but the very element of cascading and developing sequence is what set it apart from the rest.

CSS is a domain-specific, declarative programming language; it describes how HTML elements are to be displayed on screen, paper, or in other media; it can control the layout, colors, and fonts of multiple web pages all at once.

html {
  font-family: sans-serif;
  font-size: 1.2rem;
  font-weight: 400;
  line-height: 1.7;
}

body {
  box-sizing: border-box;
  background-color: white;
  display: block;
  margin: 0;
}

What make CSS special

When we write CSS, we don’t tell the browser exactly how to render a page. Instead, we describe the rules for our HTML document one by one and let browsers handle the rendering. CSS followed a predictable and perhaps more importantly, forgiving format and just about anyone could pick it up. That’s a feature, not a bug.

Cascading is the core feature of CSS since its inception, styles can cascade from one style sheet to another, enabling multiple types of CSS sources to be used on one HTML document.

Inline CSS refers to CSS found in an HTML file, found in the head of a document between style tags. Inlining CSS simply means putting your CSS into your HTML file instead of an external CSS file.

Some of the advantages of using CSS are:

  • Easier to maintain and update
  • Greater consistency in design
  • More formatting options
  • Lightweight code
  • Faster download times
  • Search engine optimization benefits
  • Ease of presenting different styles to different viewers
  • Greater accessibility

CSS gives you the opportunity to create sites that look very different from page to page, without a lot of extensive coding.

One of three musketeers

CSS is one of the core languages of the open web and is standardized across web browsers according to the W3C specification.

CSS along with HTML and JavaScript are three cornerstones of the open web — HTML defines the website structure, CSS gives it look and feel, JavaScript brings interactivity and animations.

The first commercial browser to support CSS was Microsoft’s Internet Explorer 3, which was released in August 1996. The next browser to announce support for CSS was Netscape Navigator, version 4.0. The third browser that ventured into CSS was Opera.

Even though CSS was standardized for ages, browser vendors implement CSS features at their own speeds. That’s why until today CSS might still behaves differently across browsers in some features, sometimes you have to use vendor-specific prefixes to make your website look the same everywhere.

It seems frustrating when you want to use a feature and discover that it isn’t supported by one major browser, or if things seem to be behaving in different ways.

CSS over the years

CSS features are controlled and developed by W3C over the years across multiple specifications. CSS has various profiles and levels:

Profiles are typically a subset of one or more levels of CSS built for a particular device or user interface. Currently there are profiles for mobile devices, printers, and television sets. Profiles should not be confused with media types, which were added in CSS 2.

CSS 1 was released in 1996, and republished with corections in 1999. CSS 2 appeared in 1998 and built on CSS 1. CSS 2 adds support for different output media.

After CSS 2.1, CSS itself has been modularized, such that each module can be developed independently of the rest. This allows not just for existing modules to be leveled independently, but new modules to be created at any time, either defining completely new sets of features, or extending from existing CSS 2.1 features.

CSS now has more than 60 modules that define different capabilities, some already part of the standard, some still in development. The term CSS3 refers to everything published after CSS 2.1, there is no single integrated CSS4 specification.

The development of CSS hasn’t stopped. Far from it. The CSS Working Group sometimes publishes snapshots, a collection of whole modules and parts of other drafts that are considered stable enough to be implemented by browser developers.

Current State of CSS

The CSS Working Group creates and defines CSS specifications. These specifications are assigned maturity levels as they move through the design process.

When the first CSS specification was published, all of CSS was contained in one document that defined CSS Level 1. CSS Level 2 was defined also by a single, multi-chapter document. However for CSS beyond Level 2, the CSS Working Group chose to adopt a modular approach, where each module defines a part of CSS, rather than to define a single monolithic specification. This breaks the specification into more manageable chunks and allows more immediate, incremental improvement to CSS.

The story of CSS over the past couple years is one of tremendous flexibility and adaptability. CSS may not be perfect, but it’s still managed to negotiate a smooth transition to a multitude of new devices, contexts, interaction modes, and accessibility requirements.

With features like Grid, we finally have the tools needed to specify complex layouts without requiring hacks and workarounds; while blend modes, masks, and shapes (among others) let us implement designs that are richer and more creative than ever.

Layout tools are one of the areas that have seen the most changes in recent years. First FlexBox came onto the scene, and then CSS Grid emerged as the most polyvalent and expressive way of handling CSS layouts.

For a long time, writing CSS was straightforward enough: add a .css extension to your file, open up a text editor, and start typing. But over the years, CSS has developed its own ecosystem of technologies, from preprocessors like Sass and Less to methodologies like BEM and Atomic CSS, to more recent developments like CSS-in-JS.

While BEM is ahead of the pack here, Atomic CSS is also starting to gain ground with its completely new utility-class-driven philosophy.

CSS-in-JS has been one of the biggest developments of the past few years in the CSS world. Just like preprocessors bypassed CSS to introduce their own set of new features over a decade ago, CSS-in-JS libraries piggyback on JavaScript’s power to make their own path without waiting for CSS to catch up.

Problems of CSS at scale

CSS is enjoyable to write until it’s getting really messy in big projects, the problem with CSS isn’t CSS, it’s humans. This problem is compounded as styles grow, each developer needs to know more context in order to style effectively.

CSS was initially designed with simplicity in mind and it worked very well as dominant styling language for the web. The things that many JavaScript developers hate about CSS are the same things that make it so powerful.

Let’s look at some noted problems with CSS at scale:

  • Lacking of built-in namespaces - Any programming languages lacking built-in namespaces will have problems at scale and CSS is obviously one of them. Global namespace was designed as core feature of CSS to enable portability and cascading. This is the DNA of CSS, CSS-in-JS fixed that very well when build tools can intercept and generate scopes automatically for you.

  • Too static to change - Vanilla CSS is just a set of static layout rules; even though variables and expression have been added recently, CSS is still too simple to keep up with dynamic web pages. It’s hard to implement theming and dynamically changing styles based on incoming data from JavaScript.

  • Unavoidably repeating yourself - Lack of variables so we have to repeat colors all over the place. Lack of nesting so we have to repeat huge blocks of CSS all over the place. In short, CSS violates the living crap out of the DRY principle.

  • Stuck with the past - Three cornerstones HTML, CSS, JavaScript must not break the web; maintaining backward and forward compatible is the number one priority when design new features. Even though we can introduce new features but we can’t get out of bad decisions from the past completely, adoption rate and browser support are too important to revolutionize the language.

  • Resistant from static analysis - How can we apply some static analysis like dead code elimination and minification to CSS? we can’t! the global nature and cascading styles from inline, internal and external sources make it impossible to perform those kinds of optimization.

  • Non deterministic resolution to human - According to how css works, styles are merged from multiple sources (inline, internal, external stylesheets) and origins (user agent, user, author, !important, …), going though specificity calculation, inheritance and defaulting. This complicated process is not for human, it is for machine.

The modern web is moving very fast, more dynamic and at a higher level of abstraction. People don’t build websites with vanilla HTML, CSS, JavaScript anymore, it’s possible but too slow and missing out too many cooked production optimizations provided by frameworks and tools.

How can CSS meet the incompatible demands for simplicity (from developers), flexibility (from designers), and responsiveness (from users)? It can’t by itself, it needs help from more abstract high-level tools and techniques like CSS-in-JS, preprocessors to make it closer to a programming language.

Above problems will prevent CSS from being used on daily basis by developers but it still mostly works just fine behind the scenes. We’re generating plain vanilla CSS using general-purpose programming languages, this could be done at project build time, or even dynamically on every page load if you have a good caching strategy.

We don’t need to make CSS great again and accept it as a low-level technology, we should focus on building more supporting tools and languages that ultimately compiled to vanilla CSS so it can run perfectly in all browsers.