The mobile landscape today is all but monopolized by WebKit, as a result, most of the tooling and infrastructure to support mobile web development on the frontend is taking place in the WebKit Inspector, so Iâll focus on it, and take a deep dive into its entire feature-set and how and when to use it.
Google and the Chrome team have been pumping a ton of resources into the WebKit Inspector. The changes have enabled a whole new class of complex and ambitious applications that would have otherwise collapsed on their own weight. This is great news, of course, but as I talk to more and more web developers about their process and tooling, it became clear to me that many of them havenât caught up with the changes or arenât making effective use of the tooling available. This blog post attempts to remedy that, not only by walking you through the inspectorâs feature set, but also highlighting certain techniques for bug hunting and feature development that Iâve found to be indispensable. The post is meant to be scannable and shareable. You can click on any header to share a URL to a specific tip/technique or feature to your friends.
Before we start, I want to make it clear that I donât claim to have infallible knowledge on tooling and process. If you find any of this information to be incorrect, out-of-date, or inefficient, please reach out to me and let me know, Iâd love to hear your thoughts.
If youâre new to the inspector or have a passing knowledge of it, do me a favor and play with it as you read this post. Trying things out are the best ways to learn it! âBut Majd, I donât want to keep creating new files and loading them and editing them to test these things out! I have kids to feed!â I hear you, and I agree with you, thatâs where the data: URLscheme comes in!
Try it out: Open a new tab of Chrome, and paste this into the address bar and hit enter:
data:text/html,<b>ZOMG I AM BOLD!?!!?</b>
This is one of the easiest ways to get some HTML into the page and start inspecting it and playing around/investing ideas. Anything after the comma is interpreted as html and once loaded, you can open up the inspector and start playing with it!
There isnât a single WebKit Inspector. In fact, there are 5 at any given time that you can use:
- Safari Stable
- Chrome Stable
- WebKit Nightlies
- Chromium
- Chrome Canary
Iâve tried to sort them from oldest to newest. Chrome Canary gets updated with new features all the time. After they bake for a while with the early adopters, they make their way slowly to Chromium, WebKit Nightlies, Chrome, then Safari. At any given time, Safariâs Inspector is about a yearâs worth of development behind Chrome Canary. That is to say, use Chrome Canary for your development.
Awesomesauce. Youâve downloaded Chrome Canary, you have it open, you have your site up, youâve cracked your knuckles and rolled up your sleeves. Hit CMD+J to open up the Inspector or right click on a specific element and click âInspect Elementâ.
Now letâs set up the environment so youâre comfortable. The first thing to do is familiarize yourself with the UI. Take a minute to click on every button you see, hover over it to see the tooltip, and find out what everything does.
The first thing youâll want to do is click on the gear icon in the bottom right to bring up the settings. Ignoring the horrendously ugly HUDdisplay, I highly recommend checking the âDock to Rightâ setting. What this does is stick the inspector to the right side of your window, but keeps it attached. If you decide to pop it out into its own window, then opening multiple inspectors at the same time can become confusing. If you dock it to the bottom, you get a lot of horizontal space, but vertically youâre very constricted. Docking to the right is the best of both worlds. Hereâs what it should look like:

If youâre working on a mobile application, this setting (in the settings HUD) is essential.
Google, if youâre listening: Default the docked setting to âDock to Rightâ.
Another quick tip to help speed up your work with the inspector is to get very familiar with the keyboard shortcuts. Go to the Elements Panel (some of the other panels eat the keystroke), and type â?â. This should bring up another horrendously ugly HUD display that contains a list of keyboard shortcuts. The most helpful shortcuts are the ones to navigate the Scripts panel, which weâll talk about in a bit.

Google, if youâre listening: Make the keyboard shortcuts accessible from the settings panel. Most people donât know the secret key. While weâre on the topic, why does the HUD have a different light source than the rest of the UI? Why is the border radius so big? Why is the âXâ button not vertically centered in the header? Why are some of the shortcuts so small you canât see them?
Debugging iFrames has long eluded web developers. NO MORE! You can now set which iframe the inspector is inspecting through the popup in the bottom center of the inspector that says ââ. This panel is interestingly only visible when you have the console expanded (hit escape from any panel).

Google, if youâre listening: Make the iframe drop down accessible everywhere.
Sweetums. Youâre all set up, youâve cranked up your music, and youâre hacking your heart away. Now you need to actually do something: Run a command, check the output of a function, check for the existence of a method, or see any logs/errors/warnings. This is where console comes in to help. The console is such a badass, in fact, it not only gets its own panel, itâs also accessible from any other panel by hitting the â>=â icon in the bottom left, or by hitting the Escape key.
It also happens to be one of the more intuitive features: Type something, hit enter, see the output of the expression. Any logs are visible chronologically, click the file name on the right and get taken there in the Scripts panel. What you may not have known though, is that you can type multi-line expressions in the console by hitting âshift + enterâ. This is really helpful for writing out long commands that involve anonymous functions or complex statements. You can also type âctrl + Lâ to clear the console when the logs get overwhelming.
From a DOM-debugging perspective, one of the cooler features of the console is its integration with the Elements panel (which weâll discuss in the next section). Any element thatâs selected in the Elements panel can be quickly accessed using â$0â. That will reference the element and allow you to interact with it. Inversely, whenever you see a DOM node printed in the console, you can right click on it and click âReveal in Elements Panelâ to quickly find it in the DOM.

Google, if youâre listening: Add syntax highlighting to the console command, itâll help simple parse errors. It wouldnât hurt to auto-insert braces and parenthesis and quotes, too.
So you got youâre all set up and ready to start building your application. The first step is to get your HTML and your CSS looking right (Or JavaScript, depending on your workflow). Thatâs where the Elements Panel comes in.
The Elements Panel comes into play whenever you are modifying/debugging CSS or the DOM. The main area of the Elements panel is your live DOM hierarchy. As you make changes through JavaScript, you see them reflected live in the Elements Panel. You can use the arrow keys to navigate the hierarchy, and double click on any attribute to edit either the name or the value. You can also click-drag any node in the DOM to reorder it and change its position.
Because its live, I find myself doing a lot of experimentation in this panel. Drag this node here, does it fix that z-index ordering issue? That div is invisible, is it being hidden by another layer?
At the bottom of the inspector, youâll find a magnifying glass. When you click [that, you can hover over your application itself and it will highlight the node you have selected. This comes in handy when you need a quick way to go to a deeply-nested element.
While youâre playing around with the Elements panel, try right clicking on one of the nodes and see the options that come up. One of these of note, is the âBreak on Subtree Modificationsâ option. When you enable that, any changes that you make to the DOMhierarchy under that node, it will automatically pause, and let you debug it.
Moving on to the right, the CSS editor is up-there in the list of most-helpful features of the inspector. Superficially, it allows you to live-edit your CSS. However, it reduces the barrier to experimentation so much, I find myself moving things around and playing around with ideas I normally wouldâve dismissed as stupid, which is a good thing, as Bret Victor says.
The first thing in the list you see is the âComputed Styleâ section. Check the âShow inheritedâ checkbox, and you will see a list of every single style property and its corresponding value thatâs applied to the selected node. Even if you didnât explicitly set a property, it will show you the inherited default. This helps you not only understand what is making up the styling of the node, but it also helps you find out what properties you can set yourself to modify it. Take a quick look at it and see if there are any CSSproperties you didnât know about, then try them out and see what they do!
Next in the list is the âStylesâ section. This shows you the list of properties, grouped by selector, that have been applied to the node. The first sub-section here says âelement.styleâ. This shows the properties set through the style=”” attribute in the HTML. The next section titled âMatched CSS Rulesâ shows you the selectors that matched the selected node, their properties, and their values, along with the file name and the line number on the right.
To add a new selector, click the â+â button to the right of the âStylesâ header, here you can define the selector, hit tab, then start writing properties and values. Youâll notice Chrome offer auto-complete suggestions (this is another great way to investigate which properties you can set). The version of Canary as of this writing requires you to hit the right arrow key to fill in the autocompletion, then you can hit tab to set the value. Hitting tab again will let you set the next property. If you wanted to set a new property to an existing selector, click once on the closing bracket. Clicking on the button to the right of the â+â new selector button will allow you to specify a pseudo selector. Handy!
Colors behave slightly differently. Clicking once on a color value will toggle through a list of representations (hex, rgb, rgba, etc), and clicking on the little colored square will open up the color picker.

All this is great, but letâs say youâve just spent 10 minutes editingCSS. Now what? How do you save those changes? To do that, click on the file name of the selector (or go to the file yourself in the Resources panel), then right click on the file (which will be updated to reflect those changes), and you can right click to âSave Asâ and overwrite your existing files. Personally, I find selecting the text and pasting it into my editor to be faster and less error-prone.
One final node on CSS Editing: If you write a new selector (by hitting the â+â key), it wonât persist into a file because it doesnât know which CSS file to put the selector in.
Google, if youâre listening: Prompt me which file to put a new selector in when I create one. Also, make âtabâ fill in the selected auto-completion. Finally, find a way to make persisting changes inCSS to my code easier. This last one is more of a high-level wish, I donât really know whether or not itâs possible nor how it would work, I just want the process streamlined :P.
Phew, that was a handful! Take a minute to play with all this. When youâre done, letâs move down to the next item in the list: Metrics. If youâre not familiar with the CSS Box Model, take a minute to readthis awesome guide.
The Metrics section basically shows you how the browser is rendering a node from the perspective of content size, padding, border, and margin. Use this tool to debug positioning/dimension problems.
A nice companion tip to the Metrics panel, is that the semi-transparent blue box that overlays the selected node will actually show you the padding and the margin, so you can understand how a box is affecting the flow

Blue is for content, green is for padding, and orange is for margin.
Weâll skip Properties and DOM Breakpoints for now. I havenât found a use for the Properties section yet, and DOM Breakpoints shows you any âBreak on âŚâ actions youâve taken by right clicking on a node. The last section weâll talk about in the Elements panel is the Event Listeners section.
If youâve attached any event listeners on your node (either using JavaScript or using the attribute in HTML), youâll find those listeners listed here. This comes in handy when you want to debug whether or not a listener has been properly attached to a node, and what will happen when it gets invoked.
Clicking on the little funnel icon on the right allows you to see either the listeners on the selected node or in the document. This comes in handy if you have listeners attached on things you canât select in the main list (like window, document, etc).
Your HTML and CSS are looking good, and youâve got a fair bit of JavaScript written to use either the FileSystem API, IndexedDB, LocalStorage, App Cache, or Cookies. The Resources panel is where you go to inspect and debug all these storage resources. Most of them do more or less the the same thing and are pretty self-explanatory: Click a resources, see a list of items, and dig through to navigate your data.
Of note is the first item in the list called âFramesâ. It includes a sub-item for every frame in your application, and groups resources such as Images, Scripts, and Stylesheets. Really the only reasons Iâve found to dig through this list is to find a Stylesheet file I edited so I can copy its content and paste it into my editor to save.
The Network Panel comes in handy when youâre debugging, well, network issues. Is your image asset not updating? The network panel will tell you whether or not itâs being served from a cache. Is your XHR not responding? The network panel will tell you if itâs stuck or error-ing out.
Clicking the âRecordâ button (the black circle) will maintain a Network session across reloads, handy if you want to see how a change in your codebase affects the network performance.

If you find yourself debugging performance issues, the Network Panel is also very helpful. On the right, you see a âcascading waterfallâ of your network requests. If your page is taking a really long time to load, your first step in debugging it would be to look at the waterfall. The blue and red vertical lines show you when the DOMContentLoaded event fired, which means that before then, your use is sitting around waiting for something to happen. You want to reduce that time as much as you can.
Why do I keep calling it a waterfall, you ask? Well, it looks like one, but more importantly, the reason it looks like a waterfall is because every network interaction takes time both in network latency, and in download time, and the browser can parallelize only so many of them. If your waterfall is wide, you need to go out of your way to cut HTTP requests.
By the way, you can click on the âTimelineâ header and you get a drop down (!) to change the sort order. Particularly interesting is the âLatencyâ sorting, which shows you which of your requests took the longest to establish.

The half-transparent left-side of the capsule shows the latency, and the dark part on the right shows the download time.
On the bottom of the Network panel, click âXHRâ to filter the network connections just to XMLHttpRequests. Then click one of them. You see that the right side now changes to show details of that specific request. The first tab shows you all the HTTP Headers sent with the request, and those of the response. This helps when debugging server bugs or CORS bugs.
Preview is a pretty-formatted version of Response. If youâre getting back a lot of JSON, the Preview tab will format it into a collapsable list for you, whereas the Response tab will show it in plain text.
Cookies show you the cookies that were sent as part of the request, and Timing shows more details regarding the time profile of the request. Again, helpful if you have requests taking a long time.
Iâm a full-time JavaScript developer, which implies that I spend most of my day in the Scripts Panel. It has also seen some of the biggest changes recently.
Looking around, two buttons worth mentioning are the âPretty Printâ button (looks like a pair of curly braces), which will properly format a minified file. This comes in handy if you get a bug in a third-party minified package and you want to have an even remote chance of figuring out what is going on.
The other button worth mentioning is the âBreak on Exceptionâ button (Looks like a pause button). When gray, itâs disabled. Clicking it once will cause your script to pause if it hits any thrown exception. Clicking it again puts it in the âBreak on Uncaught Exceptionâ mode, which only pauses your script if you (or something else you use), throw an exception that doesnât get caught. This is indispensable when you want to track an exception thatâs being thrown, since it preserves the call stack and the current state of the application.
The addition of tabs in the main workspace and a full file browser, scoped by origin has dramatically improved the efficiency of moving around your project.
To open the file browser, click the weird icon in the top left (it looks like two folders with a right angle between them). By default, the file browser will âfloatâ on top of your workspace, so click the weird icon on the top right of the browser (it looks like a half-white, half-black rectangle) to dock it. Try typing while youâre in the file inspector, it will do a fuzzy-match of the files in your project!

While weâre on the topic of moving around your project, try hitting âCMD+Oâ, this will open up a TextMate-style âGo-to-Fileâ popover that lets you quickly jump to a file. âCMD + Shift+ Oâ will open up a âGo-to-Symbolâ popover that lets you quickly jump to a symbol in the current file, and âCMD + Lâ will let you jump to a specific line.

Google, if youâre listening: Add the path to the file in the Go-to-File popover, in case there are duplicates.
Clicking on a line number in the gutter will insert a breakpoint. If your application hits that line during execution, itâll pause, bring up the Scripts panel, and highlight that line. Then you can inspect the call stack, the scope variables, and inspect/modify your objects. This is the main workflow when debugging issues with your JavaScript.
Occasionally, youâll want to debug a problem in hot code (code that gets run over and over). Putting a breakpoint here becomes tedious, since youâd have to hit âContinueâ over and over. What I usually do in that situation is wrap the function call I want to debug with âwindow.foo = trueâ and âwindow.foo = falseâ, then right click on the breakpoint, click on âEdit Breakpointâ, then in the textfield I type âwindow.fooâ. What this tells the inspector is that unless window.foo evaluates to true, donât stop.

So, youâve added a breakpoint, you refreshed the page, and now your script is paused. Now, the fun begins.
The first thing of interest in the sidebar is âWatched Expressionsâ. If you care about the value of some expression (Say âMyApp.someController.property === âsome valueââ), then adding that as a watch expression will let you keep an eye on it without having to type it over and over in the console.
Below that, the âCall Stackâ section shows you every function call that the system went through to end up where it did. You can navigate this list using âCTRL + .â to go down and âCTRL + ,â to go up in the stack. I usually navigate this list when I care about how a variable came to have its value and how it traveled through the system.
Next, âScope Variablesâ lists the local variables and their variables. If youâre using closures to close over variables, then those will be grouped together. The âGlobalâ group shows you every variable on the âwindowâ object (a huge list). As you move through a function, this list gets updated automatically.
Now that youâve inspected the state of the app on a breakpoint, youâll probably want to move around. âContinueâ, âStep Overâ, âStep Intoâ, and âStep Outâ are your friends here. In fact, youâll be using them so frequently, itâs worth bringing up the keyboard shortcut list again and learning the shortcuts for them. Itâs much more efficient to navigate through the list with the keyboard than the mouse. If youâve used a debugger before, these terms are already familiar to you. For the web developer though, these are new concepts that we didnât have before.
Continue resumes the execution of the program. If execution hits the same breakpoint again, itâll pause again. Step over will skip function invocations and stay within the current function. Step into will enter the new function if itâs being called. If youâre calling multiple functions in the same line, you can step into, and out of each one in order. Step Out will leave the current function and go back up one level in the call stack.
These tools are essential in walking through your code and pin-pointing a bug, or finding out which path through your codebase is being followed.
Another handy tool lives under the âXHR Breakpointsâ section. As the name suggests, it sets up breakpoints related to XMLHttpRequest objects. The way you specify the breakpoint, is by typing in a substring of the URL you want to inspect. Handy!
By the way, in the âScope Variablesâ section, you can right click on a function and choose âJump to Definitionâ to jump to the part of the file that defines that function.
Next in the list is the Timeline Panel. As you might have observed, each panel is designed to help debug a certain class of problems: Elements Panel for DOM and CSS, Resources for local storage and assets, Network for HTTP requests, Scripts for Javascript, and Timeline is for browser performance.
What do I mean by âbrowser performanceâ? Iâm referring to things that are generally out of your control, but which affect the performance of your application. Understanding whatâs happening under the hood is essential to supporting the growing complexity of an application.
The first section of interest is the Timelines section. To activate it, hit the Record button (the black circle in the bottom left of the panel). When itâs glowing red, perform a task in your application you like to inspect. If youâre wondering why your scrolling performance is slow, you would try a short scroll. If youâre wondering why loading a modal panel is slow, you would do that. Donât worry about doing too much and getting overloaded by data in the panel, there are tools to help!

So, youâve managed to get a nice little timeline of whatâs happening, but youâre only interested in a little section of the data. To âZoom inâ, you can click and drag on the timeline graph. Youâll see a couple of draggable thumbs so you can adjust the visible section. Moving down into the waterfall graph, youâll notice little arrows next to some of the orange capsules. Expand those, and what youâll see is the function invocation that triggered the browser to do work. In the example below, we can see that a scroll event had fired, invoked a handler, which caused a âRecalculate Styleâ to fire. If you hover over the item in the sidebar, you see even more detail.

You may be wondering at this point âWhat are these purple events that are taking up time? Repaint, Recalculate Style, and Layout?â. These are browser-events that are usually invoked by in response to visual changes. For example, If your resize or scroll, the browser needs to do a bunch of work to make sure everything looks as youâd expect it to. You could also invoke these events yourself, so itâs worth understanding what the inspector is telling you and not taking DOM changes for granted.

This occurs when you modify CSS properties. In the above screenshot, you see Iâm running the same command twice, but seeing different results. The first time I run it, the browser has to Recalculate Style, Layout, and Paint. The next time, it just has to Recalculate style. Whatâs happening?
Because this is on a fresh page load with nothing visible, giving an unstyle div a height causes its contents to change layout (Layout), causes the visual display to change (Paint), and invalidates the styles (Recalculate Style). The next time I run the same command with the same value, it gets to skip the Paint and the Layout, since they didnât change. Notice the order: Recalculate Style informs the later processes whether or not they need to get triggered.
Back to our empty page, letâs give our div a width, height, and background color so it actually changes visibly on the screen:

Now, it has to repaint both times, but it only needs to calculate layout once. Thatâs because the Recalculate Style step found that the positioning/dimensions havenât changed, but the background has, so it skipped that step. Anything that cause a visual change, causes a repaint.
Often referred to as âReflowsâ, a Layout event causes the browser to recalculate the position of elements. For example, say you have a picture thatâs floated, so the text wraps around it. If you remove the float, the browser has to âre-flowâ the text around it. Paul Irish has a great video where he describes reflows and how to avoid them.
Google, if youâre listening: Please fix the resize behavior. On small Macbook Air screen, itâs common to hit multiple UI bugs when you arrange the inspector/application side by side.

For more detail on how this works under the hood, refer to this blog post.
Now weâve looked at the timeline, optimized it, but the application is still crashing every now and then after you use it for a while, sometimes it slows down, and it stutters a lot. Youâve seen a few âGCâ (Stands for Garbage Collection, which runs every now and then to clean up unused objects) events in your timeline, the Memory tool helps you debug those issues.
Tony Gentilcore has a great writeup on finding and fixing memory leaks, you should definitely give it a read. Iâll give you a quick overview here.
Click on Memory in the sidebar, then click record. Perform a task in your app, and observe the memory profile. Hereâs the memory profile for an app that simply creates an object and throws it away every mousemove event:

A typical javascript memory graph looks like a sawtooth function: You keep accumulating memory until the garbage collector runs and cleans up unused memory. A few cycles through GC runs, and your memory profile should be flat. If itâs constantly going up in between GC cycles, then you have a memory leak. As your application gobbles up memory, the app will slow down, and certain browsers (MobileSafari) will actually kill it.
Below the graph youâll see some more useful metrics to track the number of DOM nodes, and event listeners, theyâre pretty self-explanatory.
Finally, letâs say you deployed your app in production, you found a bug in production, located it in the inspector. How do you tell your coworker/developer? Well, instead of taking a static screenshot, you can actually right click on âTimelinesâ and âMemoryâ, and save your session so that you can share the actual debug data! Handy when youâre working as part of a team.
So, youâre now at a point in your applicationâs development where it looks the way you want it to look, HTTP requests are minimized, and youâre causing the browser to do more work than it needs to. Somethingâs not right though. Everything seems to be snappy, except for one small part. Youâve tried debugging it with the Timeline panel, but it doesnât give you enough depth and detail. Itâs not the browser thatâs slow, itâs your own code.
Thatâs where the Profiles panel comes in.
The first type of profiling you can do is JS CPU profile. The description outlines at a high level what it measures: What functions your app spends the most time in.
Select it, then click âStartâ. Every action you take now, will be logged until you hit the glowing red âRecordâ button to stop recording (Or click on the âStopâ button). Once stopped, the profiler will show you an ordered list of all the functions that had executed, and the time it spent in each. Youâll probably see something like â(program)â at the top of your list. Thatâs webkit taking time to do stuff. You canât inspect it, and you canât do much about it (but the Timelines tab should help locate some of those bugs!). Apart from that, hereâs what a typical profile looks like:

This is the profile for my blog when I open the photo portfolio and open/close a photo a few times. Looks like the most expensive part of that interaction is setting the curtainâs opacity and retrieving the bounding client rect. Just the info I needed to optimize that part of my app.
Google, if youâre listening: Thereâs a lot of work you can do here to surface useful information and hide useless information. I often get stuck in infinitely-deep lists, or 99.99% of my time spent in (Program), distorting everything else.
CSS doesnât come for free. Complex stylesheets take time to parse, calculate, and apply. The CSS Selector profiler shows you how many times each selector was matched to a DOM node, and how long the browser spends applying those selectors. In a complex application with many divs of the same type, applying styles to them might take a substantial amount of your appâs startup time.
This is one of the most obtuse views in the inspector. So much so, I havenât actually found it useful. Take this for example:

The amount of useful information there as far as I can discern is zero. Iâll defer once more to Tony Gentilcoreâs writeup, may he light your way.
Weâre almost there! The last panel is the Audits Panel, and itâs basically the last sanity-check of performance you do before going to production. Essentially, it will inspect the resources and the HTTP requests and suggests improvements based on current industry best practices. For example, while writing this, running the Audits panel told me that I should specify the image dimensions in the HTML to make layout faster. Good to know!
All the tips here are well-documented, and you should at least take a quick look through them.
I hope youâve found at least some of this information useful. Iâve been writing complex web applications on the desktop and mobile for 2 years now, and Iâve had to use each of these panels to solve a different class of problems.
If Iâve mis-interpreted something, missed something, or made any errors, please let me know.
How Browsers Work â A Fantastic, and in-depth look at the processes and plumbing that we build on.
The Mozilla Developer Network Documentation â The most authoritative and up-to-date reference and guided documentation HTML, CSS, and JavaScript. Ignore w3schools.