I wanted to create a post to explain a little bit about my approach to front-end website design and development in 2025. With the release of Tailwind v4, it's really helped with my end-to-end process.
I recently hired a digital designer, and this process has also forced me to make sure my process is better, clearer, more consistent and documented. So, this post is dedicated to my findings and hopefully it contains something helpful for you to take away if you're reading this.
Starting with Figma
Working with Mat (our digital designer), we spoke at length about how we can create a more streamlined experience between design and dev, and how we can make best use of Figma. This started with fundamentals - typography, scale and colour.
We already used Utopia in development - but we didn't have anything in place in Figma. We actually had no idea that they had a Figma plugin to set typography and sizing. So after sending Mat away to trial it - let me tell you it really works.
It's improved our design process in three key areas:
- It allows us to create a typography scale out of the box in Figma.
- It allows a smooth handover process from design, to dev, as the variables are referenced and named - meaning I know exactly what I need to use in dev.
- It allows us to design mobile version (we don't regularly as we generally design with fluid design in mind as we design the desktop version), as it has min/max scales. This is really helpful for us with mobile designs - especially when we're offering design only services.
We make sure any text, padding and gap all use the tokens created out of the box - everything is documented, linked back to the Utopia scales for full documentation and ready to handover to development.
Moving into Development
Now we have this blueprint in Figma - it allows me to create our structure in front-end dev as we start. By following the link generated by the Figma plugin, I can export CSS variables like below at ease:
@theme {
--*: initial;
/* @link https://utopia.fyi/space/calculator?c=320,21,1.2,1140,24,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
--spacing-3xs: clamp(0.3125rem, 0.2881rem + 0.122vw, 0.375rem);
--spacing-2xs: clamp(0.6875rem, 0.6631rem + 0.122vw, 0.75rem);
--spacing-xs: clamp(1rem, 0.9512rem + 0.2439vw, 1.125rem);
--spacing-s: clamp(1.3125rem, 1.2393rem + 0.3659vw, 1.5rem);
--spacing-m: clamp(2rem, 1.9024rem + 0.4878vw, 2.25rem);
--spacing-l: clamp(2.625rem, 2.4787rem + 0.7317vw, 3rem);
--spacing-xl: clamp(3.9375rem, 3.718rem + 1.0976vw, 4.5rem);
--spacing-2xl: clamp(5.25rem, 4.9573rem + 1.4634vw, 6rem);
--spacing-3xl: clamp(7.875rem, 7.436rem + 2.1951vw, 9rem);
--spacing-xs-2xl: clamp(1rem, -0.9512rem + 9.7561vw, 6rem);
/* @link https://utopia.fyi/type/calculator?c=320,21,1.2,1140,24,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
--text--2: clamp(0.9115rem, 0.8925rem + 0.0947vw, 0.96rem);
--text--1: clamp(1.0938rem, 1.0523rem + 0.2073vw, 1.2rem);
--text-0: clamp(1.3125rem, 1.2393rem + 0.3659vw, 1.5rem);
--text-1: clamp(1.575rem, 1.4579rem + 0.5854vw, 1.875rem);
--text-2: clamp(1.89rem, 1.7129rem + 0.8854vw, 2.3438rem);
--text-3: clamp(2.268rem, 2.0098rem + 1.2911vw, 2.9297rem);
--text-4: clamp(2.7216rem, 2.3546rem + 1.8351vw, 3.6621rem);
--text-5: clamp(3.2659rem, 2.754rem + 2.5594vw, 4.5776rem);
}
Utilising Tailwind V4
By just tweaking the naming conventions slightly to conform to Tailwind V4 naming conventions, it allows us to generate utility classes at a breeze. We can use classes by using the theme config above:
<h2 class="text-1">Title</h2>
What does this allow? Well it allows for a seamless, end-to-end design and front-end development process that has no guesses and allows me as a developer to follow the blueprint in terms of design to a pixel level.
It's improved our output for sure.
Tailwind-ish
We love Tailwind. I've resisted the movement for years and the more you start using utility classes - the more you sort of start using them more and more. Where it does fall short is in DRY (Don't Repeat Yourself). Take a simple button:
<button class="bg-blue text-light border-none rounded-full no-underline leading-none">my Button</button>
A button is used across files, templates, and we need consistency. In the cases I find myself repeating, I try and create components with normal CSS. What Tailwind V4 allows is keeping the design system in sync between HTML utility classes, and CSS variables. So, our button in CSS references our theme, like so:
.button {
background: var(--color-blue);
color: var(--color-light);
border: none;
border-radius: var(--radius-full);
text-decoration: none;
line-height: var(--leading-none);
}
The beauty of this is that everything references and refers back to our theme. Tailwind is doing it's thing in generating classes, but where our config file is CSS directly, we're using modern CSS conventions (layers, variables etc) to create semantic, modern CSS alongside these utility classes. So, you can even mix and match the two:
<button class="[ button ] [ bg-red ]"></button>
We can create a one-off variant with a utility class with ease! We love that V4 has gone in this direction - we love it when products give us flexibility, choice, and don't force us into certain syntax.
Conclusion
This journey into refining my design and development process in 2025 has been both challenging and rewarding. With tools like Figma, Utopia, and Tailwind CSS V4, I’ve managed to create a seamless, end-to-end workflow that bridges the gap between design and development. Here’s what I’ve learned:
- Efficiency Through Collaboration: We’ve created a system that doesn’t just look great but is also easy to implement. Starting with Figma and standardising typography, spacing, and colour scales using Utopia has eliminated unnecessary guesswork and streamlined our process.
- Tailored Development with Tailwind V4: By utilising CSS variables in Tailwind V4, I’ve been able to unify utility classes with custom components. This approach allows for scalability and flexibility, ensuring that both designers and developers speak the same language, all while maintaining pixel-perfect accuracy.
- Balancing Utility and Semantics: Tailwind CSS is incredible for utility-driven design, but there are cases where custom CSS components are essential to avoid repetition. By combining utility classes with semantic CSS components, I’ve built a process that is consistent, flexible, and adaptable to any project.
Ultimately, this refined workflow isn’t just about producing cleaner code or prettier interfaces; it’s about delivering better results. It’s about ensuring the design intent carries through every stage, from concept to development, and creating a system that makes it easy to iterate, collaborate, and maintain consistency.
If you’re reading this and wondering if this approach could work for you, my advice is to start small. Experiment with Utopia, introduce Tailwind CSS into your workflow, and document everything as you go. The tools are there; it’s all about how you use them.
This post has been a reflection of my process and findings, and I hope it’s been helpful in sparking some ideas for your own workflow. If you’ve got any questions or want to share your approach, I’d love to hear from you!