Grunticon updated to address IE8 data URI length limit

I submitted a pull request for grunticon earlier this week and it was merged into the master branch today! The update addresses a limitation in IE8 where images embedded as data URIs are restricted to about 32KB. In these cases grunticon will now load these large images as external image files to ensure that they are still displayed.

What is grunticon?

grunticon is a tool by the talented folks at Filament Group which makes it easy to manage SVG images in your website. Basically, it reduces the number of HTTP requests to load the images to improve performance, and it automatically generates fallback PNG images for older browsers that don’t support SVG. The description from the readme follows:

grunticon is a Grunt.js task that makes it easy to manage icons and background images for all devices, preferring HD (retina) SVG icons but also provides fallback support for standard definition browsers, and old browsers alike. From a CSS perspective, it’s easy to use, as it generates a class referencing each icon, and doesn’t use CSS sprites.

grunticon takes a folder of SVG files (typically, icons that you’ve drawn in an application like Adobe Illustrator), and outputs them to CSS in 3 formats: svg data urls, png data urls, and a third fallback CSS file with references to regular png images, which are also automatically generated and placed in a folder.

grunticon also generates a small bit of JavaScript and CSS to drop into your site, which asynchronously loads the appropriate icon CSS depending on a browser’s capabilities, and a preview HTML file with that loader script in place.

What was the problem?

I came across an issue where some images I had processed with grunticon were not displaying in IE8. There was just a blank space where the images were supposed to show up. IE8 doesn’t support SVG so grunticon serves it images as PNG data URIs embedded in a stylesheet. However there is a limitation in IE8 which means that it does not support data URIs longer than 32,768 characters. Some of my images, whilst small as SVGs, were larger than 32KB when saved as PNG data URIs, and therefore they were not displaying. For an example, visit http://codepen.io/keeganstreet/full/Ltdxy in IE8, and you will only see one image.

What was the solution?

Now when grunticon generates the stylesheet with embedded PNG data URIs, it measures the size of each image, and if it is greater than 32,768 characters, it removes the data URI and uses a link to the external PNG image file instead. This results in an extra HTTP request to load the image but it ensures that the user will see it!

Element Finder now returns the line numbers of matching elements

I just released an updated version of the Sublime Text package Element Finder. The results screen now includes the line number of each matching element. You can double click the line number or summary and Sublime will open the file and jump down to the correct line.

How it works

To add this feature I needed a way to map DOM elements to line/column numbers in HTML source-code. Once a DOM has been generated it has no direct relationship with the HTML. There is no function in the DOM, jQuery, etc like `$(“#header”).getLineNumber()`. To solve this problem I wrote a Node module called domtosource, and included this as a submodule in Element Finder. Domtosource has a couple of techniques for finding the line and column number of an element.

The first technique is fastest, but only works if the outerHTML of the element is a unique string in the HTML. If that is the case, we can just get the character index of the unique string, count the line breaks before that index to get the line number, and then count the characters between the last line break and the start of the string to get the column number.

If the outerHTML is not unique, domtosource uses a slower method, but one that works in all cases. This method is based on the fact that elements appear in the HTML and the DOM tree in the same order. We get the node type of the matched element, for example `div`, then walk through the DOM tree to find how many other div elements appear before the matched one. Now that we know this is the nth div, we search through the HTML for the nth occurance of the string `<div`, which gives us the character index of the element. Once we have that index we can re-use part of the first technique and count the line breaks and characters before the index.

You can install Element Finder through Package Control.

CSS Specificity Calculator

When you see two CSS selectors can you always say which one has a higher specificity? For example, which of the following selectors would overrule the other?

div.products li > *[data-name="test"] a
:first-child .selected:hover

I don’t always know with some of the more complicated selectors, so I made a little web app to figure it out for me: specificity.keegan.st

The app uses regular expressions to find the parts of the selector which contribute to specificity. It highlights each part with a background colour to help you learn the specificity rules. The core part of the app is a JavaScript module I wrote which is available through npm via:

npm install specificity

The JavaScript module source and the website source are on GitHub.