Why Writing Websites Always Sucks

Or, why you’re always fitting four pounds of crap into three sacks.

Someone — I can’t remember who — used to be very enamored of a colorful phrase for messed up situations: “ten pounds of crap in a five pound bag”. Every time I try to write for the web, that’s how I feel. Four elements in three channels.

Let me try to explain.

MagicaVoxel is fun.

Interfaces — by which I primarily mean web interfaces, but the principle applies to other media as well— are made up of four layers:

  1. Content: What the things are made of
  2. Styling: How things look
  3. Layout: How things interrelate to each other
  4. Logic: How the user controls the engagement

(Non-interactive content would seem to have no ‘logic’, but what this really means is that the logic is external to the medium. An example is a poster seen on the subway — the user’s means of ‘controlling’ the information lie with them, such as averting their gaze, moving closer, or taking a picture of it.)

The more bespoke a medium, the thinner the lines between these. A printed book has a relatively fixed layout, with margins and lines, a field and headers and footers. Styling is related to layout — font size, for example, determines layout, whereas font family might not have as much of an impact — and content is coupled to structure, but only weakly. (For example, a book might be written to have chapters. The content inherently has structure, because the author knows it will be embedded in a medium where chapters make sense.)

In contrast, a hand-drawn picture book might blur the lines between content and layout, or between styling and content. Free-form poetry does this, using structure as content; pop-up books embed control within structure, guiding the reader in discovery.

A page from “Tree In The Trail”, with a central block of text surrounded by drawings and explanatory text about the evolution and construction of covered wagons.

Bespoke books give even more opportunities. One of my favorites growing up was The Tree In The Trail, one of Holling C. Holling’s many great books about USA’s past. Nearly every page was a cornucopia of content; the backbone of the story made up the central, traditional flow, but around it, the wide margins were filled with diagrams and drawings and stories and facts, all relating to and expanding on the story.

Because of Holling’s control over the structure and stylings in the marginalia, he was able to able to build a unique visual experience for his readers, pacing the information to coincide with the story, while not interrupting its narrative flow.

After twenty-someodd years, the web has matured into a fairly stable medium. The Java(Script) wars have been fought and won, and for now, Javascript has come out on top. HTML has been expanded and clarified; CSS has grown more powerful, its focus sharpened even as its expressiveness grew.

The web, in general, is built on these three parallel technologies, braided together into a combined mechanism for serving experiences. Different stacks use different versions, but in the end, it all ends up coming through this same triply-split pipe.

HTML provides layout. It says where things should go, and how they relate to each other.

CSS, unsurprisingly, provides style. It says what things should look like; which ones should resemble each other, and which should look different.

Javascript, and its more usable descendents, provide logic. They give the author and the user control over interaction.

(I’m well aware that you can use CSS for limited forms of logic, JS for styling, and so forth. We’ll get there.)

But what about our fourth channel, content? Where does it live? The short answer is: everywhere. And that’s a problem.

If you had said this to Web 1.0 folks, they would have said the answer was easy: content goes in HTML. Every HTML entity, in the end, contains text or an image, so the content should just go inside the HTML. Done! Easy peasy.

But the introduction of dynamically constructed web pages changed the balance. Putting static text inside an HTML file doesn’t work when that text is stored in a database, or constructed on the fly from cookies and ad servers and random number generators and phase of the moon.

Fine! Let’s put it in the Javascript.

Well, that doesn’t completely work either. Structure and content are tightly linked; and Javascript is a programmatic language, not a declarative language. Yes, you can declare things in a programming language, but the temptation to sneak some logic in there is very strong. Having gobs of content in your logic also makes it harder for authors and creators — it means you have to rebuild (or at least re-version) your code when the content changes, which totally sucks. You can use the code to grab content from another source, but you’ve only abstracted the problem up one layer — you still have to update your code every time the structure of the data changes.

(Yes, I see you there in the back. Please — I beg of you — do not put your content in the CSS. Even if that means it gets through people’s spam filters.)

Well, maybe. But also no. The web isn’t made of databases; and therein lies the rub. Our three channels don’t include a good way to talk or even think about content; and as a result, we end up having to think about it everywhere.

Let’s say you’re writing a blogging site (and it’s 2019, really you should just be downloading a blogging site from your favorite package site). If you decide to structure blog posts into the very simple division of “title” and “content”, now you’ve got to propogate those two entities across all your representations: HTML, CSS, and Javascript. If, later on, someone decides to add “author”, you have to update all three.

The web has many solutions to this problem. This week, the popular ones are Angular, Vue, and React. Let’s talk about their solution to this problem. (While each of these frameworks is flexible enough to do a lot of things, I’m going to only analyze the ‘standard’ practice for each, the ones taught in the READMEs and online courses.)

Angular and Vue put the content in the HTML, mostly. But they also put some logic in the HTML, to help with the tight linkage between content and structure. The advantage is that, with content wrapped in structure in one place, it’s easy to reasonable when you look at it, especially for common data types like lists and conditionals.

The downside is that half the logic is in the HTML, another half is in the Javascript, and a third half might be hiding on the backend (e.g. in stored procedures).

React puts content (and structure, and logic) in the Javascript, or rather, in the JSX. This has the advantage of having three of the four streams in one place, but it makes those three things very tightly coupled.

Some folks like having everything in the JSX, so they also put CSS in there via Styled Components or other such solutions. This makes it easier to find the styles for components, and helps with scoping, but does tie styling changes to code changes.

None of them present an easy solution, and part of that’s due to a final wrinkle: with all templating engines, the code isn’t acting on the content, it’s acting on the shape of the content. In these languages, when you say {{blogpost.header}}, you’re fairly sure header is a string — you might even have length restrictions on it.

But that’s the price we pay for mass publication: you’re giving up the tight connection to meaning achieved, for example, in the example from Holling above, where the history of the covered wagon is covered alongside a retelling of a wagon-trail’s passage (and later incorporated into the history of the tree itself).

On the web, we see similar examples in Bret Victor’s amazing essays, or the semi-interactive Homestar Runner (now sadly relegated to non-interactive status with the death of Flash), with content and styling and structure and logic intertwingled into an effective whole.

And so we’re back to an unsurprising point: structure, logic, and styling are incredibly important, but they are subservient to the main goal of communicating content.

Perhaps that’s why it’s so hard to figure out where content goes; because it’s the backbone of everything else.

(If you enjoyed this one, the nature of this medium guides me to remind you to clap for it. It makes my day when folks enjoy reading things enough to let me know it.)

Obligate infovore. Antiviral blogger. All posts made with 100% recycled electrons, sustainably crafted by artisanal artisans. He/him/his.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store