Sticky Captions Concept

A little trick on how to make captions of thumbnails or items "sticky" in order to stay visible in the window or viewport.

Sticky Captions Concept

View demo Download source

When creating thumbnail grids, we usually want to show image captions on hover to provide more information about the item. Image captions are usually shown in a very specific part of the thumbnail, either on the top, the middle or the bottom. When adding captions to the bottom of a thumbnail it can happen that a thumbnail that is overflowing the viewport (i.e. is partly beyond the “fold”) is being hovered but the caption won’t be seen because it appears on the bottom part of the image that is not visible. The user would have to scroll the page in order to see the bottom of the item and eventually the caption.

A small trick can solve that problem by simply making the caption “sticky”. This would mean that the caption will be visible not only at the bottom of every thumbnail but also in any place, sticking at the bottom of the page, if the thumbnail hovered is overflowing the current view.

What we basically do is to imitate position: sticky but since it’s not yet supported in many browsers, we’ll do a bit of JavaScript to achieve the same result. We’ll be using jQuery.

The main idea is to see when a hovered element overflows the viewport and show the caption in the right place by changing its position from absolute to fixed.

As an example, let’s take a simple grid with figures and figcaptions:

<div class="grid clearfix" id="grid">

		<img src="images/4.jpg">
			<a href="">Fall 7 Times Stand Up 8</a> by Erika Mackley

	<figure><!-- ... --></figure>
	<figure><!-- ... --></figure>
	<figure><!-- ... --></figure>
	<!-- ... -->

In our demo we use jQuery Masonry for creating a neat grid.

Let’s take a look at the structural styling of the figcaption element (to see all the styles, take a look at the style.css). The caption should be absolute and we will set a left of auto. This is important because when we switch to fixed positioning, we want the caption to start at the left of its parent container. We set a bottom value of -60 pixels in order to hide the caption (minus its own height). Note that the parent container needs to have its overflow set to “hidden”.

We also add a little transition which will animate the bottom to 0 when we hover over the figure:

.grid figure figcaption {
	position: absolute;
	left: auto;
	width: 100%;
	height: 60px;
	bottom: -60px;
	transition: bottom 0.2s ease-in-out;

.grid figure:hover figcaption {
	bottom: 0px;

Now, we want to check if the thumbnail that is being hovered is cut off at the bottom, i.e. out of the window view. If yes, we will change the caption position to fixed and set a width to it (otherwise it would just happily expand until the end of the page).

Let’s start by creating a custom jQuery selector called :bottomInViewport that we will help us determine if the caption of the image should be rendered or not.

$.extend( $.expr[':'], {
	bottomInViewport : function( el ) {
		var scrollTop = ( document.documentElement.scrollTop || document.body.scrollTop ),
			elOffsetTop = $( el ).offset().top,
			elH = $( el ).height(),
			descrH = $( el ).find( 'figcaption' ).outerHeight(true),
			winH = ( window.innerHeight && window.innerHeight < $( window ).height() ) ? window.innerHeight : $( window ).height();

		return ( elOffsetTop + elH > scrollTop && elOffsetTop + elH < scrollTop + winH ) || ( scrollTop + winH - elOffsetTop < descrH );

The function returns true if the element is completely inside the viewport, meaning that the bottom part is not cut off. It also returns true if the element is not in the viewport but the visible part is just too small to fit the caption. In these cases our script shouldn't do anything and the caption will simply show as usual. If the function returns false, we will show the caption by setting its position to fixed. Since we defined the bottom to be 0 in the CSS, it will show at the bottom of the page, right where we need it. We'll also have to set the width to its parent's width (the figure):

function changeToFixed( $description, itemWidth ) {
	$description.css({ position: 'fixed', width: itemWidth });

function resetStyle( $description, delay ) {
	setTimeout( function() { $description.css({ position: 'absolute', width: '100%'}); }, delay || 0 );

We will need to bind the mouseenter and mouseleave events to the items and also the scroll event to the window while hovering over an item:

$items.on( 'mouseenter mouseleave', function( event ) {

	var $item = $( this ), itemWidth = $item.width(),
		$description = $item.find( 'figcaption' );

	switch( event.type ) {
		case 'mouseenter' :

			if( !$ ':bottomInViewport' ) ) {
				$ 'sticky', true );
				changeToFixed( $description, itemWidth );
			$( window ).on( 'scroll', function () {
				var inviewport = $ ':bottomInViewport' );
				if( !inviewport && !$ 'sticky' ) ) {
					$ 'sticky', true );
					changeToFixed( $description, itemWidth );
				else if( inviewport && $ 'sticky' ) ) {
					$ 'sticky', false );
					resetStyle( $description );
			} );

		case 'mouseleave' :

			if( $ 'sticky' ) ) {
				$ 'sticky', false );
				resetStyle( $( this ).find( 'figcaption' ), 200 );
			$( window ).off( 'scroll' );

} );

When we hover over an item, we check if we should apply our trick or not. Also, we bind the scroll event to the window, where we will check if the trick should be applied or reset as we scroll. When we leave the item, we unbind the scroll event from the window and we reset the item's style (if the trick was previously applied to it).

And that's it! Take a look at the demo and hover over an item that is cut off at the bottom to see the effect. And then scroll. You will see how the caption sticks at the bottom until its "natural" position is reached.

I hope you enjoyed this little trick and find it useful!

Credits: the demo features Dribbble shots of illustrations by Erika Mackley.

View demo Download source


Tagged with:

ML is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

View all contributions by


Related Articles

Receive our bi-weekly Collective or blog updates right in your inbox.

Which newsletter would you like to receive?

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.