This is the third chapter of a 4-post series, taking you through a website refactoring process using tachyons. It's about time to get started with this re-write!
- Why re-write in the first place?
- What even is functional CSS?
- The refactoring process, step by step (you are here! 👋)
- The aftermath: key learnings and recommendations
Ok. Here we are, finally.
Well, almost. Let me start by setting the stage here.
We're a couple of days before Christmas. Everyone is leaving on holiday. I have been demanding a two-week window to do some major refactoring, and it looks like the Christmas and New Year break is my "one shot" to get it done.
I get a chance to get in the zone, get some isolation and focus on that one task only, while the office (and BAU) is in shutdown mode.
At this point, I don't have a clear idea of how much I'll be able to refactor over the break. I've done enough research and reasoning around tachyons to know it can solve our tech debt problems. I just don't know how complex the transition from our current CSS to the new system will be. How long it's going to take.
I am sitting in the car with my laptop.
My wife is driving us and our two young kids to Mudgee, a country town 5 hours inland from Sydney, where we're starting a 6-week camping journey throughout New South Wales.
You got that right. I'll be conducting my entire refactoring process while being on the road, in some areas with little to no internet.
Sounds like a plan!
Out of topic, but this reminds me of that controversial tweet that came out. I giggled as I read it in the middle of a major Christmas Day refactoring session:
I certainly don't pretend to be the best developer. Joe McCann doesn't know me. But I was sure as heck hacking over the holidays! 😂
And, here we go.
I'll break the process down in a few steps or milestones I went through, in a chronological way.
Our "legacy" CSS is composed of the Foundation framework and a large amount of custom BEM modules.
Getting started is a tricky one. The website needs to be operational when office re-opens, otherwise BAU will take over again, and my tachyons GIT branch will never see the light.
How do I gradually implement tachyons without putting the website in "demolition site" mode?
After some thinking and discussing in the tachyons slack, I decide to simply load tachyons at the very end of my stylesheet.
This allows me to use a few tachyons helper classes for padding, color, etc, without running the risk of breaking anything else.
If I don't use the helper classes, nothing happens. It feels pretty safe. I can get a feel for tachyons without taking much of a gamble.
Within an hour of work, I am blown away. I am able to remove huge chunks of legacy CSS and replace it with simple tachyons classes. Removing CSS is one of the hardest thing to do in web development, and I am moving incredibly fast. This is truly remarkable. I am giggling.
I try to explain this to my non-dev wife - who is still driving - but she doesn't really get a sense of why it's such a big deal. 😂
I take any given BEM module partial. I find the HTML template for this module, and just rebuild it in tachyons.
I comment out an entire custom CSS partial and move onto the next one. It still works. This is ridiculous.
I was expecting to just replace some margins, padding, font-sizes and weighs, but here I am, writing entirely tachyons-powered components. With incredible ease.
At some point, I notice that my progress will eventually slow down.
I start to notice more and more places where my tachyons classes don't work. Buttons have unexpected hover states, spacing is a bit off.
I realise that I am trying to fight some Foundation classes, that have more specificity than tachyons and therefore win.
If I try to comment out Foundation, I can see some of my nice tachyons modules look weird. They were inheriting some styles from Foundation, and don't look the same without them.
First lesson learned. If you plan to remove the underlying CSS framework at some point - which is my plan - don't wait too long before you do it.
Which leads me to step 2.
It's still very early in the first week. I have plenty of time. I decide to create a new branch called
kill-foundation in which I comment out everything.
I want to see what things will really look like when i get rid of all the legacy CSS.
But first, let me say this: working while camping and watching your family enjoy a holiday, is a beautiful thing. I highly recommend you try it if you have a chance.
Okay, back to our refactoring.
So, I go ahead and comment out all the CSS partials except tachyons.
And I watch the website explode.
"Hey, it's not that bad, actually!"
Sure, the website is broken as hell. What do you expect, I just removed almost 200kb of custom CSS.
But, it's not that bad. Ironically, some parts of the typography and vertical rhythm feel more consistent. This tells me something about tech debt and custom CSS declarations all over the place. 😂
The first thing I decide to fix - because it's by far the most obvious - is all the places were we relied on Foundation's columns.
Flexboxgrid does one thing: it provides you with a super versatile grid system using, well... flexbox (who would have guessed!). If you're familiar with bootstrap's classes, you're going to like it.
Flexboxgrid has a small footprint and makes re-building the grid layouts a breeze. In my books, and taking my designer colleague in consideration, it definitely warrants the addition of 14kb (non g-zipped) to the build.
Once the grid layouts are back in place, I feel very confident. I look at sections of the site and know exactly how to build them in tachyons.
So I get to work, starting with the homepage.
And I complete the homepage within a couple of hours. Boom 💥.
If I still had any doubt that I could pull off the entire rebuild over the holiday, I am now very confident that the site will be ready when I come back in the office.
I still can't get over how fast building modules becomes once you're fluent in tachyons. It's mindblowing. And you get this incredible sense that nothing is getting more complex as you move forward.
It all becomes predictable, and that's a very empowering feeling.
On the 4th of January 2017, 10 days after Christmas, I pushed the new build to our pre-prod environment.
In the 4th and final chapter, we'll dive a bit deeper in tachyons-specific learnings and recommendations.
For now, let's make a few general observations.
The new version of the website is not a 100% match of the legacy site. Nor did it ever pretend to be.
The main purpose of the re-build was to get rid of tech debt. I tried to make the site look the same, while trying to standardise some components to a more consistent overall look and feel.
In some places, the site is not as good as it used to be. But in many places, it's better.
Overall, it definitely needs a polish. While I have an eye for design, I don't come remotely close to skills of SocietyOne's very own design director (and close friend), Mr Matt Barron.
edit: fun fact, Matt and I are now colleagues again at Thinkmill 🙌
The whole thing feels so much more stable. I cannot stress this enough.
Immutable, single-purpose functional CSS classes mean that if you do
things right, there is literally no risk of accidental overrides.
One of the first assumption people do about tachyons is that it's going to be impossible for anyone else to work on your code, unless they learn tachyons.
Well, that's true. And that's true for any codebase. Thinking you can jump in any codebase and just know what to do without having to learn the system is.. delusional.
I strongly disagree to this argument. And I'm Swiss - we tend to remain neutral most of the time.
While I concede that templates look confusing at first, you see things with a completely different angle once you become fluent with the tachyons syntax.
It doesn't take long to memorise tachyons classes. Trust me, it would take much longer for you to make sense of all the custom BEM modules we had in place before that.
When working with functional CSS, the HTML is very declarative and self sufficient. It tells you exactly how things are going to look, without having to lookup CSS stylesheets to figure it out.
Being able to work in one file without ever switching context in your brain yields incredible gains in productivity.
You hear similar comments from React or Vue developers. They love working within one self contained component file. They call it the real separation of concerns, and not separation of languages.
Without worrying about performance at all, the CSS bundle when first pushing to
pre-prod turned out to be less than 50% of the original bundle size.
I feel like no BAU can stop us now.
Put it this way - tachyons as a toolkit for BAU lets you do things that are as easy as slapping inline-styles, but are fundamentally different in the impact they have on the rest of your codebase.
I'm sure you've all been there: a stakeholder (or client) wants to take a section of the site and move it up higher on the page.
It sounds like a "minor change" for some people. As a designer/developer, though, you see some of the issues it can brings to the mix.
Maybe the section had a green background. You've been asked to move it right under another green background section. It doesn't work well at all there. Spacing is completely off now, and the margin-top needs to go away.
In these types of situation, it could be easy to be tempted to just slam an inline-style like
<div style="margin-top: 0;"> and call it a day.
Functional CSS is somewhat similar (but completely different, although that point is often misunderstood) to inline-styles. In that sense, you can apply the same effect to your section with
<div class="mt0"> without any of the negative effects of applying inline-styles.
If you still need some margin top on mobile, but not on larger screens, you could do
<div class="mt2 mt0-ns">.
Good luck doing that with *inline-*styles.
I heard many people claim that functional CSS is for lazy people, or people who don't understand CSS enough to use it well.
I couldn't disagree more.
The way I see it, functional CSS forces you to think "modularity" when writing your HTML. No one enjoys copying and pasting the same classes over and over in an HTML document.
To avoid this, you need to step up your "architecture" game and think of ways to make your HTML components re-usable as much as possible.
Things like storing content in a data array, writing loops to output a repeating block of HTML have a huge impact when it comes to maintaining your code.
Tachyons has definitely made me dig deeper into modular templating techniques. The web is pointing towards web components from all angles. It's good to embrace this mindset.
Extracting your content from your markup, making it as much back-end agnostic as possible, is a good thing. It makes you a better developer.
Functional CSS makes you think in components, systems. Not pages.
Did I just sound like Brad Frost?
Functional CSS is probably not perfect. It's most definitely not to the taste of everybody.
The initial negative reactions on the ugly looking HTML, loss of semantic classes are common, because they are real facts.
You can only see past these reactions if you give it some thought and evaluate trade-offs.
Being a web developer is all about evaluating trade-offs. How much benefits do you need to get from a system or methodology to overcome the perceived negatives?
If I had to summarise my experience with functional CSS in one paragraph, it would be this:
"The benefits I get from using functional CSS, in terms of reduced cognitive load, self-describing declarative HTML markup and huge productivity boost, are simply amazing. They overcome by far the few negatives that this approach brings to the mix. I'd take that trade-off any day of the week."
And I did.
See you in the final chapter for some tachyons-specific observations, suggestions and lessons learned!