Debugging and dev tools

Of all the things you learn on the web, there are some skills that have a disproportionate impact, in that they fundamentally change the way you work for the better. For me, one of those was templating, being able to generate HTML in an orderly way instead of haphazardly. Another was learning to write a build system, crucial for news app templates like Tarbell (or the template we use at NPR). But probably the biggest upgrade in my skillset was learning to use Firebug, the ur-developer toolkit first released in 2006 for Firefox.

Dev tools vary between browsers and are updated rapidly, so we won't try to cover everything under the sun. But there are common elements between them that you should know: how to use the DOM inspector, how to place and use breakpoints, and how to debug a mobile page.

Note that for the purposes of this page, I'll be focusing on the Chrome and Firefox dev tools. It is good to have a working knowledge of the Edge and Safari developer experience, especially since those two are likely to be your "problem browsers." But for most working web developers, the best full-time tooling is in the two cross-platform browsers, Chrome and Firefox.

While working in the dev tools, you can usually have the console open at all times, even while you're looking at other panels. There's a menu option to do so, but usually the easiest way to show and hide the console drawer is to press the Esc key. Having a console open while you work on a page is like having a command line that's always present, but just for your page.

Inspecting the DOM

The vast majority of my time in the dev tools is usually spent looking at the DOM through the element inspector (which may be called "Elements" or "Inspector," depending on the browser). That's in large part because it's the place where feedback is most immediate, and where the task at hand (small visual tweaks in CSS) can be hardest to debug. It's also the easiest panel to get to: right-click on a part of the page, choose "inspect," and it'll open right up.

The element inspector displays the live document tree. This is useful, because of course the pages that a user sees are often much different from the original document that's sent to the browser: we mutate them with JavaScript, and we may also manipulate them using CSS (say, by adding pseudo-elements in different places). But what you see in the element inspector is the "browser's eye" view, and the actual source of truth for what gets shown.

You'll notice that as you run your mouse over the tree, you should see the elements highlighted in the page, with different colors representing their content, padding, margin, and border. Next to (or below, depending on the size of your dev tools window) the DOM tree, there should also be a panel showing the styles for the selected element. Click on a part of the tree, and you'll see the styles that are applied to it in descending order (meaning, the top-most styles are the ones that actually get applied).

We say that the inspector is "live" in that it reflects any changes that are made to the document. But that relationship also runs the other way: you can use the inspector to change the document, often without even writing code. For example, you can drag and drop elements around the tree to rearrange the document. You can also click on the values in the style inspector and change them, either by manually typing numbers, or by using the up and down arrows to step through numerical values. If the value of a style is a color, there's a little preview swatch, and clicking on that swatch displays a color picker. If you haven't used the style panel much, I recommend just clicking around and seeing what you can discover—it's an incredibly rich environment for experimentation.

It's natural to use the inspector during development of your own pages, since this is actually the intended purpose. But I want to stress that even if you're not a front-end developer, this panel is still incredibly useful:

You should get used to debugging other people's pages this way: it's one of the best ways to learn new CSS and HTML techniques. Many of the tricks that are in this book—the aspect-ratio padding hack, the weird attribute selectors, and the creation of responsive SVG files—were learned by digging into other people's code and seeing what made it tick.

Debugging and using breakpoints

Of course, it's sometimes no easier to tell what makes your own code tick, particularly if you step away from it for a week or two. So the second most important panel in the dev tools is the debugger (referred to, in Chrome at least, as "Sources"). Being able to use a debugger effectively will save hours of chasing down bugs, particularly in projects where you're breaking in one particular iteration of hundreds or thousands of data points.

To get us started with the debugger, I've written a script into this page that will break in a particular place. There should be an error in the console when you load it: click on the error location (on the right side of the console line, which should look something like perf-debugging.html:44, meaning line 44 of this file) to jump to the source. The line should be highlighted, and there will usually be a notification about what caused it to break (in this case, d is undefined).

Now, let's use the real power of a debugger to try out a solution. Still looking at the source file, click on the line number where the error occurred. This should highlight the line number in blue, meaning that a breakpoint is set. Breakpoints effectively pause your script before executing the line. While the script is frozen, you can mouse over variables to see their value. You can also use the console to run snippets of code (remember, you can toggle the console drawer from any dev tools panel by pressing Esc). Your code will run as if you had inserted it where the breakpoint goes, meaning that you have access to any variables that are in scope at that location.

Let's run a quick line to see how to fix this error, where we have an undefined variable. One way to fix it would simply be to defined it, so from your console type var d = c and press enter. Once that's done, you can use the "resume" button (which will look like either a play button or a stop sign, depending on the browser) or press F8 to continue. Now we've monkey-patched the code to define the missing variable, and the code will continue from there.

The problem with breakpoints is that for many data journalism contexts they may be more trouble than they're worth. Inside a loop through 1,000 rows of data, for example, you don't want to have to hammer "continue" until you actually hit the error. In that scenario, it may be easier to set a conditional breakpoint: right-click on the number and choose to add a conditional breakpoint, and then fill in the expression (imagine it as the conditional section of an if statement). For example, if I'm looping through a geo dataset but only breaking on a certain FIPS code, I might add a breakpoint with the condition set to row.fips == "53", and it'll only pause the script on rows where that's the case.

Debugging mobile

Phones are great, but if you've ever ended up with a bug that, say, only appears in Safari on an actual iOS device, you also know that debugging on mobile is an exercise in pain. It would be nice to have dev tools on the device, but given the screen sizes, it's hard to imagine how that would even work. However, before you resort to alert() and hammering refresh, you should be aware that it is possible to attach dev tools on your desktop to the mobile browser connected via a USB cable, which gives you all the power you're used to.

When using the remote inspector, you should be able to view the DOM, edit styles, and set breakpoints the same as you would on the desktop. You can also interact with the device when using the "select element" button: press the button on desktop, then tap the element that you want to inspect.