yoksel\u2019s SVG encoder<\/a> for this. So now we have a dataURI containing another dataURI. DataURInception!<\/p>\nWhen encoding the SVG we get some text to paste into the url()<\/code>, but it\u2019s worth noting that we need to prepend some metadata to make it display: data:image\/svg+xml;charset=utf-8,<\/code>. The charset<\/code>-stuff is important: it makes the encoded SVG play nicely across browsers.<\/p>\n.post-header {\r\n background-color: #567DA7;\r\n background-size: cover;\r\n background-image: url(data:image\/svg+xml;charset=utf-8,%3Csvg...);\r\n}<\/code><\/pre>\nAt this point, the whole page, including the image, is 1 request and 5KB<\/em> when using GZIP.<\/p>\nGetting the URL to the big image<\/h3>\n
Next, we create a rule for the enhanced header, where we set up the huge background image.<\/p>\n
.post-header-enhanced {\r\n background-image: url(largeimg.jpg);\r\n}<\/code><\/pre>\nInstead of just toggling the class name, thus triggering the big image to load, we want to preload the big image and then<\/em> apply the class name. This is so that we can smoothly animate the switch later, being reasonably sure the large image is done loading. Since we don\u2019t want to hard-code the image URL in both the CSS and the JavaScript, we\u2019ll grab the URL using JavaScript from inside the styles. As the class name is not yet applied, we can\u2019t just look at headerElement.style.backgroundImage<\/code> etc \u2013 it doesn\u2019t know about the background yet. To solve this, we\u2019ll use the CSSOM \u2013 the CSS Object Model, and the read-only JS properties that let us traverse the CSS rules.<\/p>\nThe following snippet finds the class name for the enhanced header, then grabs the URL with some regex. After that it preloads the image and triggers the added class name once that\u2019s done.<\/p>\n
<script>\r\nwindow.onload = function loadStuff() {\r\n var win, doc, img, header, enhancedClass;\r\n \r\n \/\/ Quit early if older browser (e.g. IE 8).\r\n if (!('addEventListener' in window)) {\r\n return;\r\n }\r\n \r\n win = window;\r\n doc = win.document;\r\n img = new Image();\r\n header = doc.querySelector('.post-header');\r\n enhancedClass = 'post-header-enhanced';\r\n\r\n \/\/ Rather convoluted, but parses out the first mention of a background\r\n \/\/ image url for the enhanced header, even if the style is not applied.\r\n var bigSrc = (function () {\r\n \/\/ Find all of the CssRule objects inside the inline stylesheet \r\n var styles = doc.querySelector('style').sheet.cssRules;\r\n \/\/ Fetch the background-image declaration...\r\n var bgDecl = (function () {\r\n \/\/ ...via a self-executing function, where a loop is run\r\n var bgStyle, i, l = styles.length;\r\n for (i=0; i<l; i++) {\r\n \/\/ ...checking if the rule is the one targeting the\r\n \/\/ enhanced header.\r\n if (styles[i].selectorText &&\r\n styles[i].selectorText == '.'+enhancedClass) {\r\n \/\/ If so, set bgDecl to the entire background-image\r\n \/\/ value of that rule\r\n bgStyle = styles[i].style.backgroundImage;\r\n \/\/ ...and break the loop.\r\n break; \r\n }\r\n }\r\n \/\/ ...and return that text.\r\n return bgStyle;\r\n }());\r\n \/\/ Finally, return a match for the URL inside the background-image\r\n \/\/ by using a fancy regex I Googled up, as long as the bgDecl \r\n \/\/ variable is assigned at all. \r\n return bgDecl && bgDecl.match(\/(?:\\(['|\"]?)(.*?)(?:['|\"]?\\))\/)[1];\r\n }());\r\n\r\n \/\/ Assign an onLoad handler to the dummy image *before* assigning the src\r\n img.onload = function () {\r\n header.className += ' ' +enhancedClass;\r\n };\r\n \/\/ Finally, trigger the whole preloading chain by giving the dummy\r\n \/\/ image its source.\r\n if (bigSrc) {\r\n img.src = bigSrc;\r\n }\r\n};\r\n<\/script><\/code><\/pre>\nThe script quits early if addEventListener<\/code> is not supported, which should overlap nicely with the rest of the support needed. As far as I can tell, all reasonably modern SVG-supporting browsers support the rest of the CSSOM and other JavaScript features used.<\/p>\nAnimating the swap<\/h3>\n
It\u2019s a bit of a bummer that we didn\u2019t get to use the filter()<\/code>-function, after finding out that it exists and all. So we\u2019ll add an animated effect, when swapping in the high-res image. This only works in WebKit nightlies at the moment, and we can safely use the @supports<\/code>-rule to scope the changes. Here\u2019s an animated GIF to show the effect in action:<\/p>\n