How HTML, CSS, and JavaScript Work Together

A hands-on walkthrough for beginners: build one small button, give it structure with HTML, looks with CSS, and behavior with JavaScript, and watch the three layers cooperate on a real page.

Published September 20, 20268 min readBy ACY Partner Indonesia
Three front-end layers combining on one web page
300 × 250Ad Space AvailablePlace your ad here

When people first learn web development, the three names HTML, CSS, and JavaScript usually arrive all at once, and it can feel like you’re supposed to master three separate worlds before anything works. The good news is that they were designed to fit together, like three workers on the same small team. The fastest way to see how they cooperate is to stop reading definitions and build something tiny.

So that’s exactly what we’ll do. In this article we build one button. Just one. It will start as plain text on a page, then get a proper look, and finally do something when you click it. By the end you’ll have seen each layer added on top of the last, and you’ll understand which layer is responsible for what.

If you want the big-picture explanation of why the web splits work into three layers in the first place, that’s covered separately in the conceptual companion to this piece. Here we stay practical and keep our hands on the keyboard.

The job each layer does

Before we type anything, it helps to name the roles. Think of building a small web feature the way you’d think about building a piece of furniture in a showroom.

  • HTML is the structure: the wood and screws. It says what things are — this is a button, this is a heading, this is a paragraph.
  • CSS is the finish: the paint and polish. It says how things look — this color, this size, these rounded corners.
  • JavaScript is the behavior: the moving parts. It says what happens when someone interacts — click this and a message appears.

A useful way to remember it: HTML is the noun, CSS is the adjective, JavaScript is the verb.

HTML  ->  structure  ->  "what it is"
CSS   ->  presentation ->  "what it looks like"
JS    ->  behavior    ->  "what it does"

Each layer is optional in the sense that a page can technically exist with only HTML. But a real, polished feature almost always uses all three, and they layer neatly on top of one another.

Layer one: structure with HTML

Let’s create the most basic version of our feature. Open a new file and call it index.html. Everything below goes inside it.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>My First Button</title>
  </head>
  <body>
    <h1>Welcome</h1>
    <button id="greet-button">Say hello</button>
    <p id="message"></p>
  </body>
</html>

If you open this file in a browser, you’ll see a heading, a clickable button that says “Say hello”, and… nothing else interesting. The button is there, but it’s plain, and clicking it does absolutely nothing yet. That’s expected. Right now we only have structure.

Notice two small details that will matter soon. The button has id="greet-button", and there’s an empty paragraph with id="message". An id is just a unique label we attach to an element so other layers can find it later. The empty paragraph is a placeholder — a spot where JavaScript will eventually write a greeting.

What an id is for

An id is a name you give one specific element on the page. It has to be unique — only one element should carry a given id. We use ids here so CSS and JavaScript can point to exactly the right element without confusion.

New to this layer? The dedicated explainer What Is HTML? walks through the tags and structure in more depth.

Layer two: looks with CSS

The button works as a thing, but it looks like a leftover from 1998. Let’s give it some style. CSS is written as a list of rules. Each rule picks an element (a “selector”) and then sets some properties on it.

We can put CSS right inside our HTML by adding a <style> block in the <head>:

<head>
  <meta charset="utf-8" />
  <title>My First Button</title>
  <style>
    body {
      font-family: system-ui, sans-serif;
      padding: 40px;
    }

    #greet-button {
      background-color: #00b8e6;
      color: #ffffff;
      border: none;
      padding: 12px 20px;
      border-radius: 8px;
      font-size: 16px;
      cursor: pointer;
    }

    #greet-button:hover {
      background-color: #0098bd;
    }
  </style>
</head>

Reload the page and the difference is immediate. The button is now blue with white text, rounded corners, comfortable padding, and the mouse cursor turns into a pointer when you hover over it. Hovering even darkens the color slightly, thanks to the :hover rule.

Read that #greet-button selector carefully. The # means “the element whose id is greet-button” — this is how CSS reaches the exact button we labeled in the HTML. We didn’t touch the HTML structure at all; we only described how it should look. That separation is the whole point. Structure stayed put; presentation got added on top.

You wrote It controls
background-color the fill color of the button
border-radius how rounded the corners are
padding the breathing room inside the button
cursor: pointer the hand cursor that signals “clickable”

If you’d like to go deeper on selectors, colors, and spacing, see What Is CSS?.

Layer three: behavior with JavaScript

We have a button that looks like a button. But click it and the page just sits there. Making it do something is JavaScript’s job.

Add a <script> block at the very end of the <body>, just before the closing </body> tag:

  <body>
    <h1>Welcome</h1>
    <button id="greet-button">Say hello</button>
    <p id="message"></p>

    <script>
      const button = document.getElementById('greet-button');
      const message = document.getElementById('message');

      button.addEventListener('click', function () {
        message.textContent = 'Hello there, nice to meet you!';
      });
    </script>
  </body>

Now click the button. The empty paragraph fills with a friendly greeting. Click again — it stays. You just made a page react to a human.

Let’s read those few lines slowly, because they show the connection between all three layers:

  1. document.getElementById('greet-button') tells the browser: go find the element whose id is greet-button. That’s the very button we built in HTML. JavaScript is reaching into the structure.
  2. We do the same to grab the empty paragraph (message).
  3. addEventListener('click', ...) says: when this button is clicked, run the function inside.
  4. Inside the function, message.textContent = '...' writes text into the paragraph — changing what the user sees, live, without reloading.

Put scripts at the bottom

Notice the <script> sits at the end of the body. Browsers read a page top to bottom. If the script ran before the button existed in the document, getElementById would find nothing. Placing the script after the elements is a simple, reliable habit for beginners.

That’s the handshake. HTML created the button and gave it an id. JavaScript used that id to find the button, then listened for a click, then changed the page in response. Want a fuller tour of variables, functions, and events? Start with What Is JavaScript?.

Seeing the three layers cooperate

Step back and look at what each layer contributed to one single button:

<button id="greet-button">     <- HTML: it exists, it's a button
background-color, border-radius  <- CSS: it looks clickable and friendly
addEventListener('click', ...)   <- JS: it responds when clicked

The same id, greet-button, appears in all three places. That shared name is the thread that ties the layers together. HTML defines it, CSS styles it, JavaScript controls it. None of them had to know the internal details of the others — they just agreed on a label and a place on the page.

This is also why developers usually keep the three in separate files on real projects. In our tiny demo we crammed everything into one index.html for convenience, but as a feature grows it’s cleaner to have index.html, styles.css, and script.js as three files. The HTML then links to the other two:

<head>
  <link rel="stylesheet" href="styles.css" />
</head>
<body>
  <!-- your content -->
  <script src="script.js"></script>
</body>

Same idea, just tidier. Structure, presentation, and behavior each live in their own file, and the page pulls them together.

Keep responsibilities where they belong

It’s tempting, once you know JavaScript, to do everything with it — even styling and structure. Resist that early on. If something is about looks, reach for CSS. If it’s about what an element is, that’s HTML. Letting each layer keep its own job is what makes a project easy to read and fix later.

A quick mental checklist

When you build any small web feature, you can walk the same three steps every time:

  1. Structure first. What elements do I need? Write the HTML. Give the important ones an id or a class.
  2. Then style. How should it look? Write CSS rules that target those elements.
  3. Then behavior. What should happen on interaction? Write JavaScript that finds the elements and responds to events.

Do them in that order and you rarely get lost. Each step builds on a finished version of the one before it. A page with only HTML still works. Add CSS and it still works, just prettier. Add JavaScript and it gains a pulse.

Wrapping up

We took a single button from plain text to a styled, interactive element, and along the way you saw the division of labor that powers every website you’ve ever used. HTML gave it structure and a name. CSS gave it a look. JavaScript gave it behavior, reaching back to that same name to wire everything up.

That’s the heart of front-end development. Bigger projects add tools, frameworks, and a lot more code, but underneath it’s still these three layers cooperating in the same way you just watched. The next time you meet a complicated interface, you can mentally peel it apart: what is it (HTML), how does it look (CSS), what does it do (JavaScript). Once that lens clicks into place, the whole web starts to make a lot more sense.

Tags:htmlcssjavascriptfrontendfundamentalsbeginners
728 × 90Ad Space AvailablePlace your ad here

Related Articles

See All Articles

You Might Also Like

Arrays and Tuples in TypeScript cover
Frontend / TypeScript

Arrays and Tuples in TypeScript: Typing Lists the Right Way

Learn how to type arrays and tuples in TypeScript. Understand string[] vs Array<number>, when a fixed-length tuple is the right tool, and how readonly keeps your data safe.

Sep 20, 20269 min read
Basic Types in TypeScript cover with string, number and boolean tokens
Frontend / TypeScript

Basic Types in TypeScript: The Building Blocks You Use Every Day

A beginner-friendly tour of TypeScript's basic types — string, number, boolean, null, undefined, plus any, unknown, void, and never — with lots of small, practical examples.

Sep 20, 20268 min read
Classes in TypeScript cover with a typed class snippet
Frontend / TypeScript

Classes in TypeScript: Typed Fields, Access Modifiers, and More

Learn how TypeScript upgrades JavaScript classes with typed fields, access modifiers, readonly, parameter properties, interfaces, and abstract classes — explained plainly for beginners.

Sep 20, 20268 min read
Declaration Files dot d dot t s cover with declare module code chip
Frontend / TypeScript

Declaration Files (.d.ts): Types for Untyped Code

Learn what TypeScript declaration files (.d.ts) are, how ambient declarations and the declare keyword work, and why you consume @types packages far more often than you write them.

Sep 20, 20269 min read
Decorators in TypeScript cover with an @Component code chip
Frontend / TypeScript

Decorators in TypeScript

A beginner-friendly introduction to decorators in TypeScript: what the @something syntax means, where you meet it, a simple example, and why it keeps evolving.

Sep 20, 20268 min read
Enums in TypeScript cover illustration
Frontend / TypeScript

Enums in TypeScript: A Friendly Guide to Named Constant Sets

Learn how enums in TypeScript group related constants under readable names. We cover numeric vs string enums, when they help, and the union-of-literals alternative.

Sep 20, 20269 min read