Keeping a good separation of concerns means writing code that only handles as much as it needs to. It’s a concept that should affect every piece of code you write, from class definitions to database tables. Only store the data which is relevant. Only encapsulate the logic which is covered by the responsibility of your class. My colleague wrote about this recently when discussing Inheritance and Composition.
Custom Elements are a major part of the Web Components spec which is making its way natively into browsers today. They allow developers to create custom HTML tags, with custom behaviour, isolated inside a “shadow DOM” – its own scope, invisible to any consumer. It involves the creation of an HTML element, and a registration of custom behaviour using document.registerElement. Once a component has been created, it allows you to use it with descriptive, semantic markup like this:
When this tag is instantiated, it creates a shadow DOM, and fills it with whatever content has been put in the gallery template. For example, the template markup may look like this:
Custom Elements are a new feature in browsers, which recently made their way into Chrome stable. The Polymer project provides a great polyfill for them for other browsers.
The React library takes care of converting them to HTML, rendering them on the page, and updating them on changes. It actually does this better than doing it manually would, as it diffs changed HTML against HTML which is already rendered on the page, and only changes as much as is necessary, rather than rerending the whole element. For example, it might just add or remove a child element, or alter a style.
Aren’t we already close enough?
There are hundreds of open source libraries out there which instantiate and control DOM elements for you. For example there are a myriad of jQuery libraries which allow the creation of custom elements like lightboxes, slideshows and validating forms.
Although obviously React demands a dependency, the HTML style syntax means third party components end up being used a similar way.
What does this mean for open source?
The goal is to have a standardised architecture for reusable, customisable DOM elements. I want to be able to import a component and put it in place as easily as I install a gem, or require an NPM module.
I don’t think the encapsulation of style is important here. In fact, I often feel UI libraries being particularly opinionated about looks slows me down as a developer. Of course sometimes this makes sense. For example, material-ui includes a huge amount of element styling, but creating elements which look and feel a certain way is the reason it was created.
Libraries which offer elements such as mobile navigation menus or autocompleting text fields ought not tell me how they should look. Their ideas generally conflict with my own ideas, and are often troublesome to override. In these cases I’m far more concerned with having the functionality put in place for me, so I can style it to the look and feel of my site as I choose.
We need to make a good separation of concerns in HTML and CSS the expectation in open source code, and our own code as well. Too many libraries are breaking the Single Responsibility Principle by pulling more than they can carry. The best UI Component libraries are going to be the ones which concern themselves with either functionality or style. Never both.