NOTES

The Line Between Describing and Executing on the Web

Why HTML and CSS feel smart but don’t actually run logic, execution flow, or algorithms the way programming languages do.
Some things just sit there, some swing when it’s time to move.

I started messing around with programming somewhere around 2013. Back then, the web felt different. Rougher, maybe. Less polished, but also more honest about what it was and what it wasn’t. Since that time, there’s one thing I’ve been oddly consistent about: I never called HTML or CSS “programming languages.”

Not because I wanted to sound smarter than anyone else. Not because I was trying to gatekeep. It just never felt right in my head.

Even back then, the distinction was clear enough.

HTML was structure. A skeleton. Headings, paragraphs, links, forms. You weren’t telling the computer to do anything. You were describing what existed. Where things sat. What they meant semantically. That was it. No execution. No decision-making. No flow.

CSS was more interesting. Even early on, it already looked clever. Selectors, cascading rules, layout behavior, breakpoints. And over the years, it became much more capable. You can calculate sizes based on the viewport. You can define animations with keyframes. You can target elements selectively with `:not()`, `:nth-child(3n+1)` (example), or newer relational selectors. You can react to conditions like screen width or orientation. You can even fake certain behaviors that look logical on the surface.

And I get why people pause there and think, “Well... this kind of feels like programming.”

It feels like it. It looks like it. But when I slow down and actually think about what’s happening, it still doesn’t cross that line.

CSS doesn’t run algorithms. It doesn’t execute steps. It doesn’t say, “Do this, then do that, repeat until a condition changes.” There’s no real sense of time or sequence from CSS itself. What CSS does is declare rules. Conditions are evaluated, not executed. The browser’s rendering engine does the heavy lifting. CSS just describes how things should look if certain conditions are true.

In real programming, that idea shows up everywhere, in many everyday forms. “If the user clicks this button, then execute this function.” “If the user submits a form, validate the input, and if it fails, stop and show an error.” “If data coming from an API matches what the user typed, call this handler; otherwise, branch somewhere else.” “While a value is still changing, keep listening; once it stabilizes, move on.” “Loop through this list, process each item, skip the ones that don’t qualify, and break early if a certain threshold is reached.”

That’s what execution looks like. There’s a sense of order. Time matters. One thing happens because another thing already happened. State changes, conditions are checked, decisions are made, sometimes reversed, sometimes repeated. The system moves forward step by step, even if those steps are abstracted away.

CSS never really enters that world. It doesn’t wait for a result and then decide what to do next. It doesn’t say, “Okay, now that this failed, try another path.” It doesn’t loop, it doesn’t halt, it doesn’t resume. Rules are evaluated, sure—but nothing is executed in the way programmers usually mean when they talk about logic or algorithms. The browser reacts; CSS just describes how things should look when certain conditions are true.

That difference—subtle at first glance, obvious once you slow down—is where the line actually is.

That distinction matters, at least to me.

It’s the difference between giving instructions and defining constraints. CSS is closer to physics than to logic. Gravity doesn’t run code. It just exists, and objects behave accordingly. CSS works the same way. You define the environment, and the browser resolves it.

HTML is even further away from programming. Calling it a programming language always sounded like calling a blueprint a construction worker. Or calling sheet music a performance. Useful, essential, powerful in its own way—but not executable logic.

Over time, the confusion around this didn’t come from technical evolution. It came from language. From simplification. From how people teach and market web development.

Learn three programming languages: HTML, CSS, JavaScript.”

I’ve seen that sentence more times than I can count. It’s convenient. It’s beginner-friendly. It avoids explaining deeper concepts like declarative vs imperative systems, execution models, or separation of concerns. But convenience has a cost. The cost is conceptual clarity.

What makes it stranger is that this confusion stuck even among people who should know better. Developers, programmers, people who’ve written actual algorithms and debugged real logic errors still sometimes lump HTML and CSS into the same category. At that point, it’s no longer ignorance. It’s habit. Or maybe identity?

Admitting that HTML and CSS aren’t programming languages sometimes feels like downgrading one’s skill set. As if difficulty automatically equals programming. But difficulty and classification aren’t the same thing. I admit, CSS can be brutally hard. Layout bugs, specificity issues, cascade conflicts, responsive edge cases—none of that is trivial. But complexity doesn’t magically turn a declarative system into an algorithmic one.

Around the same time, jQuery was everywhere. And yeah, jQuery. I used it. Most of us did, sure. It solved real problems at the time. Browser inconsistencies were painful. Vanilla DOM APIs were clunky. jQuery smoothed things over.

But as browsers matured, I slowly drifted away from it. Not out of hatred, not because it was “uncool,” but because it started to feel unnecessary. Vanilla JavaScript became capable enough. Cleaner. More direct. Less magic.

These days, I almost always prefer plain JavaScript. And even then, I use it sparingly.

Part of that is practical. I still work a lot with platforms like WordPress. You don’t always get full control there. You work within constraints. You inject scripts carefully. You keep things light. You think twice before pulling in external libraries that add weight, complexity, or maintenance burden.

And part of it comes from something older.

Before “web apps” became the default expectation, there were WAP sites. Mobile-first before the term existed. Simple pages. Minimal scripts. Fast load times. Content mattered more than cleverness. On slow connections and low-end devices, simplicity wasn’t an aesthetic choice. It was survival.

Sometimes I look at modern websites and, honestly, they feel heavier than they need to be. More fragile. More dependent. More layers between the user and the content. And I’m not anti-framework or anti-modern tooling. I just don’t believe everything needs to be engineered to death.

That same mindset applies to how I think about HTML and CSS.

They are foundational. Essential. Powerful in their domain. But they are not programming languages, and pretending they are doesn’t elevate them. It just blurs important boundaries.

Understanding why they are different actually makes you better at using them. You stop forcing logic into places where logic doesn’t belong. You let each tool do what it’s designed to do. Structure stays structure. Presentation stays presentation. Behavior stays behavior.

Maybe that sounds old-fashioned. Maybe it sounds like someone who’s been around the web for too long. But when I look at how browsers actually work, how rendering engines resolve rules, how execution models differ, this mental separation still feels right.

And yeah, I know. In casual conversation, calling HTML and CSS “programming languages” doesn’t break anything. The world won’t end. But when we stop caring about accurate terms, we slowly stop caring about accurate thinking.

For me, this was never about being technically correct for the sake of it. It was about having a clean mental model. One that still holds up after more than a decade of watching the web evolve, bloat, simplify, regress, and reinvent itself.

HTML is a skeleton. CSS is a set of physical laws. JavaScript is where thought and action begin.

That division still makes sense to me. And honestly? It probably always will.

image_title