Skip to main content

The history of the web browser

History of the web browser
(Image credit: Getty Images)

The history of the web browser is crucial to answering questions about modern web design. In this article, we'll explore the answer to the question: can you design websites as resilient as the world wide web itself? We dive into the history of the world wide web to find out.

Amazingly, you can browse websites made today in a browser that was made three decades ago. There won't be any styling. There won't be any scripting. Neither CSS nor JavaScript existed at the birth of the web, and they certainly didn't use the best web design tools around today. But if a website has been built in a robust way, it will still make sense even when viewed in an ancient web browser.

From the beginning

On 12 March 1989, a young computer scientist named Tim Berners-Lee published a memo. He was working at CERN, the European Organisation for Nuclear Research. The thousands of scientists working there needed a way of collaborating over the internet. Berners-Lee had a potential solution. He published his idea under the title Information Management: A Proposal.

It wasn't exactly a page-turner and the diagrams were completely incomprehensible. But there was enough there to get the project started. This project became the world wide web. Within a year of publishing his initial proposal, Berners-Lee created the first version of HTML, the first web server and the first web browser. The browser was somewhat confusingly named WorldWideWeb.

Thirty years on from the original proposal for the world wide web, a group of designers and developers gathered together for a week at CERN to recreate the experience of using that first ever web browser. You can see the final result here

Extending the web

History of the web browser

The first version of the HyperText Markup Language had just a handful of elements (Image credit: https://worldwideweb.cern.ch)

Scientific collaboration was the first use-case for the world wide web but the project wasn't designed to be limited to that usage. Berners-Lee knew that he couldn't predict how the web would be used in the future. He therefore designed it to be extensible.

The first version of the HyperText Markup Language had just a handful of elements. But the HTML language is open to new elements being added. Over time, we got more form fields, more structural elements like section and article and even more media like audio, video and responsive images. None of these additions introduced breaking changes. That's because of the error-handling model of HTML.

When a web browser encounters an HTML element it doesn't understand, it renders whatever is in between the opening and closing tags. It displays the content while ignoring the tags it doesn't understand. What's interesting here is what the browser doesn't do. The browser doesn't throw an error. The browser doesn't stop parsing the HTML as soon as it encounters an element that it doesn't understand.

This kind of lax error handling is an example of a design principle called The Robustness Principle or Postel's Law: "Be conservative in what you send. Be liberal in what you accept."

Browsers are very liberal in what they accept when it comes to HTML. On the one hand, this can be quite frustrating if you're a developer trying to isolate a mistake in your HTML. On the other hand, this looseness has enabled HTML to grow over time without breaking in older browsers.

In the first decade of the web's life, HTML saw an explosive growth. New elements and attributes were added to the language. Some of those additions were adding new semantic granularity but some had absolutely nothing to do with semantics. Elements and attributes for specifying fonts sizes, colours and borders were introduced. HTML, which was intended for defining document structure, was looking in danger of being swamped with presentational instructions. The solution was to split structure and presentation into two different languages.

01. The presentation layer

Håkon Wium Lie and Bert Bos joined forces to work on Cascading Style Sheets. Using CSS, developers could add presentational information without having it intermingled with HTML.

With the arrival of CSS, HTML could return to doing what it does best: describing the structure of a document's content. The new separation of concerns had other benefits. A single CSS file could be responsible for one HTML document or it could be responsible for multiple HTML documents: 10, 20, 100 HTML pages could all reference the same style sheet. Tweaking the visual style of those 100 different pages no longer involved changing each and every one. Changing the single CSS file was enough.

But CSS still needs some way of understanding which parts of the HTML it should be styling. It has a kind of 'mental model' of how parts of HTML can be targeted for styling. This model is represented in the form of selectors. Using CSS's selector vocabulary, developers can target elements with a particular tag name, class name or ID. You can think of this way of modelling a document as being like a document selector model.

Crucially, CSS adopted the same error-handing model as HTML. If you use a selector that the web browser doesn't understand, it will ignore the enclosed declarations and skip ahead to the next selector. The web browser won't throw an error. It won't stop parsing the CSS file at that point and refuse to go any further.

Likewise, if you use a property or value that the browser doesn't understand, it will skip over it and move on to the next declaration. This has enabled the vocabulary of CSS to grow over time, without waiting for universal browser support. You can use new selectors, properties and values even if they're not available in every browser. The non-supporting browsers ignore what they don't yet understand. They are liberal in what they accept.

02. The behaviour layer

History of the web browser

(Image credit: CSS Zen Garden)

Describing the structure and the presentation of a document is empowering but it has its limits. Using HTML and CSS, you can craft beautiful, accessible, semantic web pages but they're static. Interaction is bounded by HTML's vocabulary. Links and form fields are interactive by default but if you want to extend the interactivity of HTML you need a scripting language.

In the early days of the web, a young engineer named Brendan Eich created a scripting language for web browsers. The marketing department at his company, Netscape, named it JavaScript. It's a terrible name. It sounds like JavaScript has something to do with the Java programming language. It doesn't. But, back then, Java was poised to take over the world. Naming this new language JavaScript made it sound hip.

HTML and CSS are declarative languages. Rather than giving step-by-step instructions, you describe the outcome you want using the vocabulary of the language (elements and attributes in HTML, selectors, properties and values in CSS). On the plus side, these declarative languages have the loose error handling that makes them relatively easy to get started with. But, on the downside, you're always going to be limited by the language's vocabulary.

A scripting language is more powerful. It enables you to specify precisely what you want to happen. But that power and precision comes at a price. A scripting language can't afford to have the same lax error handling as a declarative language. If you write some JavaScript that a browser doesn't understand, the browser will throw an error. It will stop parsing the script at that point and refuse to parse any further. Postel's Law doesn't hold true here. Browsers are not at all liberal in what they accept when it comes to JavaScript.

JavaScript's stricter error handling means that developers need to exercise more care when writing it. If there's a particular browser API that's available in JavaScript, you need to think about what will happen in a browser that hasn't yet shipped that API. That browser won't simply ignore any parts of your code that use the new feature. Instead, you'll need to test for the existence of the API. This kind of 'feature detection' isn't needed in the declarative languages of HTML and CSS but it's a necessary part of writing responsible JavaScript.

The document object model

CSS has one way of 'seeing' an HTML page – a kind of document selector model. JavaScript has a different way of exposing the structure of an HTML document. The JavaScript language uses the programming concept of objects to expose APIs. Browsers, for example, provide a window object to JavaScript that describes the current browser window. The HTML page inside that window is exposed through another object called the document object. Unlike CSS, with its vocabulary of selectors, JavaScript 'sees' an HTML page through this Document Object Model or DOM.

During the bad old days of the browser wars in the 1990s, when JavaScript first arrived on the scene, browsers shipped with conflicting DOM vocabularies. Netscape Navigator had one way of describing a document – document.layers – while Microsoft's Internet Explorer used document.all instead. Developers had to fork their code, using feature detection to figure out which code to send to which browser. It was intolerable.

Eventually browsers converged on a standardised vocabulary for DOM scripting. Methods like document.getElementsByTagName and document.getElementById were the JavaScript equivalents of element selectors and ID selectors in CSS.

Using JavaScript and the DOM, developers were able to add extra interactivity to their otherwise static pages. To begin with, the interactions were quite basic. Image rollovers were popular: when the user moved their cursor over an image, JavaScript could swap out the image. Form validation was another common use of JavaScript and the DOM. Scripts can 'listen' for events – like when a user submits a form – and execute code to check that the inputs conform to certain criteria.

Interestingly, both of those use cases can now be accomplished without JavaScript. If you want to change how an element looks when the user mouses it, you can use :hover in CSS. If you want form fields to only allow certain kinds of values, you can use HTML5 input types like email, URL and number. These popular use cases have made their way down from the powerful – but fragile –scripting layer into the more forgiving – but less powerful – declarative layers.

JQuery, AJAX and more

History of the web browser

(Image credit: JQuery)

Most DOM scripting patterns – like image rollovers and form validation – involve finding a particular part of a document and then executing code when a particular event is fired. You could summarise these patterns as: 'Find stuff and do stuff to it'.

To 'find stuff,' you needed to use DOM methods. But, in the mid-2000s, John Resig created a JavaScript library to make it easier for developers to do DOM scripting. He called it jQuery.

There were many other JavaScript libraries around at the time – script.aculo.us, MooTools and more. What distinguished jQuery was that it enabled you to 'find stuff' using the selector syntax of CSS. If you already knew CSS, you no longer had to learn a separate vocabulary for interacting with HTML. This was hugely empowering for designers and developers who understood HTML and CSS but were intimidated by the steeper learning curve of JavaScript. jQuery was so popular that it influenced the design of the DOM's vocabulary. You can now use the document.querySelector method to 'find stuff' in an HTML document using CSS selectors.

With the rise of jQuery, the web saw an increase of interactive widgets. Carousels, modal windows and fly-out menus became commonplace. At the same time, the web was being swept by Ajax fever. Ajax is a JavaScript technique that allows the document currently loaded in the browser window to send and receive data from a web server without refreshing the whole page. Now the web was a viable medium for applications. Gmail and Google Maps led the way, demonstrating that – thanks to JavaScript – just about anything is possible on the web.

JavaScript eats the web

As web applications grew more and more complex, JavaScript libraries expanded in scope. First Angular and then React encoded a new approach. Rather than treating JavaScript as a separate layer of interaction that sits on top of an existing HTML document, the modern approach flips that model on its head. JavaScript becomes the centrepiece. The DOM is no longer generated from existing HTML – the DOM is generated by JavaScript instead. JavaScript injects markup into an otherwise empty page. You can even use JavaScript to inject CSS straight into the DOM at runtime. Where once there was a separation of concerns – structure, presentation and behaviour – now you can do everything in one language.

This power comes at a price. If the contents of a web page are being injected with JavaScript, the script has to be downloaded, parsed and executed before the user sees anything. Browsers are optimised to stream HTML, even when it's incomplete. That's not an option with JavaScript. Performance suffers and, with it, the user's experience.

The stricter error handling of JavaScript also makes it hazardous. If there's just one error in your code or if there isn't enough feature detection to deal with older browsers, users will be left staring at an empty screen.

The principle of least power

When Tim Berners-Lee was working on his world wide web project, he applied a number of design principles: simplicity, tolerance (in the form of Postel's Law), modular design and the principle of least power: "Choose the least powerful language suitable for a given purpose". See it here.

On the face of it this seems like unusual advice but remember that powerful languages come with a price: fragility. Less powerful languages are more forgiving and more widespread.

We can apply the principle of least power when we are creating products
and services on the web. As web accessibility expert Derek Featherstone puts it: "In the web front-end stack – HTML, CSS, JavaScript and ARIA – if you can solve a problem with a simpler solution lower in the stack, you should. It's less fragile, more foolproof. It just works." 

JavaScript, Ajax and the DOM are powerful tools. Use them responsibly.

Read more: