Cover image for HTML postmortem: frameset and its legacy

HTML postmortem: frameset and its legacy

macargnelutti profile image Matteo Cargnelutti ・4 min read

Ever wondered where the target="_blank" attribute came from, what it means and why it behaves the way it does? A little bit of HTML history might help with that πŸ€“πŸ“–.

Part of the HTML 4 standard, <frame> and <frameset> were all the rage in the late 90s and early 00s. At a time where CSS wasn't really a thing and WYSIWYG Web editors were very popular, <frameset> offered a simple way of building somewhat complex layouts by allowing to split the browser's window into a grid of separate HTML documents. In a way, they were the 1990's solution to problems the web development community still faces today, such as code modularity and bandwidth usage reduction, with a lot of limitations and side effects we'll go over in this article.

Let's explore together how this now-deprecated web dinosaur that is <frameset> worked, what were some of its limitation, and what its legacy to the modern web is.

How did it work?

The <frameset> tag took the place of the <body> tag: it was used to indicate to the browser that it was meant to load multiple HTML documents, represented as <frame> elements, and how they were supposed to be displayed on the screen, using cols and / or rows.

<!-- This is late 90s HTML, tags were SCREAMED! -->
<FRAMESET cols="25%, 75%">
    <FRAME name="sidebar" src="menu.html">
    <FRAME name="main" src="home.html">

Simple frameset demo with two columns

It was even possible to nest <frameset> tags to use the cols and rows attributes in combination, allowing to build more complex grids.

A special HTML Doctype was available and was "sometimes" needed to allow for the rendering of <frameset>-related tags:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"

Having multiple separate documents in a single browser window led to some complications, the first of them being to decide where a given link should open. Hence was created the target attribute for the <a> tag, which stands for "frame target": If provided the name of a given <frame>, target allowed click on <a> to open in a cell of the <frameset>. A few special target keywords were defined, such as the still overused _blank, allowing to open the link in a new window.

<A href="contact.html" target="main" title="[...]">Contact</A>

Screenshot showing that opening another page in a frameset does not change the url

Finally, since this patchwork of HTML documents was meant to be a single page, JavaScript had to be able to talk and share information between frames, and even sometimes across domains ... which we'll talk about a bit more when discussing the security issues of framesets.

What was it "good" for?

The main advantage of <frameset>-based websites was that they allowed for code reuse and modularity: splitting a webpage in separate documents, organized by role, made possible to focus on the development of a part without affecting the other, of containing code and its effects in a <frame>.

This very feature could also help, in a way, with performance: by only reloading parts of the page when navigating, it made for smaller payloads.

But more importantly, they were an easy-to-use layout tool, that styling alone could not help achieve at the time: there was no "more semantically" correct way of doing things available at the time.

Risks and limitations

Search engine optimization was really hard to achieve using <frameset>. Using target on a link to open a page on a given <frame> meant that the window's main url was not changing: single pages did not have a publically accessible url.
As a result, search engines were often indexing single frames separately, which led users to land on a "broken" website, and an information without context.

As they were multiple screens in one, <frameset> were also poorly supported by screen readers, making it challenging to build accessible websites.

On the performance side of things, while they offered some advantages after the initial load, these websites meant that many more HTTP requests had to be done when being accessed for the first time.

Finally, they were and still are a security headache: the ability for frames to interact with their parents and siblings via JavaScript, even across domains, gave birth to many malicious attacks pattern, still in effect today to some degree.

What remains of it today?

Besides everything that it taught us, and the millions of older websites out there that are still using <frame> and that would have been much different otherwise, I feel like one of <frameset>'s main legacy to modern web development is the target attribute for the <a> tag, and the security and performance challenges it poses.

When using target="_blank", we must add rel="noopener noreferrer" to let the browser know that it should not allow the new window to access the window that called it. While modern browsers implement some default protections to prevent leaks, without rel="noopener noreferrer", it is still possible to access some of the caller's information via window.opener, a behavior inherited (for the most part) from the <frameset> era.

But access to window.opener, the caller's window object, is also the main reason why target="_blank" can be a threat to performance: sharing objects accross pages means sharing memory, which gives the browser less opportunities to separate processes and threads. Jake Archibald wrote a terrific blog post about "The performance benefits of rel=noopener" back in 2016.

Its dizzying, sometimes, to look back at the origin of all things web and see how ideas from the past - that we sometimes completely forgot about - still have an important impact on our everyday lives, and how things evolved for the better.

Posted on by:

macargnelutti profile

Matteo Cargnelutti


CTO & Software Developer at Grafton Studio, Boston MA. Interested in everything Web standards, Python, Javascript. He/Him, πŸ‡ΊπŸ‡ΈπŸ‡«πŸ‡·. Opinions are my own.


Editor guide