DOM was good while it lasted, long live the Shadow DOM!

Prateek Papriwal
7 min readSep 16, 2017

--

The Document Object Model (DOM), as defined by W3C,

is a platform- and language-neutral interface that will allow programs and scripts to dynamically access and update the content, structure and style of documents. The document can be further processed and the results of that processing can be incorporated back into the presented page.

As clearly stated in the above definition, DOM gives programmers/developers a cross platform and language-neutral interface to interact with data within the documents. DOM is essentially a logical structure/model for document(HTML/XML) that gives a way to create and build documents, navigate their structure, and add, modify, or delete elements and content.

Before the invent of DOM, the documents were passive and as such documents could not be manipulated. Javascript was also invented by this time that could create pages but with limited client side interactivity. Soon after this, browsers started adding support for Dynamic HTML, allowing changes to a loaded HTML document. But the DHTML extensions were developed independently by the browser and hence remained incompatible. DOM was inspired by the introduction of Dynamic HTML and a need for consistent browser behaviour with webpages and their elements.

But that was late 1990’s and early 2000s when web pages were simple and involved very less dynamic interactivity. After two decades of eventful Web Era, things have changed a lot with webpages becoming more complex. Today, web pages are no more piece of passive information or what we call as static websites, they have become more and more dynamic and are stuffed up with many elements. To visualize this stuffed-up complex web page, think of C or java when you write your entire code in main function and the result is an awful mess of incomprehensible code. Similarly in HTML, there is no way to encapsulate and break your HTML code into pieces(custom elements/widgets).

And recently in 2014, W3C announced the Web Components Standard. One of the main parts of this

is the introduction of Shadow DOM, which claims to decrease the complexity of DOM, and give developers power to design reusable, encapsulated components.

But wait, Is there really no other way to do encapsulation?

Iframes!!! Don’t they encapsulate the markup and styles? They do. Popular examples of iframe include Google’s embedded maps and Youtube videos.

However, iframes are typically designed to embed full document into another document. Also as stated by W3C, <iframe> element represent a nested browsing context. This means that iframe DOM elements are completely in some other context, and to access them you need to cross the difficult-to-cross iframe wall. And consider the situation when we create a page with 5 iframes each representing a component. This would definitely require a lot of setup overhead, excessive separation and messy markup that comes along with iframe.

And what about Javascript and other powerful UI libraries/frameworks? Aren’t they powerful enough to manage dynamic UI?

As was discussed earlier as well, DOM was introduced to create dynamic websites. But DOM was never optimized enough. Although through the last decade or so, Javascript and other libraries/frameworks have evolved a lot. But let’s wait here and think about modern era social network websites like Facebook, Twitter. On such a humongous scale, there are thousands of nodes/elements. And managing dynamic interactivity is a problem. Think of comment component in Facebook, you really need some very optimized scripts/framework to manage it. Yeah, you can always write some super hacks to do this stuff, but in the end, it’s not easy to maintain such huge pages and dynamic UI. Though virtual DOM solves this problem in a way. Virtual DOM is just a carbon-copy of DOM, that find the difference and modify only the updated part. Virtual DOM solutions are built on the top of standard DOM. They make use of efficient diffing algorithms, efficient way of reading/updating elements of DOM. ReactJS by facebook is one of such solutions that promotes the idea of virtual DOM. Although it tries to advocate the component-philosophy but still it is not a standard. There is still a need for something that is native.

How shady is the DOM without Shadow DOM?

We saw in the above discussion that the iframes(a native solution) is not at all an effective way of DOM encapsulation. And also, we looked through the virtual DOM solutions for implementing the component-philosophy, but they are not natively supported.

Now let’s take a look at an interesting example of the floating widget of http://readthedocs.org website. Readthedocs is a free documentation hosting website. The widget can be seen in action at one of the hosted documents at http://pymoku.readthedocs.org/en/latest/

And as it can be seen, the widget is in the bottom right corner of the page. Below is the full HTML DOM in which the widget <div> is highlighted.

Readthedocs has been used by many projects to host their documentation. And it has some widget injection code that injects this widget into the document and adds perfect styles. This is pure DOM thing and it is just working well.

But now a guy thinks to use his own document template and then host the documentation on Readthedocs. And his template contains this piece of generic style somewhere in the stylesheet

And due this small piece of style code that was present in the template, the widget got disturbed and looked messy. This was one of the examples. There could be many such style or even javascript related conflicts. One of the javascript conflicts that quickly comes to mind is that open-on-click functionality getting disturbed by some random other piece of javascript.

Shadow DOM to the rescue!

Encapsulation is what we need as we saw from the above analysis. This can help us to solve many such problems of “leaking” CSS, Javascript of main DOM that go on to disturb the widget DOM. Shadow DOM provides encapsulation for the Javascript, CSS and also a way for templating in Web Component.

Let’s see how we can use Shadow DOM for creating the Readthedocs widget. We can wrap the widget as below -:

In the script part as written below, we create a shadow root attached to a host(<div id=”readthedocs-widget”>) in the main DOM and then copy the contents of the template into the shadow DOM.

With the above implementation, any generic styles and scripts on the main DOM cannot affect the readthedocs “shadowy” widget.

As you can see the newly created DOM, the widget DOM is inside Shadow DOM, as result of which it cannot be styled or queried.

Now if we try to access the contents of the widget, it would return null. Jam-packed security! Isn’t it.

Similarly, the CSS that earlier disturbed the widget, has now no effect on it. The dl selector in the main DOM can’t reach the shadow DOM.

Conclusion

There is no doubt that DOM and Javascript frameworks have evolved a lot and they have promoted component-philosophy (which is good). But native support for “encapsulation” (through Shadow DOM) is a welcomed feature. Conflicts, development overheads, messy markup will be reduced in a big way. With most of the browsers already supporting Web Components Standards, there has been lot of interesting progress taking place (like Google Polymer etc.) to make it easier to develop components which are encapsulated, compatible-across-browsers.

Hence, DOM was good while it lasted. It led the progress of two eventful decades of Web era. But as we are moving forward, we are seeing a shift with almost all websites having dynamic interactivity, and stuffed-up with loads of data nodes. Going further in the future, we could easily imagine web of documents getting replaced by web of data. To be ready to manage this swift changes, let’s embrace the Web Components Standard and the magical Shadow DOM.

--

--