CSS Pseudo Elements On Images

Image of a web page's HTML code

Please note: This post relates to an ealier website build, in a time when I thought that this kind of behaviour was perfectly acceptable. Please forgive me.

The Problem:

Forever on the lookout for ways to speed up the loading time of my website, I realised that the graphics for each of my music production, web development and online promotion pages were causing considerable overhead. This surprised me at first, as I’d taken the time to create SVGZ (zipped SVG) files (with a neat fall back to PNG for those less well-endowed browsers), but all-in, the six images on my ‘Web Development’ page came to an astounding 653KB – far too large for my liking. The reason for this was mainly due to a ‘background’ image (a browser window in the case of the ‘Web Development’ images) featuring in each instance and making heavy use of line and fill stylisation (in the form of Adobe Illustrator’s ‘Charcoal – Feather’ brush) – a huge and unnecessary overhead.

'Make Your Website More Useful' Graphic - 111KB
Figure 1: ‘Make Your Website More Useful’ Graphic From My ‘Web Development’ Page – A Whopping 111KB SVGZ File

The fact is that SVG is great for describing nice, clean lines (such as in diagrams, maps or any other kind of line art) but not so economical for when having to describe brush strokes or anything with rough edges.

Web Development Browser Detail
Figure 2: ‘Web Development’ Browser Detail – 108KB Of SVG Data Alone Due To Adobe Illustrator’s ‘Charcoal – Feather’ Brush

With a lot of duplicate code going on behind the scenes, I decided to try and find a more economical way of presenting the images. My plan was to make use of the pseudo :after CSS element. I thought that I would be able to render a file including just the browser window (the ‘background’ image) – reusing it in each image instance – and place each unique ‘icon’ image on top where needed, creating the full picture.

3D Diagram of Intended Stacked Images Using 'img:after'
Figure 3: 3D Diagram of Intended Stacked Images Using ‘img:after’

There was a problem however; I just couldn’t get the ‘icon’ image to show. It was then I came across the official spec, essentially forcing me to find a workaround. From the w3.org website:

Note. This specification does not fully define the interaction of :before and :after with replaced elements (such as IMG in HTML). This will be defined in more detail in a future specification.

Great. But there was light up ahead…

The Solution:

So while img tags can’t have :before or :after pseudo elements attached to them, others can. Perhaps not as semantic as I’d like (I hate adding extra elements in unnecessarily) but needed all the same.

The HTML:

<span id="website-more-useful" class="picon-wrapper">
	<img class="picon" src="web-dev-bg.svgz"/>
</span>

And the CSS:

.picon_wrapper {
	position: relative;
	display: block;
}
.picon_wrapper:after {
	content: '';
	position: absolute;
	width: 100%;
	height: 50px;
	left: 0;
	top: 50%;
	margin-top: -25px;
}
#website-more-useful.picon_wrapper:after {
	background: url('website-more-useful.svgz') center top no-repeat;
	background-size: auto 50px;
}

This of course then gave me the desired result (see figure 3); the total amount of image data decreased dramatically from 653KB to 114KB. Unfortunately, using this technique has added another server call, as by creating a separate ‘background’ image, the number of image files has increased from 6 to 7. With this in mind, I now plan to concatenate all of the ‘icon’ images into one SVG sprite sheet, bringing the total number of server calls down to two.

Leave a Reply

Comments will be approved pending moderation.