HTML, CSS, JavaScript Fundamentals — Web Dev Basics

Photo: Bibek ghosh / Pexels
Every website you have ever visited, from a five-page portfolio to a full banking dashboard, is built from the same three languages. HTML defines what content exists on the page, CSS decides how that content looks, and JavaScript controls how the page reacts when someone interacts with it. According to MDN Web Docs, HTML is "the most basic building block of the Web," and the Stack Overflow 2025 Developer Survey found that JavaScript remains the most-used programming language among professional developers at roughly 66%, with HTML/CSS close behind at around 62%. If you understand how these three pieces fit together, you can read almost any website's source code and know exactly what each part is doing.
This guide walks through each language individually, then shows how they combine to build a working, interactive feature. Along the way you will see the actual mental model browsers use to parse a page, not just a list of tags to memorize.
Why three separate languages instead of one
A reasonable question for a beginner is why the web didn't settle on a single all-purpose language the way many desktop applications did. The separation is deliberate, and it traces back to the earliest design of the web itself.
Tim Berners-Lee created HTML in 1990 as a markup language for sharing linked scientific documents at CERN, according to W3C's history of HTML. It had no concept of visual styling. When Håkon Wium Lie proposed CSS in 1994, the goal was explicitly to separate presentation from content so that the same HTML document could be restyled for different devices, print layouts, or user preferences without touching the underlying markup, a principle documented in the W3C CSS history. JavaScript arrived in 1995, built by Brendan Eich at Netscape in ten days, to give web pages the ability to respond to user actions without a round trip to a server for every click, as described in Mozilla's JavaScript history retrospective.
The separation-of-concerns model has a practical payoff you will feel immediately once you start building anything real. If you want to redesign a site's color scheme, you edit CSS and every page updates at once. If you want to fix a typo, you edit HTML without touching the layout logic. If you want to add a new interactive feature, you write JavaScript without risking the visual design. Mixing all three into inline styles and inline event handlers is technically possible, but it makes a codebase brittle: one small HTML edit can silently break styling or functionality that depended on the exact structure you just changed.
Think of a house under construction. HTML is the framing, the walls, floors, and rooms that determine what spaces exist and how they connect. CSS is the paint, flooring, and furniture layout, everything that determines how the space looks and feels. JavaScript is the electrical and plumbing systems, the parts that make lights turn on when you flip a switch and water flow when you turn a tap. You could technically build a house where the wiring is embedded in the drywall in a way that makes future repairs a nightmare, but professional builders keep these systems separable for exactly the same reason web developers keep HTML, CSS, and JavaScript separate.
Part 1: HTML — the structure layer
HTML, HyperText Markup Language, describes the meaning and hierarchy of content on a page. Every piece of text, every image, every button starts as an HTML element wrapped in a tag.
The document skeleton
Every HTML document follows the same basic shape, and browsers rely on this shape to know how to parse the file correctly.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Website</title>
</head>
<body>
<h1>Hello World</h1>
<p>This is a paragraph.</p>
</body>
</html>
Each line has a specific job. <!DOCTYPE html> tells the browser to render the page in standards mode according to the HTML5 specification, rather than a legacy quirks mode that older browsers used for pre-2000 pages, per MDN's DOCTYPE documentation. The <head> section holds metadata, the page title, links to CSS files, and character encoding declarations, none of which is visible content. The <body> section holds everything the visitor actually sees.
Common HTML elements
You do not need to memorize all 100-plus HTML elements to start building. A small, well-understood set covers the vast majority of real pages.
Table 1. Core HTML tags and what they render.
| Tag | Purpose | Example |
|---|---|---|
<h1> to <h6> |
Headings, largest to smallest | <h2>Subheading</h2> |
<p> |
Paragraph of text | <p>Body text here</p> |
<a> |
Hyperlink | <a href="/page">Click</a> |
<img> |
Image | <img src="pic.jpg" alt="description"> |
<button> |
Clickable button | <button>Submit</button> |
<div> |
Generic block container | <div>Content</div> |
<span> |
Generic inline container | <span>word</span> |
<form> |
Input form wrapper | <form>...</form> |
<input> |
Text field or control | <input type="text"> |
<ul> / <li> |
Bulleted list and items | <ul><li>item</li></ul> |
Why semantic HTML matters
A <div> and a <article> can look pixel-identical once styled, but they mean very different things to a browser, a screen reader, or a search engine crawler. Compare these two blocks:
<!-- Generic, no meaning -->
<div>Blog post title</div>
<div>Blog post content...</div>
<!-- Semantic, meaning is explicit -->
<article>
<h1>Blog post title</h1>
<p>Blog post content...</p>
</article>
The second version tells assistive technology, like screen readers used by blind and low-vision users, exactly what kind of content this is and how it's structured. The W3C Web Accessibility Initiative documents how semantic landmarks like <article>, <nav>, and <main> let screen reader users jump directly to the content they want instead of tabbing through an undifferentiated pile of <div> elements. Search engines use the same structural signals to understand what a page is actually about, which is part of why semantic markup is considered a baseline SEO practice, not an optional nicety.
H3: What does semantic HTML mean?
Semantic HTML uses tags that describe the meaning of their content, like <nav> for navigation or <article> for a self-contained piece of content, rather than generic tags like <div> that carry no inherent meaning. This helps browsers, screen readers, and search engines interpret a page correctly.
Part 2: CSS — the styling layer
CSS, Cascading Style Sheets, controls the visual presentation of HTML: colors, fonts, spacing, and layout. The "cascading" in the name refers to how style rules can come from multiple sources (browser defaults, external stylesheets, and inline styles) and combine according to a defined priority order called specificity, as detailed in MDN's cascade documentation.
CSS syntax basics
/* Target every h1 element */
h1 {
color: blue;
font-size: 32px;
margin-bottom: 20px;
}
/* Target elements with class="button" */
.button {
background-color: green;
padding: 10px 20px;
border-radius: 5px;
}
/* Target the single element with id="header" */
#header {
background-color: navy;
color: white;
}
Each rule pairs a selector, which decides what elements to target, with a declaration block, which decides what properties to change. Understanding selectors is the single highest-leverage CSS skill for a beginner because almost every layout bug traces back to a rule targeting the wrong element or being overridden by a more specific one.
Table 2. CSS selector types and specificity.
| Selector | Targets | Specificity weight |
|---|---|---|
h1 |
Every <h1> element |
Low (element) |
.button |
Every element with class="button" |
Medium (class) |
#header |
The single element with id="header" |
High (ID) |
h1, h2 |
Every <h1> and every <h2> |
Same as element |
style="..." (inline) |
Just that one element | Highest, aside from !important |
When two rules conflict, the browser does not pick randomly. It resolves the conflict using the CSS Cascading and Inheritance specification, which ranks rules by origin (browser default, then author stylesheet, then inline), then by specificity (ID beats class beats element), and finally by source order when specificity ties. This is why a beginner's most common CSS bug, "I changed the color but nothing happened," is almost always a specificity conflict rather than a syntax error.
Flexbox for one-dimensional layout
Flexbox arranges items along a single axis, either a row or a column, and is the tool most developers now reach for to center content or distribute space evenly.
.container {
display: flex;
justify-content: center; /* horizontal alignment */
align-items: center; /* vertical alignment */
height: 200px;
}
Anything inside .container is centered both horizontally and vertically, a task that required awkward positioning hacks before flexbox became broadly supported around 2015, per the CSS Flexible Box Layout specification.
Grid for two-dimensional layout
CSS Grid handles layouts that need control over both rows and columns simultaneously, which flexbox was never designed to do well.
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
}
This produces three equal-width columns with 20 pixels of space between each item, and the browser automatically wraps additional items into new rows. Think of flexbox as arranging books on a single shelf, one dimension to manage, while grid is arranging books in a full bookcase, rows and columns you control at the same time.
Responsive design with media queries
Media queries let a stylesheet apply different rules depending on the viewport width, which is how the same HTML produces a different layout on a phone versus a desktop monitor.
/* Desktop default */
.sidebar {
width: 300px;
display: flex;
}
/* Screens narrower than 768px */
@media (max-width: 768px) {
.sidebar {
width: 100%;
display: block;
}
}
Mobile traffic has made this technique non-optional. Google's own Search Central mobile-friendly guidelines treat mobile usability as a ranking input, and Google has used mobile-first indexing, crawling the mobile version of a site as the primary version, for the entire index since 2021. A site that only looks correct at desktop widths is now the exception, not the norm. For a deeper walkthrough of this exact topic, see the site's Responsive Design & Mobile-First guide.
H3: What is the difference between Flexbox and Grid?
Flexbox lays items out along one axis at a time, a row or a column, and is best for components like navigation bars or button groups. Grid controls rows and columns simultaneously and is best for full-page or full-section layouts. Many production interfaces use both: grid for the page skeleton, flexbox for the components inside it.
Part 3: JavaScript — the behavior layer
JavaScript is what turns a static page into an application. It runs inside the browser, reads and modifies the page in real time, and responds to whatever the user does.
JavaScript syntax basics
// A variable that can be reassigned
let name = "John";
// A constant that cannot be reassigned
const age = 25;
// A reusable block of logic
function greet(name) {
return "Hello, " + name;
}
greet("John"); // Returns: "Hello, John"
let and const were introduced in ECMAScript 2015 (commonly called ES6) specifically to fix scoping problems with the older var keyword, according to the ECMAScript 2015 language specification. In modern JavaScript, const is the default choice unless a variable genuinely needs to change value later, which makes code easier to reason about because a reader immediately knows which values are fixed.
DOM manipulation
The Document Object Model, or DOM, is the browser's live, in-memory representation of the HTML page, structured as a tree of nodes that JavaScript can read and change. The W3C DOM specification defines this as the standard interface that lets a script query, add, remove, or update any part of a page after it has loaded.
// Select an element by its id
const heading = document.getElementById("title");
// Change the visible text
heading.textContent = "New Title";
// Change a CSS property directly
heading.style.color = "blue";
// Add a CSS class
heading.classList.add("active");
This is the mechanism behind everything from a "like" button that updates instantly to a search box that filters results as you type. None of it requires reloading the page, because the DOM update happens entirely inside the browser's existing memory.
Events: reacting to the user
An event listener tells the browser "run this function whenever this specific thing happens."
const button = document.querySelector("button");
button.addEventListener("click", function () {
alert("Button clicked!");
});
Table 3. Common DOM events and when they fire.
| Event | Fires when | Typical use |
|---|---|---|
click |
User clicks an element | Buttons, links, toggles |
submit |
User submits a <form> |
Login, search, checkout forms |
change |
An input's value is committed | Dropdowns, checkboxes |
input |
An input's value changes on every keystroke | Live search, character counters |
keydown |
Any key is pressed | Keyboard shortcuts |
load |
A resource finishes loading | Running setup code after the page loads |
Fetch API: talking to a server
Modern JavaScript can request data from a server without reloading the page, using the fetch() function defined in the WHATWG Fetch Standard.
fetch("https://api.example.com/users")
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.log("Error:", error);
});
This pattern, requesting data in the background and updating the page without a full reload, is the technical foundation of AJAX-style interfaces (short for Asynchronous JavaScript and XML, though modern APIs almost always use JSON instead of XML). It's why a social media feed can load new posts as you scroll instead of forcing a page refresh for every batch of content.
H3: What is the DOM in JavaScript?
The DOM (Document Object Model) is the browser's tree-shaped, in-memory representation of an HTML page. JavaScript reads and modifies the DOM, not the original HTML file, so any change (adding an element, updating text, toggling a class) appears on screen instantly without a server round trip.
H3: Is JavaScript the same as Java?
No. Despite the similar name, JavaScript and Java are unrelated languages with different syntax, runtimes, and use cases. JavaScript runs primarily in browsers and Node.js for web development; Java is a separate general-purpose language used for enterprise backends, Android apps, and more. The naming overlap was a 1995 marketing decision, not a technical relationship.
Putting it together: a working todo app
The real payoff of learning all three languages is combining them into something interactive. Here's a minimal todo list that uses HTML for structure, CSS for styling, and JavaScript for behavior, all in roughly 40 lines.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Todo App</title>
<style>
.todo-item {
padding: 10px;
background: #f0f0f0;
margin: 10px 0;
border-radius: 5px;
}
.completed {
text-decoration: line-through;
color: gray;
}
</style>
</head>
<body>
<h1>My Todos</h1>
<input type="text" id="todoInput" placeholder="Add a todo...">
<button id="addButton">Add</button>
<ul id="todoList"></ul>
<script>
const input = document.getElementById("todoInput");
const button = document.getElementById("addButton");
const list = document.getElementById("todoList");
button.addEventListener("click", function () {
const text = input.value;
if (!text) return;
const li = document.createElement("li");
li.textContent = text;
li.className = "todo-item";
list.appendChild(li);
input.value = "";
li.addEventListener("click", function () {
li.classList.toggle("completed");
});
});
</script>
</body>
</html>
Walk through what happens when someone uses this page. The <input> and <button> elements exist because of HTML. The gray background, padding, and strikethrough on completed items exist because of the CSS block. Everything else, creating a new list item when the button is clicked, clearing the input, toggling the completed style when an item is clicked, is JavaScript reading and rewriting the DOM in real time. Remove any one of the three languages and the app breaks in a specific, predictable way: no HTML means nothing to see, no CSS means an unstyled but functional list, no JavaScript means a button that does nothing at all.
Common patterns you'll see in real codebases
Once the fundamentals click, most real-world JavaScript reduces to a handful of recurring patterns. Tools like HTMX and Vite build on these same three languages.
Form validation
const form = document.querySelector("form");
form.addEventListener("submit", function (event) {
event.preventDefault(); // stop the browser's default full-page submission
const email = document.querySelector("#email").value;
if (email.includes("@")) {
console.log("Valid email");
} else {
console.log("Invalid email");
}
});
event.preventDefault() is doing important work here. Without it, a <form> submission triggers the browser's default behavior, a full page reload that sends the form data to whatever URL is set in the form's action attribute. Calling preventDefault() lets JavaScript intercept the submission and validate or handle it without a reload, per the MDN Event interface documentation.
Conditional rendering
const loggedIn = true;
if (loggedIn) {
document.querySelector(".dashboard").style.display = "block";
document.querySelector(".login").style.display = "none";
} else {
document.querySelector(".dashboard").style.display = "none";
document.querySelector(".login").style.display = "block";
}
This is a manual, low-level version of what frameworks like React automate. React's component model handles this show/hide logic declaratively, but understanding the raw DOM version first makes it much easier to understand what a framework is actually doing under the hood rather than treating it as unexplainable magic. For a full comparison of frameworks that build on these fundamentals, see React vs Vue vs Svelte 2026.
Looping through data
const users = ["Alice", "Bob", "Charlie"];
users.forEach(function (user) {
console.log("Hello, " + user);
});
// Output:
// Hello, Alice
// Hello, Bob
// Hello, Charlie
forEach() is one of several array iteration methods introduced in ES5 (2009) specifically to replace error-prone manual for loops with clearer, purpose-built functions, as documented in the MDN Array.prototype.forEach reference. Beginners often start with a traditional for loop, which is fine, but production code overwhelmingly favors forEach(), map(), and filter() because they express intent more directly: "do this for every item" rather than "manage an index variable and increment it manually."
What browsers actually do with these three languages
It helps to understand what happens the instant a browser receives an HTML file, because it explains several behaviors that otherwise seem mysterious, like why a <script> tag's placement in the document matters.
The browser first parses HTML into the DOM tree described earlier. When it encounters a <link> to a CSS file, it fetches that file and parses it into a second tree called the CSSOM (CSS Object Model). The browser then combines the DOM and CSSOM into a render tree, which it uses to calculate the exact size and position of every visible element (a step called layout or reflow), and finally paints pixels to the screen, per the rendering pipeline described in Google's web.dev rendering performance documentation. JavaScript can pause this entire pipeline: by default, a <script> tag blocks HTML parsing at the point it appears, which is why many developers place scripts at the end of the <body> or use the defer attribute, so the page's visible content appears before any JavaScript runs.
This pipeline also explains why heavy, poorly optimized JavaScript makes a page feel sluggish even when the visual design is simple. Every DOM change potentially triggers a new layout and paint cycle, and doing this too frequently, for example updating styles inside a tight loop instead of batching changes, is a common performance bottleneck. The site's Web Performance Optimization guide covers Core Web Vitals and concrete techniques for keeping this pipeline fast as a project grows beyond toy examples.
What people get wrong about learning these three languages
"I need to master HTML and CSS before touching JavaScript"
Sequential mastery sounds tidy, but it's not how most working developers actually learned. A more effective approach is building small projects that use all three languages together from day one, even imperfectly, because the languages only make sense in relation to each other. A <div> styled by CSS and then manipulated by JavaScript teaches you more about all three than memorizing 200 CSS properties in isolation ever will.
"Frameworks make fundamentals obsolete"
Frameworks like React, Vue, and Svelte compile down to the same HTML, CSS, and JavaScript primitives covered in this guide, they just automate the repetitive parts. A developer who understands the DOM, the event loop, and CSS specificity debugs framework issues far faster than one who only knows the framework's API, because framework error messages routinely reference these underlying concepts directly. The site's Complete Web Development Learning Path 2026 lays out where frameworks fit relative to fundamentals in a realistic learning timeline.
"CSS is simple, it's just colors and fonts"
CSS has its own execution model, the cascade, specificity, and layout algorithms like flexbox and grid, that behaves closer to a programming language than a simple styling checklist. Experienced developers still hit unexpected specificity conflicts and layout quirks regularly. Treating CSS as a serious language rather than an afterthought avoids a huge share of the debugging time beginners lose to "my style isn't applying and I don't know why."
"JavaScript errors mean the whole page is broken"
A JavaScript error typically stops only the script it occurred in, not the entire page. HTML and CSS that were already parsed and painted remain visible; a broken addEventListener call just means that specific interaction won't work. Understanding this helps with debugging: open the browser's developer console (usually F12) and read the actual error message and line number before assuming the entire page has failed.
Frequently asked questions
Q: Do I need to learn HTML, CSS, and JavaScript in a specific order? A: Most curricula teach HTML first because it defines the content JavaScript and CSS act on, but there's no strict requirement. Many effective learners study small amounts of all three simultaneously through project-based tutorials rather than fully finishing one language before starting the next.
Q: How long does it take to learn HTML, CSS, and JavaScript fundamentals? A: Timelines vary widely by prior experience and study hours, but a common pattern in coding bootcamp curricula is 4 to 12 weeks of consistent, focused practice to reach comfortable fundamentals, followed by months of project work to build real proficiency. The Complete Web Development Learning Path 2026 breaks this down phase by phase.
Q: Can I build a real website with just HTML, CSS, and JavaScript, no framework? A: Yes. Frameworks add convenience for large, complex applications with many interacting components, but a static portfolio site, a landing page, or a small interactive tool needs nothing beyond vanilla HTML, CSS, and JavaScript.
Q: What's the difference between JavaScript and TypeScript? A: TypeScript is a superset of JavaScript that adds optional static typing, meaning you declare the expected type of a variable and the compiler flags mismatches before the code ever runs. It compiles down to plain JavaScript, so browsers still only ever execute JavaScript.
Q: Why does my CSS change not apply to an element? A: The most common causes are a more specific selector overriding your rule elsewhere in the stylesheet, a typo in the class or ID name, or the browser caching an old version of the file. Opening the browser's developer tools and inspecting the element's "Computed" styles panel shows exactly which rule is winning and why.
Q: What does const mean in JavaScript, and how is it different from let?
A: const declares a variable whose binding cannot be reassigned after creation, while let declares a variable that can be reassigned. Neither prevents changing the contents of an object or array assigned to the variable, only reassigning the variable itself to a new value.
Q: Is HTML a programming language?
A: No. HTML is a markup language, it describes structure and content but has no logic, loops, or conditionals. CSS is also not a general-purpose programming language, though newer features like CSS custom properties and calc() add limited computational ability. JavaScript is the only one of the three that qualifies as a full programming language.
Q: What is the box model in CSS? A: The CSS box model describes how every element's total size is calculated: content, then padding around the content, then a border around the padding, then margin outside the border. Misunderstanding the box model, especially forgetting that padding and border add to an element's width by default, is one of the most common sources of unexpected layout sizes for beginners, as detailed in MDN's box model documentation.
Q: Do I need to learn jQuery before JavaScript? A: No, and this advice has flipped over the past decade. jQuery was created to smooth over inconsistent browser APIs and DOM manipulation that were painful in the mid-2000s. Modern JavaScript and modern browsers have largely closed that gap natively, so current curricula, including MDN's own learning path, teach vanilla JavaScript first and treat jQuery as optional legacy knowledge for maintaining older codebases.
The takeaway
HTML, CSS, and JavaScript are not three unrelated skills to check off a list, they are three layers of the same system, each responsible for a different job: structure, presentation, and behavior. The fastest path to real competency is building small projects that force all three to work together, like the todo app above, rather than trying to fully master one language in isolation before touching the next. Once the DOM, the cascade, and event handling actually click, frameworks stop looking like magic and start looking like automation built on exactly the fundamentals covered here.
Read next:
Follow new articles
Add SciHub101 to your feed reader to see new science and technology stories.
About the Author
SciHub101 is an independent science and technology publication founded and edited by Buğra Sözeri, a software engineer and app developer based in Türkiye. AI tools assist with drafting and research. Source documentation in the existing archive is uneven, and articles are being reviewed and corrected. The Editorial Team byline identifies editorial responsibility; it does not certify specialist or independent human review. Where we compare products, anything built by our own team is labelled as such — see the editorial guidelines and About page for how corrections and disclosures work.
Related Articles

Complete Web Development Learning Path 2026 Roadmap
6-phase learning roadmap for web development. Timeline, costs, realistic expectations, job prospects. Beginner to employed.

React vs Vue vs Svelte 2026 — Which Framework to Learn?
Compare React, Vue, Svelte side-by-side. Job market demand, learning curve, salary, real-world usage. Which one to choose.

What Is HTMX? Hypermedia for Modern Web
HTMX explained: how this 14KB library lets you build dynamic web apps with HTML attributes instead of a JavaScript framework, plus how it actually works.

CSS Flexbox and Grid — Complete Layout Guide
Master CSS Flexbox and Grid with practical code examples. Learn when to use each, key properties, and common layout patterns every developer needs.

Tailwind CSS Explained — Why It Dominates Web Design 2026
Tailwind CSS for beginners: why utility-first CSS won, common patterns, integration with React/Next.js, gotchas. The CSS framework everyone uses in 2026.

Next.js vs React 2026 — Which Should You Learn First?
Next.js is a framework built on React, not a rival. What each does, Server Components, App vs Pages Router, and when to pick which, per the official docs.