A Repeatable Routine for Debugging Front-End Bugs
Most front-end bugs are not mysterious. They feel mysterious because we start changing code before we know what the browser actually did. A repeatable routine, from inspecting the live result to isolating a minimal case, saves more time than any single clever trick. This is the sequence we would suggest, along with a few recent DevTools additions that make parts of it easier.
1. Look at the DOM, not the source
View Source shows the file as the server delivered it. The Elements panel shows the DOM the browser built, and the two can differ. Browsers repair broken markup, so a mismatched heading tag gets silently corrected, and any script that edits the page changes the DOM without touching the source. When something renders strangely, inspect the element first and confirm the structure you think you wrote is the structure that exists.
2. Read the Styles pane like a report
DevTools tells you a lot about why a rule is or is not applying. Chrome’s CSS issues guide describes three categories:
- Invalid: the property or value is not recognised, so it is crossed out with a warning.
- Overridden: a valid declaration lost to another one in the cascade, and is crossed out.
- Inactive: a valid declaration that does nothing because of another property, shown faded with an information icon. The classic example is
justify-contenton an element whose display isblock.
Hover the information icon and DevTools explains what to change. Expanding shorthands, such as margin, also reveals a longhand set later that overrides part of it. The newest DevTools release goes a step further: the Elements panel now keeps inactive styles visible with a distinct marker, with a setting to show or collapse them, which helps when a style stops applying and you want to see what it was.
3. Toggle before you edit
Untick declarations one at a time to get an instant before-and-after comparison. If disabling overflow: hidden makes a dropdown reappear, you have located the cause in seconds. Edit values live in the panel, and only copy the final change back into your stylesheet.
4. Check specificity and the box model
When a rule appears to be ignored, a more specific selector is usually winning. The fix is to match or lower specificity deliberately, not to reach for !important.
/* Specificity: one element */
a { color: gray; }
/* Specificity: one class, so this wins */
.nav a { color: navy; }
/* Better than !important: make the intent explicit */
.nav .nav-link { color: navy; }
For size surprises, open the layout view. By default an element’s width covers only its content, so padding and border add to it; setting box-sizing: border-box makes the width include them.
5. Rule out the boring causes
MDN’s debugging checklist puts a few unglamorous steps in a sensible order: take a short break, validate the HTML and CSS, confirm that the property or value is supported in the browser you are testing, and look for overrides. Unsupported values are dropped without any error message, so a quick look at a compatibility table can save an hour. Testing in a second browser also helps separate a genuine bug from a quirk.
6. Build a reduced test case
If the cause is still unclear, start removing things. Recreate the markup as static HTML, delete the JavaScript and see if the problem remains, then strip HTML and CSS until only the minimum that reproduces it is left. This often reveals the answer along the way, and if it does not, you now have something small enough to share with a colleague or attach to a bug report.
<!-- reduced.html: nothing but what reproduces the bug -->
<style>
.wrap { display: flex; }
.item { flex: 1 1 200px; min-width: 0; }
</style>
<div class="wrap">
<div class="item">Short</div>
<div class="item">A very long unbroken string ...</div>
</div>
New tools worth knowing
Chrome’s October 2026 DevTools post, published in September, adds several things relevant to debugging:
- Network: you can edit and resend a request as a
fetch()call, pre-filled in the Console, which is handy for replaying a failing API call with tweaked parameters. Local overrides now reject path traversal and non-HTTP schemes. - Memory: heap snapshots can be filtered by minimum retained size, with primitive values hidden, and objects can be found by property name, which speeds up leak hunting.
- Performance: soft navigations are covered in the statistics view, and CPU performance overrides allow more repeatable throttled tests.
- Device mode: presets are grouped into mobile, foldable, tablet and desktop categories and the device list has been refreshed.
The post also covers agent and MCP tooling for DevTools, which is outside the scope of this article.
Write down the cause
Once fixed, add a short comment or commit message explaining why the change was needed. Future you will meet the same quirk again. If your team would rather hand the investigation to someone else, our services include debugging and rescue work on existing sites and themes.