Should you style HTML Elements directly?
Over the last year and a half, I have been developing a Design System for RoleModel Software. This has required a high level of collaboration between me (a full-stack developer who primarily enjoys front-end work) and our design team (specifically our Design Director).
We call it Optics, a RoleModel Design System
Early on in our collaboration, a question came up as to how we style our inputs.
Should we design all of the inputs in our system to have styles applied directly to the HTML Elements? Wouldn't that be easier than requiring
.form-control
to render the styles?
This question applies to more than just form controls as well such as styling buttons directly or always using a class like .btn
.
.form-control {
// Shared styles go here
}
// OR
input[type="text"],
input[type="password"],
input[type="search"]
input[type="date"],
input[type="datetime-local"],
input[type="email"],
input[type="month"],
input[type="number"],
input[type="tel"],
input[type="time"],
input[type="url"],
input[type="week"]
textarea {
// Shared styles go here
}
<input type='text' class='form-control'>
<input type='email' class='form-control'>
<!-- OR -->
<input type='text'>
<input type='email'>
So should you? No, use classes.
Let me explain why by addressing some potential concerns.
Concern #1: Requiring a class creates a worse Developer Experience
Needing to remember to use a class every time adds complexity to the Developer Experience and friction to implementation right?
While this can be true of some elements like buttons, inputs, or other semantic HTML elements, requiring a class means the HTML has to be written with more intention and care. It also provides semantic meaning and in some cases intention revealing names to elements or concepts that might not have a dedicated semantic HTML element.
Concern #2: Requiring a class leads to unexpected default behavior
The fundamental purpose of a Design System is to provide styling for a cohesive user experience. Shouldn't elements behave correctly without using classes?
Most design systems provide component libraries to solve this. They ensure you always use the styled and "blessed" default approach by providing a simpler interface. Even they don't override default styles though. If you ever needed to add a new component based on an input element but with a different use case or something along those lines, they still allow for it.
Optics doesn't have a component library (yet), but it does have component blueprints (HTML snippets) with the right semantic elements and classes applied that you can copy and adjust as needed.
Concern #3: This feels like shaping the code toward an edge case
Opening the door for straying from our design patterns feels like encouraging edge cases. Shouldn't we avoid writing code to allow for this?
Allowing for intentional variation and customization is not an edge case, but rather a feature of a cross-product Design System. It doesn't lock you into one way of thinking or using the system.
Default styling forces you to use an element in one way and doesn't allow for intentional, well-thought-out divergence from that one case. It assumes that the Design System has thought of every need or use case that could come up.
Any time you need to create a new variation, you would need to un-style and then restyle the element which leads to more confusing and complicated CSS.
Based on my experience working across dozens of applications, you simply cannot account for every need or situation.
Every app has unique challenges and uses elements in different ways. Without flexibility, every app built with the same Design System ends up getting locked into a similar look and feel and loses any uniqueness or character. A Design System should provide consistency and standardization, but should still allow for character to show through.
Subscribe to my newsletter
Read articles from Jeremy Walton directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jeremy Walton
Jeremy Walton
I am a Senior Developer at RoleModel Software. I started exploring programming in middle school, following some books with guidance from family friends who did web development for a living. In High School, I joined a robotics team and was taught by another developer how to take a project from nothing to competing against other robotics teams. Near the end of High School, I learned about RoleModel software and the Software Craftsmanship Academy they ran. It felt like the perfect opportunity for me to pursue a career in software. After graduating the Academy, I joined RoleModel full time and have been delivering quality software to clients, leading teams of developers, and mentoring junior developers. I am continuing to learn new things and push my abilities while helping others do the same.