About
This project hopes to make it easier for federal product teams to work with, adjust, and extend the USWDS.
Motivation
The USWDS has played an incredible role unifying the federal government’s digital experience since 2015, simplifying both design and development to create consistent, maintainable products. However, frontend development evolves rapidly, and as I worked with USWDS, its reliance on older tools and approaches like BEM style naming, SCSS, Gulp, and manually installed fonts and icons began to feel like they were slowing me down.
Given the USWDS’s existing utility classes, I saw an opportunity to modernize it by using Tailwind CSS, which offers similar functionality out of the box. This project is an experiment combining Tailwind’s utility-first approach with the USWDS’s design tokens.
Additionally, (while originally unintended) updating the JavaScript workflow with Alpine.js felt natural, allowing for declarative, streamlined event handling without needing to target custom classes.
My hope is that this project makes working with the USWDS a simpler, easier, and more efficient tool for developers, and therefore users.
Tailwind CSS
Efficiency and Performance
Tailwind optimizes our projects by generating only the necessary CSS, significantly reducing the CSS footprint compared to SCSS functions and nesting. This leads to faster load times and improved performance for end users by minimizing the resources they need to download.
By using Tailwind alone to build the components of the USWDS, we’re able to ship only 123 KB. If we use fewer components, we ship even less!
Enhanced Developer Experience
I’ve got to say it: the USWDS has some really complicated SCSS. This makes it particularly difficult to work with and extend.
The USWDS relies heavily on BEM and nested styles which creates issues with CSS specificity. For example, a utility class like “.text-white
” is always going to have a lower specificity than “.usa-footer__secondary-link a
” which means you won’t be able to alter any predefined styles using a utility class. Building with only utilities allows us to avoid this problem altogether.
Advanced DevTools Integration
We leverage Tailwind’s powerful DevTools, including class sorting, linting, and autocomplete, which streamline development even with our custom configuration.
Utility-First Flexibility
Tailwind’s extensive utility classes make it easy to implement unique design requirements, such as adjusting spacing or overriding font colors, with minimal effort.
While there are plenty of good utilities in the USWDS, I’m often in need of ones that don’t exist: .space-y-4
, .column-count-4
, .gap-2
, etc. While these could be added, accounting for all these use cases would make the USWDS’s generated CSS even bigger!
Wide Adoption and Excellent Documentation
As the most widely used styling system globally, Tailwind benefits from a large community and comprehensive documentation. This reduces the learning curve for new developers and minimizes the need for internal documentation.
Iconify
Seamless Integration with Tailwind
Iconify complements Tailwind by allowing effortless addition of new icons, similar to changing font colors. Its robust library supports extensive icon options without increasing the project’s complexity.
Optimized Rendering
Iconify generates SVGs directly in our CSS, ensuring immediate rendering by browsers and eliminating the need for additional network requests for images or icon sprites (which come with their own, specific challenges).
Simplified Icon Management
Dynamic generation of icons with Iconify removes the burden of managing icon libraries, optimizing SVGs, or creating icon sprites, ensuring cross-browser compatibility effortlessly.
Fontsource
Reliable Self-Hosting
Fontsource enables us to self-host fonts, providing greater control over font updates and rollbacks on a per-project basis without relying on external dependencies or manual downloads.
Enhanced Flexibility
By installing fonts within projects, we’re able to have greater flexibility over how we manage, update, or rollback fonts. Relying on updates from the USWDS means we’re forced to update all or nothing. This puts extra stress on individual teams and on USDWS maintainers when consuming and publishing updates.
Parcel
Speed and Simplicity
Parcel is a compiler and bundler that is extremely fast. It’s able to compile all of our assets in 600ms. Compiling our CSS happens faster than you can blink, at 60ms!
Parcel doesn’t require an index.html
or a custom configuration file. We can configure how we want Parcel to work right in our package.json
.
Tailwind Compatibility
Parcel integrates seamlessly with Tailwind by using lightningcss
to generate efficient CSS. Tailwind is adopting the same tool for its CLI in a coming release.
Alpine.js
Declarative and Intuitive Syntax
Alpine.js complements Tailwind’s declarative nature with a Vue-like syntax, making event binding and attribute manipulation straightforward and easy to understand.
Component Encapsulation
Custom directives in Alpine.js allow us to build encapsulated components without worrying about event bubbling or behavior leakage, enhancing modularity and maintainability.
Rich Plugin Ecosystem
Alpine.js offers a variety of plugins that simplify complex functionalities such as input masking, popovers, and focus management, accelerating development and reducing code complexity.
Twig
You may have noticed that each of the component examples is written in Twig, a templating language for PHP. This is because much of the federal government still uses Drupal as its primary CMS, which relies heavily on Twig to render content. In order to demonstrate the rendering of conditional attributes and specific markup, I chose to demonstrate it with a syntax I felt would be most widely understood. If you’re only interested in the rendered HTML, you can “inspect” any of the examples and simply copy the code directly.