You Are Browsing: CSS3

19th Jul

CSS3/HTML5 animated image tooltips

I’ve got a project coming up where, as part of a site rebuild, I would be replacing some old flash content with some updated and more semantic HTML5. The Flash content in question was a product image that had several icons on it, which when hovered would display a bit more information about that area of the product. As well as the fact this would then make the content accessible to devices such as the iPhone which don’t support Flash, it also makes the content easier to update using a CMS such as WordPress.

Here’s my recreation of this using HTML5 and CSS3. Please note this is just for demonstration purposes’ only, and the image is copyright to Chris Polack.

Ok, let’s check out some code! Here’s the HTML…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<section id="wrapper">
    <article>
        <h1>Image with pure CSS animated tooltips</h1>
        <figure>
            <a href="#" class="caption one">
                <aside>This is a dog, woof woof woof!</aside>
            </a>
 
            <a href="#" class="caption two">
                <aside>Check out this dudes haircut.</aside>
            </a>
 
            <a href="#" class="caption three">
                    <aside>Graffiti, ten points if you can read what it says.</aside>
            </a>
 
        <figcaption>Hover the <span class="dot">dot</span> for information.</figcaption>
        </figure>
    </article>
</section><!-- /#wrapper -->

So, reasonably straight forward… We’re using the new HTML5 figure element to wrap the whole image, and the new figcaption element for the main caption. I was going to use figcaption for all the captions but the HTML5 spec states that each figure should only have one figcaption. I decided to use another new element aside, for the pop-out captions as it seemed the most semantically appropriate: secondary content that is related to the main content. These are wrapped in anchor tags (using anchors to wrap block level elements is allowed and validates in HTML5).

Then on to the CSS…

1
2
3
4
5
6
7
section,
article,
aside,
figure,
figcaption {
    display:block;
}

First we run a quick reset to ensure our new elements will be displayed how we want them, and then the rest of the CSS…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
article {
    width:760px;
    margin:0 auto;
}
figure {
    background: url(img/tooltips.jpg) no-repeat;
    width:760px;
    height:500px;
    position:relative;
    margin:0;
    padding:0;
}
h1 {
    color:#fff;
    font-weight:normal;
}
a {
    position:absolute;
}
a:before {
    content: "";
    display:block;
    position: relative;
    top: 23px;
}
a:before,
span.dot {
    height:10px;
    width:10px;
    background:orange;
    border-radius:5px;
    vertical-align: middle;
}
span.dot {
    text-indent:-9999px;
    display:inline-block;
}
.caption.one {
    top: 210px;
    left: 305px;
}
.caption.two {
    top: 210px;
    left: 680px;
}
.caption.three {
    top: 360px;
    left: 330px;
}
a {
    width:174px; /*10px extra for dot, 10px for arrow, 4px for box-shadow */
    overflow:hidden;
    text-decoration:none;
    color:#333;
    font-size:12px;
}
a aside {
    background:#fff;
    padding:10px;
    width:130px;
    border-radius:4px;
    position:relative;
    margin:0 0 4px 0; /*to show box shadow*/
    box-shadow: 2px 2px 4px rgba(0,0,0,0.5);
    right:200px;
    opacity:0.0;
    -webkit-transition: all 0.2s linear;
    -moz-transition: all 0.2s linear;
    -o-transition: all 0.2s linear;
}
a aside:before {
    content: "";
    position: absolute;
    left: -8px;
    top: 10px;
    border-top:8px solid transparent;
    border-right:8px solid #fff;
    border-bottom:8px solid transparent;
    display: block;
    width: 0;
    height:0;
}
a:hover aside {
    right:-20px;
    opacity:1.0;
}
figcaption {
    background:#000;
    background:rgba(0,0,0,0.8);
    position:absolute;
    bottom:0;
    padding:10px;
    color:#fff;
    width: 740px;
}

So, there’s quite a bit going on there, but there’s only a few key points to look at.

  1. The orange dots are created with a :before pseudo class on the anchor‘s.
  2. The parent figure element is has relative positioning, allowing for it’s child anchor elements to be positioned absolutely.
  3. The anchor‘s have an explicit width set, and are set to hide the overflow.
  4. The asides are positioned relatively, hiding them from view, this position is then changed (and animated with CSS3 transitions) when the anchor is hovered.
  5. The arrows on the side of the captions are based on a CSS technique by Nicolas Gallagher using pseudo elements.

So far this works in all the modern browsers… but, using Modernizr we can get the same animated experience in older versions on internet explorer too. I grabbed a customised version, containing a basic HTML5 Shim and feature detection for CSS3 transitions.

1
2
3
4
5
6
7
<script src="modernizr.js"></script>
	<script>
		Modernizr.load({
			test: Modernizr.csstransitions,
			nope: ['http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js', 'animate.js']
		});
	</script>

I loaded in the script the my page head, and using Modernizr‘s built in Yep Nope library we can choose to load further resources based on browser support. Here we test if the browser supports CSS transitions, if the answer is no, we then load in a Google CDN copy of jQuery and our own animation file…

1
2
3
4
5
6
7
$(document).ready(function() {
	$('figure a').hover(function(){
				$(this).find('aside').animate({right:'-20px'},{queue:false,duration:500});
			}, function(){
				$(this).find('aside').animate({right:'200px'},{queue:false,duration:500});
			});
});

…which effectively does exactly the same as the CSS transitions. Tested in IE8 and works fine.

So thats that! I’d love to hear any suggestions of how the semantics or markup could be improved or if you find somewhere to put this to use! This could also be taken further, if necessary to force IE support for border-radius and box-shadow, but I’m perfectly content with old browsers seeing little orange squares rather than circles, as long as the interaction still works.

Here’s my demo.

8th Jul

Force Vertical Scroll Bars with CSS3

Here’s a quick and simple one!

The Problem: When using centered layouts, if you get to a page which doesn’t have enough content to cause the page to scroll, the layout will ‘jump’ slightly to the side compared to pages which have a scroll bar.

The Solution: For once, IE seems to do the right thing here and always forces a scroll bar. So we can use a new CSS3 property called “overflow-y”. This works in the latest versions of all the main browsers: Chrome, Safari, Firefox and Opera.

1
html {overflow-y: scroll;}

Wooooah there buddy!