Jun 23 2012

Image comparison with CSS

Category: Software,WebdevelopmentSpiller @ 16:07

As I’m browsing the web I sometimes tend to look at the source of the webpages and if it is questionable I consider how this could be improved. However at times it is just to painful to watch…

This website was reviewing Blue-Ray releases of TV broadcasts and showed the differences by overlaying screenshots from the TV and BD versions. When you hovered over them with the mouse, the image switched. This was implemented like this:

    -webkit-transition: opacity .4s ease-in-out 0s;
    -moz-transition: opacity .4s ease-in-out 0s;
    -o-transition: opacity .4s ease-in-out 0s;
    transition: opacity .4s ease-in-out 0s;
<div style="position:relative;">
  <img src="http://i.minus.com/j5BVlrAz0767W.jpg" width="640" height="360" />
  <img class="himage" src="http://i.minus.com/j0KF3taUebpkC.jpg"
      width="640" height="360" onmouseover="this.style.opacity=0;"
      onmouseout="this.style.opacity=1;" style="position:absolute; top:0; left:0;"

Instead of having the CSS in the style sheet as it should, it is unneeded repeated like this for every image. It also uses the style attribute on the elements which is also considered bad practice. (XHTML 1.1 actually deprecated it, but nobody uses that anyway…) I don’t see why you would use JavaScript here either when it is just a simple hover effect.

The HTML can be much simpler:

<div class="himage">
  <img src="http://i.minus.com/j0KF3taUebpkC.jpg">
  <img src="http://i.minus.com/j5BVlrAz0767W.jpg">

As you can see, the only requirements to do this in CSS is a container and a way to identify this container, here done with a class. The CSS is much the same, just not done as attributes:

.himage{ position: relative; }
.himage img{
  -webkit-transition: opacity .4s ease-in-out 0s;
  -moz-transition: opacity .4s ease-in-out 0s;
  -o-transition: opacity .4s ease-in-out 0s;
  transition: opacity .4s ease-in-out 0s;

  opacity: 0;
  position:absolute; top:0; left:0;
.himage img:first-child{
  position: relative;
.himage:hover img{ opacity:1; }

There are some differences however:

  • The JavaScript have been replaced with the :hover selector (which is the last line).
  • Instead of specifying a fixed width and height, max-width have been used. The browser automatically resizes it to keep aspect ratio. (which was slightly wrong btw…)
  • To keep the HTML as clean as possible, the :first-child selector was used to differentiate the first and second img element. :last-child would have made the CSS simpler, however it is not supported in older versions of IE.

Live versions

You can watch the two versions here:

Note: The CSS is included in the HTML for ease of distribution, it should of course be in the style sheet.

Edit: My version behaves a bit differently, the hover area is the whole div and not just the img, if you want the same effect change .himage:hover img to .himage img:hover.


I cannot currently test it in IE7 and IE8 (and I don’t care about IE6), however I think it should work if you take the following in account:

  • The :first-child selector is supported from IE7, but not on content which have been inserted with JavaScript.
  • opacity is not supported in IE5-8, you will have to use MS filters in addition to opacity to get it working there. It is two extra lines of CSS for each time opacity is used, see this article on how to do it: quirksmode.org: opacity – IE compatibility note
  • The CSS3 transitions effects degrade gracefully. IE support will be in IE10, prefix not necessary (source).

Leave a Reply