Christian Heilmann

You are currently browsing the Christian Heilmann blog archives for November, 2020.

Archive for November, 2020

Quick hack: How to make the new CSS Overview feature of Chromium Devtools shareable

Thursday, November 12th, 2020

Ok, I am an impatient person. I also love to hack around with things. You may or may not know about an experiment in Chromium Developer Tools called CSS Overview. What it does is give you an excellent report about your web site’s CSS:

CSS Overview Results for this blog

You can see statistics about the CSS like how many selectors you used, you get an overview of all the colours, learn about contrast issues and which fonts you used.

It is a bit like a style guide, but generated from the CSS used in the document. Now, I’d love this to be shareable with third parties to show, for example, a client what they’ve done wrong in their CSS. But for now, this isn’t a feature yet.

However, there is a quick and dirty way to make the results shareable. You can watch the screencast on YouTube or look at the instructions below.

Here’s how to do this step-by-step.

  1. Go to the site you want to get the CSS overview from
  2. Open Developer tools (CMD|Ctrl+Option+I)
  3. If you haven’t got CSS Overview yet, go to the settings (the little cog), pick “Experiments” and select on the CSS Overview option
    Turning on CSS overview in the developer tools experiments
  4. Restart DevTools
  5. Go to the CSS Overview Tab and press the “Capture Overview” button – you should get your report
  6. Go to the … menu top right of the Developer Tools and select the “undock to separate window” option – the DevTools should be an own window now.
    Undocking the Developer Tools to get them in an own window
    Developer Tools in own Window
  7. Click on that window to give it focus and press CMD|Ctrl+Option+I again. This will open another DevTools instance that debugs the current one!
    Developer Tools debugging another instance of developer tools
  8. Go to the Elements tab and scroll all the way up until you are at the HTML element.
  9. Click the element and click the … menu at the beginning of the line
  10. Select “Copy Outer HTML” from the menu
    Selecting copy outer HTML in developer tools
  11. Close this instance of DevTools
  12. Dock the other instance back to the left of the browser (by selecting … again and choosing the left option)
  13. Open a new browser tab with CMD|Ctrl+t or hitting the + next to the tab
  14. Go to the Elements tab, and go back to the HTML element again.
  15. Right-Click and select “Edit as HTML
    Edit as HTML
    Editing HTML in Devtools
  16. Highlight all the HTML with CMD|Ctrl+a and paste the copied HTML with CMD|Ctrl+v
  17. Click outside the edit box and the document is now the report of the CSS Overview
  18. Print, save as HTML or whatever else you fancy

Quick and dirty, but for now does the job. Tell me what you think about the CSS Overview feature and what else it should do on Twitter at either @ codepo8 or the official @ EdgeDevTools account.

How to persistently change third party web sites with browser developer tools

Tuesday, November 3rd, 2020

This has also been published on Medium and dev.to in case you prefer them.

Often you find things in web sites that annoy you. And – as a web developer – you’re even asked to fix some problems in web sites without getting access to the source.

Using developer tools in browsers you can change a lot of things and you can even fix some issues. You get visual tools to tweak colours, dimensions and more without having to know CSS.

The problem is that the changes aren’t persistent – once you reload the page, they are gone. Furthermore it is tough to make your changes accessible to others short of a screencast or pair programming using live share.

Stuart Langridge complained about that on his blog and longed back for the days of Greasemonkey and Userscripts. Both are still around and to a degree maintained. There are also a few extensions for other browsers than Firefox that do similar things. But the overhead of having to install an extension to do some tweaking seems a lot.

There are some features in browser developer tools that can help you with this task though. Some may be hard to find or you never looked, so here’s an overview.

Elements, Styles and Changes

Using the Elements and Styles pane in Developer Tools you can inspect the HTML, and change or add to the styles of a chosen element. Most likely you’ll have done that already, tweaking your CSS until it did exactly what you wanted it to do.

Link to opening the CSS in the Sources pane

What is often forgotten is that if you have bigger changes, you can also click the name of the CSS file and get to the Sources pane where you have a full-fledged editor in the developer tools. The editor will jump to the right line in the CSS file. For minified files the Developer Tools will offer you to get a more human readable version . If that doesn’t happen for some reason you can click the ‘{}’ button instead.

CSS file open in sources pane

Another thing that you may not be aware of is the Changes feature. You don’t need to keep track of what you changed in the CSS when you get back to your source code. In the “Changes” tab you get a difference view of all the changes you did and you can copy and paste them.

The changes pane showing what happened to the CSS file when you used the developer tools

Console

The Console is the go-to JavaScript debugging environment for most (although Breakpoints are so much better). You can also write JavaScript in the console that gets executed in the Window object of the currently open document. You have some handy shortcuts available there. For example $ is document.querySelector, $$ is document.querySelectorAll and $0 is the currently selected element of Developer Tools. The copy() command copies to the clipboard. You can find a list of all the available commands in the docs.

Often you find yourself trying to cram all the code to run against the page into one line, but that’s not needed. If you hit enter on a line that isn’t a full JavaScript expression, Console automatically realises you want to write more and indents the next line. You can also always use Shift-Enter to force linebreaks and hit Enter to execute the code when you’re done. Hitting the up and down arrow allows you go back and forward in the Console history, much like any other Terminal emulator.

You can do clever things in the console. For example, if you wanted to get all the links in the document that have “media” in them and filter out duplicates, you could do the following:

copy(
   [...new Set($$('a')
      .map(l => l.href)
      .filter(l => l.includes('media')))]
  .join("\n")
)

Running this against this page for example will give you a list of 25 unique images.

Whilst this is powerful, you also will lose your work when you restart the browser and the Shift+Enter trick is useful but also feels not natural.

That’s why Developer Tools also have a way to edit and store snippets of code to execute in the context of the current page.

Snippets

Snippets are a feature of the Sources pane in the Developer Tools. It allows you to write small scripts to execute in the context of the current page using a built-in editor. You can name the scripts and keep them as a collection for re-use later on.

Snippets in Developer Tools

This upgrades the Console experience, but you still need to run the script by hand every time you reload the page. And you can’t re-use any of the resources of the page you try to fix. To do this, you can use a feature called Overrides.

Overrides

By using Overrides you can take any resource of the current web site and store it locally on your computer. On later reloads of the document, the browser will take your local copy instead of the live one.

I wrote a detailed explanation how to use them on the official Developer Tools docs and here is a quick screencast explaining the feature.

The excellent part about overrides is that you use the real code of the page and change it. You can select files from the Network tab, directly from the Elements tab or really anywhere. Once you set up your overrides folder these stay in there as replacements until you delete them. The browser creates the correct folder structure for you. This means you can tweak the code and once you are done you can zip up your overrides folder and send it to the site maintainer as a drop-in. It is also an interesting feature to override annoying popup scripts.

More on overrides:

Summary

These are some of the features of Developer Tools that allow you to change web sites for you locally. It is fun to play with live sites and change them to your needs. And running a few scripts locally is most likely safer and less detrimental to the performance of your browser than using overzealous browser extensions.

Back to Basics: Event Delegation

Sunday, November 1st, 2020

Screenshot of the event delegation example code

Back to basics is a series of small posts where I explain basic, dependency free web techniques I keep using in my projects. These aren’t revelations but helped me over the years to build sturdy, easy to maintain projects.

One of my favourite tricks when it comes to building web interfaces is Event Delegation

Events don’t just happen on the element you apply them to. Instead they go all the way down the DOM tree to the event and back up again. These phases of the event lifecycle are called event bubbling and event capture.

The practical upshot of this is that you don’t need to apply event handlers to every element in the document. Instead, often one handler on a parent element is enough. In the long ago, this was incredibly important as older browsers often had memory leaks connected with event handling.

Say you have a list of links, and instead of following these links you want to do something in code when the user clicks on them:

<ul id="dogs">
  <li><a href="#dog1">Dog1</a></li>
  <li><a href="#dog2">Dog2</a></li>
  <li><a href="#dog3">Dog3</a></li>
  <li><a href="#dog4">Dog4</a></li>
  <li><a href="#dog5">Dog5</a></li>
  <li><a href="#dog6">Dog6</a></li>
  <li><a href="#dog7">Dog7</a></li>
  <li><a href="#dog8">Dog8</a></li>
  <li><a href="#dog9">Dog9</a></li>
  <li><a href="#dog10">Dog10</a></li>
</ul>

You could loop over each of the links and assign a click handler to each:

const linkclicked = (e,l) => {
  console.log(l);
  output.innerHTML = l.innerHTML; 
  e.preventDefault();
};
const assignhandlers = elm => {
  let links = document.querySelectorAll(`${elm} a`);
  links.forEach(l => {
    l.addEventListener('click', e => {linkclicked(e,l)});
  });
}
assignhandlers('#dogs');

You can try this event handling example here and the code is available on GitHub (event.handling.html).

This works, but there are two problems:

1. When the content of the list changes, you need to re-index the list (as in, call assignhandlers() once more)
2. You only react to the links being clicked, if you also want to do something when the list items are clicked you need to assign even more handlers.

You can try this by clicking the “Toggle more dogs” button in the example. It adds more items to the list and when you click them, nothing happens.

With event delegation, this is much easier:

document.querySelector('#dogs').
  addEventListener('click', e => {
    // What was clicked?
    let t = e.target; 
    // does it have an href?
    if (t.href) { 
      console.log(t.innerText); // f.e. "Dog5"  
      output.innerHTML = t.innerText; 
    }
    // if the list item was clicked
    if (t.nodeName === 'LI') { 
      // print out the link
      console.log(t.innerHTML);
      output.innerHTML = t.innerHTML; 
    }
  e.preventDefault(); // Don't follow the links
});

You can try this event delegation example here and the code is available on GitHub (event-delegation.html). If you now click the “Toggle more dogs” button, and click any of the links with puppies, you’ll see what it still works.

There are a few things you can do to determine what element the click event happened on. The most important bit here is the “let t = e.target;” line, which stores the element that is currently reported by the event capturing/bubbling cycle. If I want to react to a link, I check if a “href” exists on the target. If I want to react to a list item, I compare the ‘nodeName’ to ‘LI’. Notice that node names are always uppercase if you do that kind of checking.

I really like event delegation as it gives me a lot more flexibility and I don’t have to worry about changes in content. The handler just lies in wait until it is needed.