< Blog roll

The hills I‘ll die on

Gif of the "the hills are alive scene in Sound of Music

Whenever I get deep in conversation about some such UX or front end development topic that ends up being hot, I’ll inevitably say that “I don’t have that many hills I’ll die on, but this might be one of them” when I’m feeling rather opinionated about it (those who know me know it happens a lot).

Well that happened this afternoon when I was listening to the latest episode of Shop Talk Show. I was just going to let my brain thoughts stay inside my brain when I saw a Bluesky post about that same episode, and I found myself replying before I knew it. The hill in question is number one on the list for this post, though these hills are not organized in any order that I know of.

Shop Talk Show is genuinely a truly great web dev podcast. Chris Coyier and Dave Rupert (President of Web Components) are good chaps that know their stuff and are basically the godfathers of blogging about web stuff. Give it a listen!

It occurs to me that I don‘t have a rant or post about all of these I‘m going to list, so I might do a little bit of explaining why I think the way I do. Let me know over on Bluesky if I should write a full post about any of these if I don’t already have one.

“Dark” is a “mode” not a “theme”#

I already have a post/rant about this one on my blog, so I won‘t belabor the point. Head on over to the post about it if you are so inclined.

Never show an input error while the user is typing#

I am sure we have all experienced this at some point. As soon as we focus a field in a web form, some over-zealous validation script runs and plasters red text under the input that says “The value you have entered is required!”. My response is always “Well no shit, I wasn’t finished yet stupid form.”. I am not alone. Users absolutely hate seeing validation errors while they are furiously fixing said validation errors. I‘m also not alone because there are guidelines all over the internet saying something similar to the above. Validating form fields too early is a big mistake.

System errors are different than form input errors and should be displayed differently#

One of the most common scenarios folks mention when talking about validation is “the username is taken”. It seems very common to display this type of error as red text under an input box, but I don’t think thats right. I think that form field errors should be reserved for errors that happen while the user is filling out the form, not errors that happen after they submit that form and the data gets sent to a server to be used. I separate out “field level” errors from ”system level errors” and I think everyone should. If the server checks that a username is taken, that’s not an issue with the data the user entered. They filled out the form correctly, the data just can‘t go into the system as is.

My thinking is “system level” errors should be displayed as alert boxes over the form rather than field level errors. Theoretically there shouldn‘t be many system issues if the “field level” validation is doing its job and preventing bad formatting. In the “username taken” situation, when the server responds, you might be able to build a UI with a form with one input so the user can JUST choose a new username and the rest of the data can be kept and used as is. There are lots of options and red text under the field is the laziest one.

Tabs#

Not spaces.

Utility classes for everything isn‘t the right approach to CSS#

Yep, had to have a Tailwind take in here. Don‘t freak out, I‘m not a Tailwind hater. Its fine. Its not amazing and groundbreaking. Its not “the standard way to style things on the web” no matter what talking heads on youtube say. Its just fine. Use it if the approach resonates with you, don’t if it doesn’t. But the one major drawback is that using utility classes for everything is a bad approach. The main thing utility classes are bad at is state/component property change. Attribute-based styling ([data-some-state="some value"] { ...the style}) is SO much better than utility classes when changing style based on the value of a component prop or internal state changing.

This one might need to be a longer post with code snippets. But while I work on writing that, think about how many runtime JS packages have evolved around the concept of having to switch out a pile of Tailwind utility classes when a prop changes. cx, classnames are just a few. All of them basically do a el.classlist.add(…tailwind pile`). It has to be simpler and more performant to write a static style the browser can just handle automatically than to use JS to flip out a giant class string every time. And that‘s without touching on having to read the piles of util classes for each possible state. Yikes.

And since I mentioned it a bit…

There is no “standard” way to do anything on the web#

Well there are, but actual web standards like APIs are never what talking heads are referring to when they say asinine stuff like “React won the web” or “Tailwind is the default” on a podcast. It grinds my gears when anyone declares that “{popular tool}” is ”the standard on the web”. React is fine. I might even call it good or valuable for some use cases. Its popularity is undeniable. But to declare that React is ”the standard” these days basically ignores that Wordpress powers like 50% of the internet still.

Tailwind is great for a lot of folks as well, but its usage graph compared to the number of websites on the internet is tiny. If we can trust Google‘s AI summary of the search “tailwindcss market share” we see it is used on 1.7% of websites where the css framework is known. 1.7% is a lot of websites, but its still less than 2%. The AI summary for a similar search about Bootstrap shows that Bootstrap‘s market share is like 75%. So much for tailwind being “the standard”. But you can find SO many blog posts with rage-inducing titles talking about how “Tailwind won”. LUL.

As far as I‘m concerned, the web has exactly 3 standard ways of doing things. HTML for structure, CSS for presentation, JS for behavior. And thats it. Literally everything else is just “popular”.

Web components are the right way to build reusable components#

You knew this one was coming too didn’t you? I have been a “web components guy” for a long time now, so its kinda my job to shill for web components. My reasoning for them being the right way to build reusable components is simple. A component isn‘t as reusable as it could be if some people can‘t use it. If you want to build a react component, build it! Ship that thing! But recognize that in doing so, you are actively prohibiting a LOT of the web. As the component author thats a choice you can make for sure! But if you do make the choice to build a framework-specific component then you are effectively preventing all of the rest of the web from using your cool thing. Why? If your idea is so great, why not make it so that literally anyone can use it? Web components work literally everywhere there‘s a browser DOM.

There are libraries out there that make several different framework copies of the same component and stitch them together with some core package where the actual logic lives. Clerk has copies of their UI components for lots of frameworks. Awesome! How much complexity are they introducing when they could just have built web components?

People should stop using jsdom to test browser code#

If you are writing code designed to run in a browser, testing it in a fake DOM is not the way. Not only are you not testing what you think you are, you are destined to run into an issue with any fake DOM, but especially jsdom.

I don‘t want to throw much shade at jsdom or the team. There was a point in time where jsdom was truly needed and worked well. But that time passed a long time and its time for the front end to move on

Jsdom is not a faithful recreation of browser DOM. There are a LOT of APIs that are just straight up not implemented. Also there will always be a lengthy lag between when a feature arrives in browser and when that same feature is available in a fake DOM. Try to write some CSS with @layer in it and run that in a jsdom environment. red text everywhere. Jsdom‘s CSS parser is a trillion years old and errors when it sees newer CSS. @layer has been a baseline browser feature for years at this point, but jsdom‘s CSS parser still errors.

Real browser testing tools like Playwright have gotten way too good. People are switching I think, but it should be more widespread than it is.

skipLibCheck: true always and forever#

skipLibCheck: true should be the default in Typescript. This config in Typescript is baffling to me that it even exists. If false every ts/js file that matches the includes in your project will be typechecked, even in node_modules. So a library you installed from npm could break your typecheck script for your app by having a bad export or something. Who wants that?! Why?! If you are installing a library its so incredibly highly likely that you didn‘t also write that code. Why would you want it to be able to break your build?? LOL

So I‘ll die on nine hills I guess#

I think thats all of them? I dunno, we‘ll see what comes up tomorrow at work. Nine hills to die on isn‘t that bad right?

I‘m also interested in the hills you would die on. Indulge me and start up a thread on Bluesky about it? Who knows, maybe I can add to this list and join you on a hill!

The End