#221: Move and Replace

[Robin]: This week I’ve been moving into a new apartment and everything is, well, to put it kindly, an absolute nightmare. There’s a rat king of cables and three laundromat’s worth of clothes on the floor. Important documents are flung about all over the place in my kitchen, there are coffee cups in the plant pots, there are knives teetering on top of books, and I am now deadly certain that I’m breaking a dozen or more violations in my tenancy agreement. Drama!

Why am I talking about all this? Well, there is some method to the madness here. Yes, everything is disorganized and tragic but it makes sense in my head. I have made piles of gross stuff, organized bundles of categories which themselves happen to be very disorganized — and I eventually need to deal with them. Once I’ve built up enough courage I slowly walk over to a pile, give it a long, hard stare, and then dive in to fix it.

And I think is true of refactoring a big codebase, too.

Over the past few weeks I’ve been busy refactoring the styles in our app at Sentry — slowly, but surely. But I’ve started to take the approach that was recommended to me by my old mentor Kelly Sutton who in turn learned that from his mentor Kent Beck.

Anyway, step #1 in a refactor? Don’t refactor it, don’t edit the logic of the code itself. First, move all the junk into one spot.

In my case that means moving the five chunks of CSS that styles the Button component and move all of that into the same .less file. But I haven’t changed the logic yet, I haven’t removed any styles, as much as I might like to.

So what’s step #2 of a refactor after moving things? REPLACE! Purge every line of code ruthlessly because now you know that it all works in the order that it should. Delete, delete, delete. Anything that’s inefficient or weird or simply unhelpful? Bye! Send it all back to hell where it came from.

Now it’s important to mention that tech debt is going to happen to everyone but we have a decision as to whether it happens to us or we happen to it. Okay, that sounded smarter in my head. What I mean by that is there is unknown tech debt that hurts everyone and then there‘s the tech debt where everyone is focused on a plan to resolve it. So, at least we’re recognizing there’s a problem here with our CSS. That’s step #0 of any refactor.

But all I’ve been doing this week is move the mess around. I move a bunch of bad code into one spot, wait for tests to pass, and we learn that there are no regressions yet. That’s the plan, at least. We’re still in step #1 of the refactor, just as I’m still stuck in the first stage of moving into my new apartment; make big bundles of mess and then preparing myself to tackle each bundle one by one.

I guess my advice to myself here is this: small steps where you’re not being punk rock and deleting massive amounts of code will actually make things faster in the end. Try and break up every refactor project into two steps: Move and Replace, and from there you’ll be more focused, fewer regressions will happen, and it’ll ultimately be faster in the end.

Although yes, it’s embarrassingly messy and slow in the beginning. In fact, from a distance it even looks like you’re contributing to the mess. But dang it really does seem to work — so much so that when I’m refactoring things I become incredibly annoying:

“Move and replace,” I now whisper to myself. “Move and replace.”

The :focus-visible trick

“What if we could apply focus styles only when the keyboard is used to focus something, not the mouse?” asks Chris in this blog post all about that and the :focus-visible trick. Chris points to Lea Verou’s suggestion several years ago now to remove the outline from all elements that are focused with a mouse:

:focus:not(:focus-visible) { outline: none }

I like this suggestion a lot and I think I’m going to add it to my newly refactored base.less file; that’s where we keep all global styles like h1, p, etc. Back to the refactoring!

Learning CSS Grid visually

Matias Capeletto wrote about how to start learning CSS Grid the other day:

When you are learning CSS Grid, it is easy to feel intimidated by its notation and semantics. Until you develop some muscle memory for it, kickstarting the learning process with visual and interactive tools can be an excellent way to overcome that early trepidation.

That’s where tools like Layoutit Grid come in. It’s an interactive play pen for us to explore making our own grids. You can click different columns and change their area name, create new rows and columns, and see how that changes the code that gets output at the end.

I think what I like about Matias’s take above is that he argues for both learning the intricacies of how the code works under the hood, whilst also allowing for GUI-style interfaces teach you how the syntax works. Above, I’ve created a sidebar and blog section and can see how that fills in the grid-template-areas CSS property. Nifty stuff.

Also this reminds me of a tool that Sarah Drasner made not so long ago called CSS Grid Generator:

I love seeing how these tools can help us become better designers and engineers and also how they can help us unlearn the decades of thinking about web design layout in a certain way. I’m always a little jealous whenever I heard folks who have been introduced to web design and started off with flexbox and grid. How many new and interesting layouts will they come up simply because they’ve grown up with the tools and haven’t had to learn the Old Way of Web Design? That’s annoying but also exciting to me.

Hover highlight effect

Here’s a really smart technique from Aaron Iker I spotted the other day. When you hover a link in this demo you’ll see a rather lovely animation kick off:

It’s one of those animations I love because it’s small but delightful. Under the hood, this is using the very same SVG line animation technique that we’ve mentioned a ton of times before but it’s impressive to me that this technique still feels new and fun.

The gist is that Aaron is using an SVG and hiding parts of it with the stroke-dasharray and stroke-dashoffset CSS properties. We can see this is what’s happening when we hide those lines in Codepen:

See how the whole SVG is visible now? On :hover, Aaron changes the color of that SVG line and also decreases the offset and the stroke-dasharray. The really interesting part about this code to me is that Aaron is using CSS properties in the :hover state like this:

:root {
    --text: #2B3044;
    --line: #BBC1E1;
    --line-active: #275EFE;

a { 
    margin: 0 var(--spacing, 0px);

    svg {
      stroke: var(--stroke, var(--line));
      stroke-dasharray: var(--offset, 69px) 278px;

      &:hover {
        --spacing: 4px;
        --stroke: var(--line-active);
        --stroke-delay: .1s;
        --offset: 180px;

I’ve edited the code above a bit to focus on the ooooo! parts. But basically the :hover state here is changing all these CSS custom properties and I think that’s the coolest thing. Instead of having to redeclare all these CSS properties all over again, Aaron makes it very clear that he’s just changing the variables. It’s so easy to read!

An Event Apart

Only one week until An Event Apart’s Online Together: Fall Summit kicks off on October 26! This is a three-day online web design conference with an intense focus on digital design, UX, content, code, and more. And the speaker lineup is not just incredible, but there will be live Q&A sessions with them as well as one-on-one conversations with special guests. Space is limited, so register now to save a spot. Oh, and use coupon code AEACP and get $100 off your registration!

Register today →

[Chris]: I’m gonna hit ya with some links related to typography I’ve got saved up.

  • At the last WWDC, Apple had some typography advice (from Loïc Sander and Jiang Jiang) which they published as a video: The Details of UI Typography. Optical sizes, variable fonts, tracking and leading, and text styles and dynamic type. There is a lot of talk over Apple’s San Francisco font. Did you know you could just download those fonts? As an aside here, I noticed this is the license for those fonts: “You may use the Apple Font solely for creating mock-ups of user interfaces to be used in software products running on Apple’s iOS, iPadOS, macOS or tvOS operating systems, as applicable. … The grants set forth in this License do not permit you to, and you agree not to, install, use or run the Apple Font for the purpose of creating mock-ups of user interfaces to be used in software products running on any non-Apple operating system or to enable others to do so.” I was looking at SF Mono as a coding font. So I guess you can’t use that if ultimately the code is for a website that it’s possible to view on Windows?
  • This is an awesome video from Oliver Schöndorfer pointing out an obnoxious detail about how time is displayed on iOS. Then goes through a whole journey of prototyping the options and… well, I won’t spoil the ending.
  • In an @font-face declaration, we have the opportunity to use a local() src meaning that if a user has that font locally, we don’t have to bother downloading it (great for performance). But that’s dangerous for the web, as it can be used for user identification (e.g. if the user has “Google Sans” installed, there is a decent chance they are a Google employee). Google talks about a new API to help with this, which involves both permissions and freedom for the browser to not cooperate exactly. Doesn’t look like it totally solves it, but it’s probably quite a bit better.
  • Speaking of Google, here’s Adam Argyle and Oriol Brufau on ::marker in CSS. I covered this as well: Finally, it Will Be Easy to Change the Color of List Bullets. This is all suuuuper great, thank god. Good job CSS.
  • Here’s a super deep dive on font fallbacks from Marcin Wichary for Figma. Fallbacks, even if we don’t think about them much, are a genius and absolutely critical thing to make the web work, be accessible, and long-lasting (who cares if that font doesn’t load right? It will still load in something readable). Web text even does this on a character-by-character basis, and this illustration is the best I’ve seen to explain that: