Hacker News new | ask | show | jobs
by tomlagier 2189 days ago
I think the fundamental problem I find when architecting a new website is that not enough thought has been put into making HTML and CSS sites scale with complexity.

It feels like we put all of our eggs in the JS basket - we know how to factor out well-scoped components, encapsulate styles at the component level, and build reactive, state-driven interfaces, all from JS.

There are certainly patterns that allow for componentization, encapsulation, and state management in pure HTML and CSS. None of them that I have used (pure WebComponents, SSR templating a la Pug or Rails/Laravel/etc, the "good ol' days" of "simple" single-file HTML/CSS) have felt like they scale beyond a basic document with link-based navigation.

As soon as you introduce forms, real-time updating, or layered interface state (modals, drop-downs, etc) you start spiraling into progressively more and more kludgy orchestration scripts until you end up wishing you'd just built the damn thing in React to start with.

If there was a well-defined set of HTML and CSS patterns that you could start your website with and _always_ feel like you could add additional functionality without compromising the existing structure, I'd migrate to that in a second.

As it is, the best way I can see for accomplishing a web project where I don't feel boxed in as soon as the requirements change is to just eat the few days of setup complexity up front and use a well-supported JS-based component framework.

There are all sorts of terrible downsides to that approach, as have been extolled ad nauseum here and elsewhere, but I legitimately don't see another way to do it. It's easy to say "for a simple static site, just use plain HTML/CSS!", which is fine if there's a clear scope that won't expand.

The second you introduce uncertainty and possible future complexity, I don't see a better alternative to a current JS-favored stack.

That's hugely compounded by all of the zillion QOL things that you need to worry about as you account for complexity - time to first paint, responsiveness across screen sizes, proper eventing, cross browser support, memory leaks, jank-free animation, page weight, internationalization, etc etc etc. One layer of the stack has an answer to most of these concerns, but it's very difficult to orchestrate all of them without ending up with a lot of JS that needs to be managed.

2 comments

Nice to also read this sentiment, I just go all in on client-side code (react-redux, redux-forms, css-in-js, next.js) and once it's set up and working you can really iterate quickly and it all scales.

I find myself annoyed by how trendy it is to crap on all of the progress that has been made on the client-side stack... basically it seems like a lot of the lessons we have learned over the years are being forgotten. "Embrace the C in CSS!" Like, no! That C is what lead to the most painful CSS refactor and cost 6 months of my life. "Seperation of concerns!" It sounds good to say HTML and CSS should be separate, but we found how powerful it is to co-locate a component's styling with the component. People underestimate how much styling is just inline styles. "Wait, what do I name this class that is just applying margin-top?" If you have a global bin of css utilities and theme variables, everything else is just inline on the component.

How do forms require Javascript in your view?

My experience is that most of the Javascript used for forms is for fancy custom controls (where a standard one would be fine), weird editing flows (like click to edit), or other functionality which isn't actually needed.

That's not to say that JS with forms is evil. HTML validation is better than nothing, but complex data requirements may require custom validation logic in JS as a convenience to the user.

JavaScript is a requirement on most forms due to either designer or client expectation. They want styled, custom client side validation. They want a visual loading state while the form is being fetch'd to the server/service. They want a nice success message to display inline once the submission is complete. Rarely is it custom controls or weird editing flows in my experience - it's much simpler than that.

And we do it because they're paying the bills - there are more important hills to die on.

Validation, datepickers, multi-select, other complex controls, dynamic forms (think "add row"), accessibility. You can definitely get away with simple forms in pure HTML, but again it puts a hard limit on the complexity you can support.
Examples where some JS has its place for forms:

1. The browser already gives you <input type="number"> or <input type="date">, but you may also need <input type="credit-card-number"> or <input type="expiration-date">. For credit card numbers (or bank account numbers) specifically, you want the input field to break it up into groups of 4 digits similar to how it's printed on the card, to make it easier for the user to double-check their input.

2. Suppose you're in the checkout workflow of a webshop. While choosing a shipping method and destination, I want to see the final price update to reflect my selection immediately. I don't want to flip back and forth between selecting a shipping method and seeing the actual cost on the final confirmation screen.