This post is Part 2 of a two-part series.
Part 1 is here. In it we’ve explored how interactive elements are treated differently in code vs traditional visual design tools and that this problem gets worse the more complex the element gets.
In this second part I’ll go deeper to elaborate on some more ways communicating about components and elements is difficult, why classification is non-trivial, but chiefly about why that matters so much. Why the consequences of this difference are so important. To be on the positive side - I’ll compare two ways I see our industry is trying to overcome this problem, and which I prefer more. I’ll also provide links to valuable resources to help designers be more mindful of the caveats.
Let’s go!
How do we define an element, actually?
The taxonomy of the web elements is not completely solved for. There are many commonplace components that were invented much later than the beginning of the web, so they didn’t get to have a very well defined place in the w3c list of HTML element tags.
Unlike input type elements like a text input, checkbox etc, think about more complicated things like a time picker, date picker components, or even a wizard or a carousel. Definitely components, complex ones, but are they elements? If yes - why? If not - on which basis? I mean, it’s easy to draw the line arbitrarily anywhere we like, but the whole issue here is that we don’t want this line to be arbitrary, as much as it is possible.
In order to try and draw a more accurate line in this - I might need to summon Brad Frost to remind us of Atomic design:
If atoms are the basic building blocks of matter, then the atoms of our interfaces serve as the foundational building blocks that comprise all our user interfaces. These atoms include basic HTML elements like form labels, inputs, buttons, and others that can’t be broken down any further without ceasing to be functional.
Notice the rule - “can’t be broken down any further without ceasing to be functional” that’s Brad’s rule for being elemental enough. The issue that might be illusive here is what constitutes a function here?
If we take a date picker - I can easily break it down to a bunch of buttons, a carousel to switch between months, so that should disqualify it from being an element - but the function of a date picker is registering a date, or a range of dates in the system, and that is breaking down if you start picking the date picker component apart. So if we allow treating the elements not as nouns but as verbs, an element becomes - the minimum things needed to execute that verb, that function that defines it.
On these grounds a date picker is in fact an element, and the mind bending realization is that an element can contain other elements in it, if they are simpler!
Moreover, when you examine the HTML tags themselves - you’ll see that it has always been like this. What is a <ul> tag? Unordered list - an element. And what does it always have inside of it? <li> - List items. Other elements. So elements inside elements, right there from the beginning of the web itself.
The ‘Delta debt’
At this point you might think to yourself - so what’s the problem - isn’t that the developers’ job? Well, it is, of course, but this is exactly the moment components start to diverge between design and development. And that’s a big problem en mass because if you have some 30+ elemental components and then some 60+ complex components in your design system, and most of them are not really in sync with code at the level of what each layer represents - when you start implementing wide changes, using tokens and maybe decisions about accessibility (what is clicked and triggering the interaction, which hit area, what is focusable and how etc) a nasty debt starts to grow. I call it the ‘Delta debt’. You know what I’m talking about if you are a product designer with some years under your belt.
That small ‘letting go’ when you do your visual QA, the staging/production versions doesn’t really map 1:1 with the design, and when you inquire it with the devs - you either get a ‘that’s how browsers render things, it’s not up to me, and making a custom patch is dangerous and will take a bite out of our speed, didn’t you want that other feature?’ or maybe something more puzzling like ‘what do you mean, this is exactly according to your specs, to the pixel, I followed Figma perfectly’.
So you make a tactical move and give up, promising to yourself that you’ll let this one slide, it’s probably only you and your sharp eye for design details that this thing is bothering, we have more important things to do now and you’ll get this later when there is more time. Sadly, there will never be more time. Just more miss-aligned components.
And so that ‘Delta debt’ is only growing with time, and like death by a thousand cuts - you grow your own displeasure with how the actual product looks and behaves and prefer to get back to your beloved, pristine, perfect design files, where your eyes are safe from this irritation. Sometimes the inertia is so strong that there’s nothing you can say that will convince stakeholders that this debt has to be repaid. The only thing you promise yourself is that either on rebrand, or on the next project - you’ll be more assertive from the get go to make sure the design and the product are exactly aligned. Only for the same circle to be repeated again.
Although frequent, this problem perhaps can be avoided. And there are 2 paths that I see can help bridge this gap. One - easy to explain but hard to do in practice, the other - harder to explain but might solve the issue as a bi-product.
Potential paths to solution
1st path
Improve communication to the level that there’s no silo problem, the designer and developer pass a ‘hot potato’ of a task very frequently, until both of them have a very similar mental model of what the design should look like, behave like, built like and perhaps animate like. This is probably the most frequent piece of advice you see people give in podcast interviews about their success (of course), well meaning and inspiring talks from a stage and heaps of Youtube videos. Alas - what is easy to say to do, is fiendishly hard to actually do. It takes effort and friction to maintain cohesive communication, the fruits of which you don’t always feel as vividly, and in an ever-optimized and measured work environment - it’s the first thing to suffer. Especially as startups grow and expand from seated in a single room to spanning continents and time zones.
2nd path
Construct tools and processes for designers and developers that will make it much harder to not be on the same page. Suppose a design tool would be made out of real elements, with an already existing, verified structure, that is backed by code beneath it all. You mainly see web builders do it today, like Webflow and Framer. When you use an element like a checkbox in these apps, it’s a real, working checkbox. Sadly, there’s no developer to hand it all over to, because builders cater mostly to teams where a designer can handle the whole project end-to-end, with no need for a dev in the loop. Now, imagine something like this for overall product design, web apps, native apps etc.. massive products that cannot be resolved only by a talented designer, but actually have a ton of business logic, state management and data backend stuff to handle. Products that require many front and back end developers. Most SaaS startups products are like that today.
So imagine these teams all use a design + code process and toolset that from the get-go nudges them to use pre-existing elements and style them as they wish, then pushing the result to front-end developers who don’t need to rebuild it all from scratch, but rather wire it all up with non trivial extra logic (in their own beloved IDE) and use it together with the backend engineers.
When I think about product design at it’s best - it’s always better to prevent a problem than trying to help dealing with the problem’s consequences. It would come as no surprise that I much prefer the second path.
Summary
It is a hard problem to solve. And if you zoom out and look at the product design tools and methods industry from above, you’ll see that as time goes by there is an ever growing thirst by designers to close that gap already. That’s why you see a plethora of plugins for Figma and Sketch that help to ‘translate’ (guess) your visually optimized designs to some or other useable form of code. That’s why design tools adopt more and more features and mechanics that resemble the capabilities of code (like variables that can reference other variables, component API through the use of properties and variant groups, auto layout and absolute positioning in it, truncation in text, conditional logic etc).
Some people believe it’s still all just about communication skills, and the tools themselves don’t matter, some believe that artificial intelligence embedded inside the design tools will help sprinkle some fairy dust on this problem and help designers traverse that chasm, and some, like myself - believe it’s just a matter of building better tools.
In the meantime, the more we know about the different quirks of each element in actual, live products, the easier it becomes to bridge the gap.
Here’s a list of useful places you can learn and dive about the details of the different interactive elements, and improve your handoff:
Radix UI is a great headless UI repository to both use and explore
This is a fantastically deep disambiguation of what people like to call a ‘dropdown’.
Of course the most complete and reliable list of all HTML elements, the MDN website
Small but useful repository of real components - Headless UI
Brad frost’s ‘Atomic design’ and overall blog
And this is an inspiring and informative article on how to structure communication so well that handoff becomes almost risk-free (good luck with actually implementing that, though).