As with most weekday mornings, links and articles are dropped into our random channel as either points of potential interest or swords drawn discussion. The topics have a lot of range, but the one that recently caught my eye was and article regarding finding improper font definitions in a page.
The article had a useful premise, thought I wasn’t big on the code example or the page injection (which I found hard to read personally, but your mileage will vary). Instead, I decided I’d just write a variation of the snippet to output a unique report and use the DOM’s TreeWalker instead.
TreeWalker has been in the spec and in browsers for a long time and allows you to get a given document’s subtree and take a look at the nodes within. The nice thing about TreeWalker is that it’s fast and if you’ve ever used say lit-html or other such libraries, congratulations, you’ve used TreeWalker without even knowing it.
With our API in mind, we can transverse and go about finding out what our getComputedStyle()
is for a given text node as in the DevTools snippet below.
function findTextNodesFor(element){
let node;
const discoveredTextNodes = [];
const walkTree = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false);
while(node = walkTree.nextNode()) {
discoveredTextNodes.push(node);
}
return discoveredTextNodes;
}
weights = {
100: "Thin",
200: "Extra Light",
300: "Light",
400: "Regular",
500: "Medium",
600: "Semibold",
700: "Bold",
800: "Extra Bold",
900: "Black"
};
fonts = new Set();
findTextNodesFor(document.querySelector('body'))
.filter(node => !['SCRIPT', 'STYLE', 'NOSCRIPT'].includes(node.parentNode.nodeName))
.forEach(node => {
const computedStyle = window.getComputedStyle(node.parentNode);
const font = computedStyle.fontFamily || "";
const size = computedStyle.fontSize;
const weight = computedStyle.fontWeight;
const weights = {
100: "Thin",
200: "Extra Light",
300: "Light",
400: "Regular",
500: "Medium",
600: "Semibold",
700: "Bold",
800: "Extra Bold",
900: "Black"
};
fonts.add(`${size} ${weights[weight]} ${font}`);
});
console.table([...fonts].sort());
This will output a nifty little table of only the unique fonts we find (if you’ve not used Set, I highly recommend you take a look at the docs to see how if can make your life easier).
Now, there are some gotcha’s to keep in mind here:
-
This won’t show you the browsers computed display. Chrome DevTools for instance will show you the font(s) that system are actually being rendered as opposed to just the font definition that is being applied to the node.
-
This won’t transverse the custom element with shadowDOM (because that’s a whole other can of worms).
Sans that, you get a nice little way to see exactly what’s being defined and if you may need to re-evaluate your font strategy.