Content updated
By the end, you can…
- Describe a bug using expected and actual behavior.
- Use HTML, styles, and runtime messages to investigate a cause.
- Test a small repair without losing behavior that already works.
Describe the difference before editing
A bug is a difference between what you expected and what actually happened. Start with one action you can repeat, not the whole page at once.
A quick visual example
Action: click Save
A confirmation appears.
The old message stays.
A useful bug report: “After Save, I still see Not saved.”
- 1Observe
- 2Investigate
- 3Change one thing
- 4Test again
Predict what one small change should do, then test it. If you change several things together, you will not know which one helped. Keep a copy or use undo when an experiment makes things worse.
When a style seems to do nothing
A valid CSS rule can match nothing. Compare the class in this HTML with the CSS selector, then try the repair button.
Interactive illustration · try it
<p class="note">
Remember to save
</p>
.notes {
background: #fef3c7;
padding: 16px;
}Remember to save
No match: the text keeps its default appearance.
Compare note in the HTML with notes in the CSS. One extra letter matters.
On your own page, use Inspect on the element. Styles or Rules shows matching declarations; Computed shows the resulting value. A crossed-out declaration usually lost to another rule. If the whole page has no styling, check that the stylesheet loaded before changing selectors.
Before you try: running, pausing, and stepping
A statement is an instruction in your code, such as changing a paragraph’s text. Running (or executing) code means carrying out those instructions. A runtime error happens while the code is running and can stop it before later instructions are reached.
Pausing gives you time to inspect the current values without running the next instruction. In the example below, the highlighted statement has not run yet when the script is paused. Stepping means running that statement, then pausing again so you can see what changed.
Use Run automatically to start fresh and watch the script run. Use Start step-by-step to start fresh and pause before the first instruction.
Once paused, Run next statement advances one instruction. Resume automatically lets the remaining code run without clicking through each step. These two controls are disabled when there is no paused code to resume.
Interactive illustration · try it
Start from the beginning. Watch all three instructions run without another click.
Here, output is the paragraph shown as “On the page” below.
let count = 1;count = count + 1;output.textContent = count;Ready. No instructions have run yet.
A simplified simulation of these three instructions. Each numbered example resets its own starting point.
A callback is a function that runs later in response to something, such as a click. Registering a click listener does not run its callback immediately: the example waits for you to click Save in the live page.
When the script stops
An early error can prevent later statements from running. Predict where this script stops, then trace it.
Live code · run or step through
The goal: show Ready after setup, then Saved when you click Save. This HTML is loaded before the script runs.
<button id="save">Save</button>
<p id="message">Not ready</p>Broken: #save-now does not match any element in this HTML.
const button = document.querySelector("#save-now");const message = document.querySelector("#message"); button.addEventListener("click", () => { message.textContent = "Saved";}); message.textContent = "Ready";Try Start step-by-step to watch what changes after each instruction.
- button
- Not assigned yet
- message
- Not assigned yet
Run a version to open its page here.
What each statement does
Follow the execution order: find the elements, prepare the click, then update the page.
- Line 1
Find the Save button
#savelooks forid="save". The broken selector,#save-now, finds nothing.Result:
buttonholds the element ornull(no match). No error yet. - Line 2
Find the message paragraph
#messagematches the paragraph in both versions.Result:
messageholds that paragraph. Its text is still Not ready. - Line 4
Prepare a response to a click
addEventListenerregisters the callback. It does not run the callback yet.Broken · stops here
nullhas noaddEventListenermethod. An error stops this run; line 8 is never reached.Corrected · continuesThe real button gets a listener. The callback waits for a click while setup continues to line 8.
- Line 8
Show that setup is complete
In the corrected version, the paragraph changes from Not ready → Ready.
Next: the script waits for you to click Save. Line 5 has not run.
- Line 5
After a click: run the callback
Click Save in the corrected live page. The callback changes the paragraph from Ready → Saved.
In step mode: it pauses before this update. Choose Run next statement to execute it.
This teaching debugger executes the shown example with pause instructions in an isolated page. It is not the browser’s DevTools and cannot debug arbitrary code. Each run or version change starts fresh. Saved changes the demo text; it does not save a file.
In a local project, open the developer tools Console and reproduce the problem. Start with the first relevant error and follow its file-and-line link. A null error is a clue to trace a missing value, not proof of one particular cause. The practice has a runtime message panel rather than a full console.
When the code runs but the page stays the same
Click Add a star twice. Watch the stored number and the displayed number separately. Then include the display update and try again.
Interactive illustration · try it
starsstars = stars + 1;
// No statement updates the page here.Stored: 0. Shown: 0. Only the value in memory changes.
Switching modes starts both numbers at zero. This example uses a star counter, separate from the practice.
A variable and the page are separate. Trace which statements change each one, and whether they run on every click. After a repair, test repeated actions and reset behavior too. Fixing an early error can reveal another bug that was previously hidden.
Your turn: fix a broken counter
Fix this page is a separate interactive practice. You will repair a counter with broken styling and button behavior. The HTML is provided; you edit its CSS and JavaScript and test your changes in a live preview.
- Run the supplied code and try the counter. Describe what you expected and what actually happened.
- Investigate one symptom. If you get stuck, open a hint for a question that points you toward what to inspect.
- Make one small change, then use Check solution to see which checks pass. Repeat until the counter works, including repeated clicks and reset.
The practice uses different names from the lesson examples, so compare its HTML and code rather than copying a selector from here. Hints guide your investigation; the explained solution shows the complete repair when you are ready to review it.
Go to the source
Examples are authored for Tuklas and checked with code and reference documentation. This is not a claim of independent human review. Suggest a correction.