Engineering teams are challenged to make decisions that work for them today and will continue to do so years down the road as an application scales. Teams need solutions that are easy to train, powerful to use, and help to directly address core challenges of an application. Choosing an approach for styling our frontends is one such solution and one that can often result in dreaded technical debt without forethought.
Styling is currently a bit complicated. There are a lot of different types of solutions and many require pre-compilation or bundling. Some think simplicity is the answer here but often your users are paying for these simpler styles with larger downloads and increased bandwidth usage. It’s hard to make a good decision without a broad understanding of the problem space.
To go a step further, as teams reach a decision on what tool they like, the outcome is often to scale the chosen technology across all application properties. Does a team love styled-components
? Now every application uses it because that should be easier for teams to manage. But is it actually easier to stick to a single styling system?
Looking at the evolution of modern web development, we’ve actually seen many teams switch from using a single language everywhere to writing smaller services and incorporating other languages. Looking at Functions-as-a-Service (FaaS) and other cloud native solutions we’re seeing teams that can easily write code in different languages within the same application context. Using the right tool for the job is important and we have a larger selection of styling tools now than ever before.
At Rangle we’ve been a major contributor to the evolution of Design Systems that further the ability for businesses to scale design across large teams. These systems are built so that each component can encompass a specific User Experience fully while relying on the structure of common tokens to enable the system to make larger changes. The need for each component to have very specific style code written is important to be able to solve the UX and UI problems present.
When we look to use a Design System in a web app, we’re looking to largely rely on these components to drive many aspects of the user experience within some scaffolding to keep it all working together. Every page created should receive the same scaffolding and we have an increased need for consistency in our web app over making very specific changes.
You can start to see how these two problems are different. Pages need consistency. Design Systems need specificity. So why use the same styling methods in both spaces?
Styling Systems for Design Systems
We’ve worked with a lot of different styling systems over the years. While some of the past libraries are still close to our heart, we’re very happy to not be building style systems ourselves from scratch anymore. A lot of work has been done for us and with much to do to get a Design System started, we’re happy to be able to have a running start.
Our current favourite system is the styled-component approach (either using styled-component directly or using @emotion/styled). Being able to keep some of the styled code in JS has enabled us to more easily break-down and define the parts of components. We find this essential for keeping things simple and surfacing common elements that might be able to be reused.
Design Systems we find best work as separate repos or within a mono-repo environment, like Nx. Keeping the system co-located directly with code raises a challenge to anyone trying to surface these components for common use. So its best to keep these libraries separate from application code.
Best Styling Systems for Pages
If you think about what works great for pages, you really want to focus on speed and fast configuration above all else. Pages are temporary and change frequently with the business. Teams need a system that’s easily adapted and be changed with he times.
For this task I can think of no tool better than TailwindCSS. By leveraging utility classes and a common theme configuration the developer is easily able to style and scale pages. You ensure consistency without introducing custom utility files that easily clutter your code base. When developers start to reach for a more complex solution requiring custom CSS, it’s a good time to put that solution into the DS instead of the application code.
While the syntax of TailwindCSS is challenging to pick up, the ability for you to leverage tooling is huge. Teams can leverage VSCode to help auto-complete solutions and preview the resulting style. React can also often pick up on these changes as style changes and hot-reload to enable even faster design iterations than CSS-in-JS solutions.
TailwindCSS is terse to the point that a fully styled page section only takes a few lines of code. This makes it optimal for AI extension tools like GitHub CoPilot. We’ve seen this tool give us a simple working solution in only a few seconds. When you have a solution that you’re immediately able to iterate on, it’s incredible how fast you’re able to make something great.
If you run an engineering team, this is your problem
This style challenge gets trickier to solve as time goes on. If you’re sharing common styling configuration across applications you’ve seen it get harder to make changes and stay updated. The pressure is on, but by bringing two great tools to the table that cover the page and component domain separately, you’ll be able to diffuse this problem for your team. Ultimately scaling out your ability to work fast at a high quality across a wide range of pages.