The behavior layer of the web — linking scripts, reading the console, writing your first statements, and watching HTML, CSS, and JavaScript work together
Up to this point, the websites you have built respond to users the way a printed book responds to a reader: they display information, they follow links, they show images, but they do not change based on what the user does while reading. A form submits. A link navigates. But nothing happens in place, nothing updates without a full page reload, and nothing responds to a user action in the moment.
JavaScript changes this. JavaScript is the language that makes pages respond, update, and behave dynamically while a user is looking at them. When a user clicks a button and a message appears without the page reloading, that is JavaScript. When a navigation menu expands on a small screen, that is JavaScript. When a form shows an error message next to the field that needs attention, that is JavaScript. When a list of items filters as a user types, that is JavaScript.
This chapter introduces JavaScript as the behavior layer of the browser. It explains what JavaScript is, how it fits alongside HTML and CSS, how to connect a JavaScript file to an HTML page, how to use the browser console to understand what your code is doing, and how to write and read the most basic JavaScript statements. It introduces common beginner errors with practical debugging guidance, and it closes with a first small interactive page that brings all three languages together.
This is a beginning. The chapters that follow will teach variables, functions, events, the DOM, logic, loops, and forms. This chapter's job is to make JavaScript feel approachable, understandable in its purpose, and connected to the real work of building websites.
A button that changes a message when clicked. A menu that opens on a phone screen. A form that warns you before you submit it with an empty field. None of these require the page to reload. What language makes a page change while a person is still looking at it? By the end of this chapter, you will understand the answer well enough to write — and link, and run, and debug — a small piece of it yourself.
By the end of this chapter, you should be able to:
<script> element.<script> elements are typically placed at the end of <body>.console.log() and simple dialog functions to produce visible output during development.<script> element; where to place it; the JavaScript file itself; project structure with a js/ folderconsole.log(); reading error messages; the interactive consolealert(), confirm(), and prompt() at an introductory level; why console.log() is the better development habitDOMContentLoadedJavaScript is a programming language that runs in the browser. Unlike HTML, which describes the structure of a document, and CSS, which describes its visual presentation, JavaScript describes behavior: what should happen, when it should happen, and what should change.
JavaScript was created in 1995 by Brendan Eich while working at Netscape Communications. It was designed to add interactivity to web pages that were, at the time, entirely static documents. Despite its early origins and occasional awkward history, JavaScript has become one of the most widely used programming languages in the world. It runs in every major web browser without any installation. It is the only programming language that runs natively in the browser. No other language can do what JavaScript does in the browser without being compiled into JavaScript or running on a server.
JavaScript is not Java. The two languages share the first four letters of their names and superficially similar syntax in some areas, but they are distinct languages with different histories, different uses, and different design philosophies. The similar name is a historical marketing decision from the 1990s, not a technical relationship. You will not need Java for this course.
JavaScript is a scripting language. In traditional programming, a program is compiled into machine code before it runs. In scripting, code is read and executed more directly. Browsers contain a JavaScript engine — a program that reads JavaScript code and runs it. The V8 engine in Chrome and Edge, the SpiderMonkey engine in Firefox, and the JavaScriptCore engine in Safari all do this work invisibly whenever a page with JavaScript is loaded.
JavaScript is also a dynamic language. It is flexible about types, forgiving about some syntax details, and can be written in many styles. This flexibility is both a strength and a source of confusion for beginners. This textbook takes a careful, explicit approach: it will explain what each piece of code means, avoid shortcuts that obscure logic, and build habits that make code readable and maintainable.
In the context of web development, JavaScript's primary job is to interact with the browser and the page. It can read what is on the page, change what is on the page, respond to what users do, and communicate with servers. These abilities make it the foundation of every interactive website on the web.
You have already learned that web pages are built from three layers, each with a distinct job.
These three layers are separate concerns. This separation is intentional and valuable. A page's structure can be understood without knowing its styles. A page's styles can be updated without touching its structure. A page's behavior can be changed without rewriting the underlying HTML. Keeping these layers clean and independent makes websites easier to read, maintain, and debug.
<nav> element..is-open defines what the "open" state looks like.is-open class on the navigation list. It does not write any color values or define any HTML — it only manages the transition between states.Notice that the JavaScript does not write color values. It does not define the HTML structure. It manages behavior: it listens for the click, and it adds or removes a class. The visual change happens because CSS responds to that class. This is the right pattern.
This separation also means that a page should still be usable even if JavaScript is unavailable or slow to load. Good web development treats JavaScript as an enhancement to an already functional HTML and CSS foundation, not a replacement for it.
Just as CSS is linked from an external file, JavaScript is typically stored in an external .js file and linked to the HTML page.
JavaScript is linked to an HTML page using the <script> element. The <script> element takes a src attribute whose value is the path to the JavaScript file, just as <link> takes an href to a CSS file.
<script src="js/main.js"></script>
The placement of the <script> element in the HTML document matters. JavaScript code can interact with the page's HTML elements, but it can only interact with elements that have already been loaded by the browser. If JavaScript runs before the page has finished loading its HTML, the code will try to find elements that do not yet exist.
The simplest and most reliable solution for beginners is to place the <script> element at the end of the <body> element, just before the closing </body> tag.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Page</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h1>Welcome</h1>
<p>This is my page.</p>
<!-- JavaScript goes at the end of the body -->
<script src="js/main.js"></script>
</body>
</html>
By placing the script at the end of the body, all of the HTML elements have been created and loaded before the JavaScript runs. This avoids the common beginner problem of JavaScript trying to select elements that do not exist yet.
There is a more modern approach using the defer attribute on a <script> element in the <head>, which tells the browser to load the script in parallel but only execute it after the HTML is fully parsed. You will encounter defer in later courses. For now, placing <script> at the end of <body> is clear, reliable, and correct.
The JavaScript file is a plain text file saved with a .js extension. It contains JavaScript code, not HTML. There are no tags in a .js file. JavaScript has its own syntax.
A minimal JavaScript file might look like this:
// This is a comment in JavaScript
console.log("The script is running.");
This file does very little: it runs a single line of code that sends a message to the browser console. The console is a place where JavaScript can display information for developers. Users do not see it. You will learn to use it in the next section.
A clean project folder with HTML, CSS, and JavaScript looks like this:
The js/ folder is conventional but not required. For small projects, some developers place main.js at the project root. For this textbook, keeping JavaScript in a js/ folder is the recommended practice. It mirrors the way CSS is kept in a css/ folder and reinforces the idea of organized, layered projects.
The browser console is one of the most important tools a JavaScript developer uses. It is a panel inside the browser's developer tools where:
console.log()You opened the developer tools in Chapter 4. The console is one of the tabs inside that panel.
To open the developer tools and find the console:
console.log() is a JavaScript statement that sends a message to the console. It is the most common tool for checking whether your JavaScript is running and what values your code is working with.
console.log("Hello from JavaScript.");
console.log(42);
console.log("The page has loaded.");
Each call to console.log() prints one line to the console. The message in parentheses is what gets printed.
This may seem like a small thing, but console.log() is genuinely one of the most useful techniques in web development debugging. Professional developers use it constantly to understand what their code is doing, what values variables hold, and at what point something is going wrong.
When JavaScript code contains a mistake — a misspelling, a missing parenthesis, a reference to something that does not exist — the browser will not just ignore the error. It will log a red error message to the console. That message includes:
Uncaught ReferenceError: consle is not defined
at main.js:3
This message tells you exactly where to look. In this case, consle is a typo for console. The error is on line 3 of main.js. Learning to read console error messages is a critical skill. They are not failures — they are the browser's attempt to tell you what went wrong and where. Beginning developers sometimes feel discouraged by red error messages. Experienced developers feel relieved: a clear error message is far easier to fix than mysterious behavior that produces no message at all.
You can type JavaScript directly into the console and press Enter to run it immediately. This is useful for quick experiments. Try typing the following in the console on any web page:
2 + 2
The console will show 4. Try:
document.title
The console will show the title of the current page. The console is a live JavaScript environment connected to the page you are viewing. You will use this throughout the course to test small pieces of code before putting them in files.
JavaScript code is made of statements. A statement is one complete instruction. When the JavaScript engine runs your code, it reads and executes statements in order, one at a time, from top to bottom (with exceptions you will learn about later, such as functions and events).
Each line in the following code is a statement:
console.log("Line one.");
console.log("Line two.");
console.log("Line three.");
JavaScript statements end with a semicolon (;). Semicolons are technically optional in many cases because JavaScript has a feature called automatic semicolon insertion that adds them in certain situations. However, writing your semicolons explicitly is a better habit. It prevents a small category of subtle bugs and makes your intentions clear. All examples in this textbook use explicit semicolons.
Comments are notes written in the source code that the JavaScript engine ignores. They exist for human readers: you, your teammates, your future self revisiting the code six months later.
There are two types of comments in JavaScript. A single-line comment begins with // and extends to the end of that line:
// This is a single-line comment.
console.log("This runs."); // This comment is after the statement.
A multi-line comment begins with /* and ends with */. Everything between those markers is a comment, even if it spans multiple lines:
/*
This is a multi-line comment.
It can span as many lines as needed.
It does not run as code.
*/
console.log("This still runs.");
Good comments explain why something is done, or note something that might not be obvious to a reader. They do not simply restate what the code says.
// Redundant and unhelpful:
// Log a message
console.log("Hello.");
// Useful:
// Confirm the script loaded before attempting DOM operations.
console.log("Script loaded successfully.");
Writing clear comments is part of writing readable, maintainable code. You will develop better instincts for when and how to comment as your programs grow larger.
JavaScript executes statements in order, from top to bottom, unless something changes that order. Understanding execution order is fundamental to understanding how your programs behave.
Consider this file:
console.log("First");
console.log("Second");
console.log("Third");
The console output will be:
First Second Third
That seems obvious. But consider:
console.log("First");
// console.log("Second");
console.log("Third");
The second statement is commented out, so it does not run. The console output is:
First Third
And consider:
console.log("A");
function greet() {
console.log("Hello from greet.");
}
console.log("B");
The output here is:
A B
The greet() function is defined but never called. Defining a function does not run the code inside it. Calling a function does. You will learn about functions in Chapter 20, but the principle matters now: code only runs when the JavaScript engine reaches it in the execution sequence, or when it is triggered by something like a function call or an event.
This also explains why placing the <script> element at the end of <body> matters. The browser loads and executes JavaScript as soon as it encounters a <script> element. If that element appears in the <head>, the script runs before any of the body content has been loaded — which means the HTML elements do not yet exist in memory, and any JavaScript that tries to find them will fail.
Unless you understand defer or event-based initialization, place your <script> element at the end of <body> and write your code in the order you want it to execute.
Before diving into the full power of JavaScript's interaction with the page, it is worth knowing a few very simple ways that JavaScript can produce visible output. These are useful for early learning and quick experiments, though you will rarely use them in production websites.
alert() displays a browser dialog box with a message and an OK button. It pauses the page until the user dismisses it.
alert("Welcome to this page.");
When the browser runs this line, a small dialog box appears with the text "Welcome to this page." and an OK button. The page waits until the user clicks OK before continuing.
alert() is one of the oldest JavaScript features. It is rarely used in modern websites because it interrupts the user experience and looks unprofessional. However, it is useful for early experiments because it gives immediate visible proof that JavaScript is running.
confirm() displays a dialog box with a message and two buttons: OK and Cancel. It returns a value depending on which button the user clicks. You will use return values more after Chapter 20.
confirm("Do you want to continue?");
prompt() displays a dialog box with a text field. The user can type a value and click OK. Again, you will learn how to use the value it returns after Chapter 20.
prompt("What is your name?");
For debugging and development, console.log() is far more useful than alert(). It does not interrupt the page. It shows values in context. It can display objects and arrays. Get in the habit of using console.log() for development feedback, and reserve alert() for only the earliest experiments.
There is an important relationship between JavaScript and the process of loading an HTML page. Understanding this relationship helps you avoid a very common category of beginner errors.
When a browser loads a web page, it does the following work in roughly this order:
<link> elements and downloads CSS files.<script> elements and downloads and executes the JavaScript files.load event fires.The critical point for beginners is step 5. If the <script> element appears at the top of the page, in the <head>, the JavaScript runs at that moment — before the <body> content has been parsed. The JavaScript cannot interact with elements that do not yet exist in memory.
Placing <script> at the end of <body> ensures that all HTML has been parsed before the script runs. This is the approach used throughout this textbook.
<body> <h1>My Page</h1> <p>Content here.</p> <script src="js/main.js"></script> </body>
When the browser reaches the <script> tag at the bottom of the body, all of the HTML above it has been loaded. Any JavaScript that looks for page elements will find them.
There is another pattern you may encounter in examples on the web:
document.addEventListener("DOMContentLoaded", function() {
// Code here runs after the page has loaded.
});
This approach wraps code in a function that only runs after the page's HTML structure has been fully loaded. It allows a <script> in the <head> to safely interact with page elements. You will learn about events and event listeners in Chapter 21. For now, using <script> at the end of <body> is simpler and achieves the same result.
The three languages of the browser are most powerful when they work together as intended: HTML for structure, CSS for presentation, JavaScript for behavior. Let's look at a complete small example to see this collaboration in practice.
Build a page with a heading, a short message, and a button. When the user clicks the button, the message changes.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Button Demo</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<main>
<h1>Button Demo</h1>
<p id="status-message">The button has not been clicked yet.</p>
<button id="change-button">Click me</button>
</main>
<script src="js/main.js"></script>
</body>
</html>
Notice two attributes in this HTML: id="status-message" on the paragraph and id="change-button" on the button. IDs give JavaScript a way to find specific elements on the page.
/* css/main.css */
body {
font-family: Georgia, serif;
max-width: 600px;
margin: 2rem auto;
padding: 0 1rem;
color: #1a1a1a;
}
h1 {
font-size: 2rem;
margin-bottom: 1rem;
}
p {
font-size: 1.125rem;
margin-bottom: 1.5rem;
}
button {
background-color: #1a5276;
color: white;
border: none;
padding: 0.75rem 1.5rem;
font-size: 1rem;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #154360;
}
// js/main.js
// Step 1: Find the elements we need to work with.
var button = document.getElementById("change-button");
var message = document.getElementById("status-message");
// Step 2: Tell the button what to do when clicked.
button.addEventListener("click", function() {
message.textContent = "The button has been clicked!";
});
This JavaScript does three things:
Do not worry about fully understanding this JavaScript yet. The details of getElementById, addEventListener, and textContent will be explained carefully in Chapters 21 and 22. What matters now is seeing the pattern: HTML defines the elements and their IDs, CSS styles how those elements look, and JavaScript uses the IDs to find the elements and changes them when the user acts. Each language does its part. The layers remain clean.
Before clicking: The page shows a heading, a paragraph that reads "The button has not been clicked yet," and a blue button.
After clicking: The paragraph now reads "The button has been clicked!" The button remains where it is. The page never reloaded. The change happened instantly, in place.
This is the fundamental pattern of JavaScript interaction on the web.
JavaScript code that contains mistakes does not always stop working entirely — sometimes it simply behaves unexpectedly. But many errors cause the browser to stop executing a script and log an error message to the console. Learning to recognize common errors will save you significant time.
JavaScript appears to do nothing. No output in the console, no interaction. The src path in the <script> element is wrong, and the browser cannot find the file.
<script src="main.js"></script>Right
<script src="js/main.js"></script>
How to check: Open the Network tab in developer tools and reload the page. If the JavaScript file shows a red 404 error, the path is wrong.
Red error in the console: Uncaught TypeError: ... is not a function or Uncaught ReferenceError: ... is not defined. A word is misspelled. JavaScript is case-sensitive.
Console.log("Hello."); // Capital C is wrong
consol.log("Hello."); // Missing 'e'
console.Log("Hello."); // Capital L is wrong
Right
console.log("Hello.");
How to check: Look at the error message and the line number it points to. Read that line carefully, character by character.
Red error in the console: Uncaught SyntaxError: Unexpected token. A string literal is not properly closed.
console.log("Hello.); // Missing closing quote
console.log('Hello."); // Mismatched quotes
Right
console.log("Hello.");
console.log('Hello.');
How to check: Strings must open and close with the same type of quote mark. Most code editors color string literals, which makes this easier to spot visually.
Uncaught SyntaxError with a message about an unexpected token, often on a line that looks fine. An opening parenthesis, closing parenthesis, opening brace, or closing brace is missing. JavaScript often does not notice this until a later line, so the error may appear several lines after the actual mistake.
console.log("Hello."; // Missing closing parenthesis
Right
console.log("Hello.");
How to check: Many code editors highlight matching pairs of parentheses and braces. Using a good editor helps catch these immediately.
Uncaught TypeError: Cannot read properties of null — the code finds null instead of a real element. The JavaScript tries to find an HTML element by ID before the HTML has loaded.
<head> <script src="js/main.js"></script> <!-- Runs before body content loads --> </head> <body> <button id="my-button">Click me</button> </body>Right
<body> <button id="my-button">Click me</button> <script src="js/main.js"></script> <!-- Runs after body content loads --> </body>
How to check: Always place <script> at the end of <body> until you are comfortable with the defer attribute or DOMContentLoaded events.
Uncaught TypeError: Cannot read properties of null. The ID in the JavaScript does not exactly match the ID in the HTML.
<button id="submitButton">Submit</button>Wrong
var btn = document.getElementById("submit-button"); // Wrong: hyphen vs. camelCase
Right
var btn = document.getElementById("submitButton"); // Matches the HTML exactly
How to check: IDs are case-sensitive and must match exactly. Copy-paste the ID from the HTML rather than retyping it.
Errors appear in the console that do not seem related to your code. The console accumulates messages. Old messages from previous page loads or other experiments may still be visible.
How to fix: Click the clear button in the console (usually a circle-with-slash icon), or press Ctrl+L (Windows/Linux) or Cmd+K (Mac) to clear it. Then reload the page.
<script> element and its src attribute. Placing <script> at the end of <body> ensures the HTML exists before the script runs. JavaScript files conventionally live in a js/ folder.console.log(), shows error messages with file names and line numbers, and accepts JavaScript typed directly for quick experiments.// and multi-line comments are wrapped in /* */. Good comments explain why, not what.alert(), confirm(), and prompt() produce simple dialog-box output, useful for early experiments. console.log() is the better habit for ongoing development work.<head> run before the body exists, which is why this textbook places <script> at the end of <body>. DOMContentLoaded offers an alternative for later courses.<script src="path/to/file.js"></script>.console.log().//. Multi-line comments are wrapped in /* */.;) used to end JavaScript statements. Technically optional in many cases due to automatic semicolon insertion, but explicitly written semicolons are the recommended practice.<script> in the <head>.null because a selected element was not found.null.Read each example carefully and answer the questions that follow.
console.log("Starting.");
console.log("Processing.");
console.log("Done.");
//?// This script checks whether the page loaded.
console.log("Page script is running.");
// alert("This is a test.");
console.log("End of script.");
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test Page</title>
<script src="js/app.js"></script>
</head>
<body>
<h1 id="main-heading">Hello</h1>
</body>
</html>
// js/app.js
var heading = document.getElementById("main-heading");
console.log(heading);
<script> element placed in this page?console.log("Before the function.");
function showMessage() {
console.log("Inside the function.");
}
console.log("After the function.");
For each code block, predict what the console will show, what the browser will display, or what error will occur.
Console.log("Hello.");
console.log("One");
console.log("Two")
console.log("Three");
No error is expected — what does the output look like?
// console.log("A");
console.log("B");
// console.log("C");
console.log("D");
<body>
<p id="note">Read this.</p>
<script src="js/main.js"></script>
</body>
var note = document.getElementById("note");
console.log(note);
What will console.log(note) show in the console?
alert("Welcome.");
console.log("Script complete.");
What happens first: the alert dialog or the console message?
Each example below contains an error. Identify what the error is, explain why it causes a problem, and write the corrected version.
consol.log("Script loaded.");
console.log("Hello world.);
<head>
<script src="js/main.js"></script>
</head>
<body>
<button id="go-button">Go</button>
</body>
var btn = document.getElementById("go-button");
btn.addEventListener("click", function() {
console.log("Clicked.");
});
<p id="StatusMessage">Loading...</p>
var msg = document.getElementById("statusmessage");
console.log(msg);
console.log("Start.");
console.log("Middle."
console.log("End.");
index.html and a js/main.js file. Link the script at the end of <body>. In main.js, write three console.log() statements with different messages. Open the page in a browser and verify that all three messages appear in the console.console.log() lines labeled A, B, C, and D. Comment out lines B and D, reload, and verify that only A and C appear. Then uncomment line D and reload again to confirm the updated output.Console.log("Done."). Predict the error before loading the page. Then load it, compare the actual error to your prediction, fix it, and reload.<script> in the <head> of a page that tries to select a paragraph by ID and log it. Observe the console output. Then move the script to the end of <body>, reload, and compare the results. Write a brief explanation of the difference.<title>, a <link> to an external stylesheet, a <script> at the end of <body>, a heading with a name, a short descriptive paragraph, a list of three interests or facts, and one <button> with an ID.console.log() statements, and an event listener on the button that logs a message to the console when clicked.| Criterion | Points |
|---|---|
| Valid HTML structure with correct DOCTYPE and tags | 15 |
| CSS file correctly linked; styles applied | 15 |
JavaScript file correctly linked at end of <body> | 15 |
Three meaningful console.log() messages in the JavaScript | 20 |
| Button with event listener that logs a message on click | 20 |
| No errors in the browser console | 10 |
| Clean file organization with correct folder structure | 5 |
| Total | 100 |
console.log() statements that log the current date and time using new Date().JavaScript does not remove the need for accessible HTML. It adds to it. Before adding JavaScript to any page, the HTML and CSS should already be accessible. Then JavaScript can enhance the experience without breaking it. Review your Mini-Project page for the following:
<title>?<h1> correctly?<button> element, not a <div> or <span> styled to look like a button?This last point matters. JavaScript should enhance a working page, not be required for the page to have any content at all. A page that shows a blank screen when JavaScript is disabled has been built on an unstable foundation.
These questions draw on earlier chapters as well as Chapter 19.
js/scripts.js to an HTML page.<script> element inside the <head> of the page. What problem might this cause, and what is the simplest fix?console.log() do? Where does its output appear?<link> element is placed in the <head>. In JavaScript, the <script> element is placed at the end of <body>. Explain why these are placed differently.Console.log("Hello.") and nothing appears in the console. A red error message appears instead. What is wrong?css/ folder, and one JavaScript file in a js/ folder? Draw the folder tree.Uncaught TypeError: Cannot read properties of null (reading 'addEventListener'). What is likely causing this error?<script> elements are typically placed at the end of <body>.<script> element.console.log() to display output.Chapter 20 introduces the building blocks of JavaScript programs: values, variables, expressions, and functions. You will learn how to store information in variables using let and const, how to work with strings, numbers, and Booleans, how to build and evaluate expressions, how to write reusable functions, and how to connect these tools to real page behavior. Chapter 20 builds the vocabulary you need to write programs that do more than print messages — programs that compute, decide, and act.