The Difference Between HTML, CSS, and JavaScript
HTML defines structure, CSS controls presentation, and JavaScript adds behavior. Learn how browsers combine them with runnable examples and practical guidance.
HTML, CSS, and JavaScript are the three core technologies browsers combine to display and operate most websites:
- HTML defines the content’s structure and meaning.
- CSS controls presentation, layout, and visual states.
- JavaScript adds behavior, interaction, and changes over time.
A useful shortcut is HTML = structure, CSS = style, JavaScript = behavior. It is a learning model, not a strict boundary. JavaScript can change HTML and CSS at runtime, and an HTML file can contain or load both styles and scripts.
HTML: structure and meaning
HTML (HyperText Markup Language) describes what content is present and what each part means. Elements identify headings, paragraphs, navigation, links, images, lists, forms, buttons, tables, and page landmarks. Browsers parse the document into a tree-like Document Object Model (DOM) that scripts and styles can work with.
<main>
<h1>Account settings</h1>
<p>Update your contact details.</p>
<form>
<label for="email">Email</label>
<input id="email" name="email" type="email" required>
<button type="submit">Save</button>
</form>
</main>
The tags communicate relationships that visual styling alone cannot. Semantic HTML also gives browsers and assistive technologies useful information. See MDN’s HTML reference and MDN’s guide to structuring content.
HTML responsibilities
- Represent content and its hierarchy.
- Give controls names, labels, and relationships.
- Provide links, forms, media, and landmarks.
- Expose structured content to search engines and assistive technology.
HTML can present a useful page without JavaScript. A form can submit to a server, and links can navigate with only HTML and HTTP.
CSS: presentation and layout
CSS (Cascading Style Sheets) is a rule-based stylesheet language. It selects HTML elements and assigns visual properties such as color, typography, spacing, borders, animations, and responsive layout. CSS also controls how content is arranged across screen sizes.
main {
max-width: 42rem;
margin: 2rem auto;
padding: 1rem;
font-family: system-ui, sans-serif;
}
form {
display: grid;
gap: 0.75rem;
}
button {
background: #0b57d0;
border: 0;
border-radius: 0.4rem;
color: white;
cursor: pointer;
padding: 0.65rem 1rem;
}
button:hover,
button:focus-visible {
background: #0842a0;
}
The cascade resolves which declarations apply when several rules match. Specificity, source order, inheritance, media queries, and user-agent styles all affect the result. CSS can alter layout substantially without changing the document’s meaning. Read MDN’s CSS styling guide for the fundamentals.
CSS responsibilities
- Visual appearance: color, type, borders, shadows, and effects.
- Layout: flow, flexbox, grid, positioning, and alignment.
- Responsive behavior through media and container queries.
- Visual states such as hover, focus, checked, and disabled.
Keep essential information available in HTML. A CSS rule that hides content can make it unavailable visually or to assistive technology depending on how it is written.
JavaScript: behavior and change
JavaScript is a programming language used to respond to events, process data, call APIs, validate input, and update the page. It can read and modify the DOM, change classes and inline styles, create or remove nodes, and react to timers or network results.
const form = document.querySelector('form');
const message = document.querySelector('#message');
form.addEventListener('submit', (event) => {
event.preventDefault();
const email = new FormData(form).get('email');
message.textContent = `Saved ${email}`;
});
Use JavaScript for behavior that improves the experience, while preserving a sensible fallback when scripts fail, are blocked, or have not loaded. Interactive controls must remain keyboard-operable and should expose their state to assistive technology. MDN’s scripting guide covers these patterns.
How a browser combines the three
A browser receives HTML, CSS, JavaScript, images, and other resources. It parses HTML into the DOM, parses CSS and matches rules, calculates layout, paints pixels, and executes JavaScript. Script execution can add or modify DOM nodes, which can trigger another style calculation, layout, and paint. This is a simplified model; browsers can differ in details. See MDN’s overview of how browsers load websites.
- Parse HTML: create the DOM and discover linked resources.
- Parse CSS: create style rules and match them to elements.
- Run scripts: execute inline or external JavaScript according to loading and execution rules.
- Calculate layout: determine each box’s size and position.
- Paint and composite: draw pixels and combine layers for the final view.
A complete runnable example
Save this as index.html and open it in a browser. It contains semantic HTML, CSS layout and states, and JavaScript behavior in one file.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>HTML, CSS, and JavaScript demo</title>
<style>
:root { color-scheme: light dark; }
body { font: 1rem/1.5 system-ui, sans-serif; margin: 0; }
main { max-width: 42rem; margin: 3rem auto; padding: 1rem; }
.card { border: 1px solid #888; border-radius: .75rem; padding: 1rem; }
.actions { display: flex; gap: .5rem; flex-wrap: wrap; }
button { border: 0; border-radius: .4rem; padding: .6rem .9rem; cursor: pointer; }
.primary { background: #0b57d0; color: #fff; }
.dark { background: #111; color: #eee; }
.status { min-height: 1.5em; }
</style>
</head>
<body>
<main>
<h1>Task list</h1>
<section class="card" aria-labelledby="task-heading">
<h2 id="task-heading">Today's task</h2>
<p id="task">Review the page layers.</p>
<div class="actions">
<button class="primary" id="complete" type="button">Complete task</button>
<button id="theme" type="button" aria-pressed="false">Dark mode</button>
</div>
<p class="status" id="status" role="status"></p>
</section>
</main>
<script>
const complete = document.querySelector('#complete');
const theme = document.querySelector('#theme');
const task = document.querySelector('#task');
const status = document.querySelector('#status');
complete.addEventListener('click', () => {
task.textContent = 'Task complete.';
status.textContent = 'Updated by JavaScript.';
});
theme.addEventListener('click', () => {
const enabled = document.body.classList.toggle('dark');
theme.setAttribute('aria-pressed', String(enabled));
theme.textContent = enabled ? 'Light mode' : 'Dark mode';
});
</script>
</body>
</html>
What changes when you edit each layer?
| Change you make | Primary layer | Typical result |
|---|---|---|
| Replace a heading or add a form field | HTML | Different content, semantics, or document structure |
| Change spacing, colors, or columns | CSS | Different appearance or layout with the same content |
| Open a modal after a click or load API data | JavaScript | New behavior or content that changes at runtime |
The boundaries overlap. JavaScript can set element.textContent (HTML content) or element.style.color (presentation). HTML can include <style> and <script>, although separate files often make projects easier to maintain.
Recommended learning and project order
- Write semantic HTML for the content and interactions.
- Add CSS for readable typography, layout, responsive behavior, and focus states.
- Add JavaScript only where behavior or dynamic data is needed.
- Test with keyboard navigation, a narrow viewport, scripts disabled where practical, and a screen reader or accessibility checker.
- Split files when the project grows:
index.html,styles.css, andapp.js.
This order keeps content understandable while you build. It also makes failures easier to isolate: inspect the DOM for structure, computed styles for presentation, and the console/network panel for script and request errors.
Capturing the rendered result
A screenshot captures the browser’s final pixels after HTML, CSS, JavaScript, fonts, images, and network requests have affected the page. For a local page, open it in a browser and use its screenshot command. For repeatable automation, a browser tool must wait for the page’s required state before capturing.
Practical capture checklist
- Wait for fonts and important images to load.
- Trigger the state you want to document, such as an open menu or completed form.
- Choose a viewport and device scale that match the audience.
- Hide transient banners, chat bubbles, and personal data before capture.
- Capture the full page or a specific element deliberately.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers.
See the ScreenshotNeo API documentation for all options. A minimal request is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Options include full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or any viewport, retina scale, PDF paper sizes and page ranges, custom CSS and JavaScript, click and wait actions, ad/tracker/request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of 100 URLs per call, and a usage API. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
There are 1,000 free shots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing gives two months free. Create a free ScreenshotNeo account.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Content appears unstyled | CSS URL is wrong, blocked, or loaded after an early capture | Check the network panel, use a correct relative/absolute URL, and wait for stylesheet readiness. |
| Button does nothing | Script error, selector mismatch, or script ran before the DOM existed | Read the console, verify the selector, and use defer or place the script after the markup. |
| JavaScript changes are missing in a screenshot | Capture happened before the event or asynchronous data completed | Trigger the state, wait for a selector, delay, or network idle, then capture. |
| Layout differs between devices | Viewport, device scale, fonts, or responsive rules differ | Set the viewport explicitly, load the same fonts, and test the relevant media queries. |
| Screenshot shows a consent banner or chat widget | The capture method did not dismiss or hide the overlay | Click or hide the element in browser automation, or use ScreenshotNeo’s cleanup options. |
| ScreenshotNeo response is not billed | The verdict is a bot check, blank page, timeout, failed load, or cache hit | Inspect X-Page-Verdict; adjust access, waits, headers, or URL and retry. |
Performance, reliability, and cost considerations
- Browser work: large images, complex layouts, third-party scripts, and repeated layout changes increase capture time. Reduce unnecessary resources and wait only for the state you need.
- Determinism: pin viewport, timezone, locale, data, and fonts when comparing screenshots.
- Reliability: use retries with backoff for transient network failures, make captures idempotent, and record the URL, viewport, and page state with each artifact.
- Caching: cache stable pages to reduce repeated work; invalidate when content or CSS changes.
- ScreenshotNeo billing: only clean shots are billed. Cache hits and failed or unusable captures are free. Use a TTL you choose, async jobs for slow pages, bulk capture for up to 100 URLs per call, and the usage API to watch consumption.
FAQ
Can I build a site with only HTML?
Yes. HTML can deliver structured content, links, and form submissions. CSS and JavaScript add presentation and richer interaction.
Do I need to learn CSS before JavaScript?
Learn basic HTML first, then enough CSS to build readable layouts. Start JavaScript when you need dynamic behavior; the three skills develop together.
Is CSS a programming language?
CSS is a stylesheet language with rules for presentation and layout. JavaScript is a programming language used for general computation and behavior.
Can JavaScript replace HTML?
JavaScript can create or modify DOM nodes, but starting with semantic HTML usually improves accessibility, resilience, and maintainability.
Why does the same HTML look different in two browsers?
Browsers share standards but can differ in defaults, feature support, font availability, and rendering details. Use standards-based markup, reset or normalize intentional defaults, and test target browsers.


