Featured Clients List with Hover Descriptions

Startups and larger companies both have a need for repeat clients. Whether you’re selling a product or a service, clients will keep any business running successfully with repeat work and hopefully some extra referrals too. Once you’ve worked with some big-name clients you could show off and signify your talents by including their logos on your website.

Live DemoDownload Source Code

In this tutorial I want to demonstrate how you can build a client logo display which also includes some related quotes or descriptions. Visitors may want to read a company’s review or learn about a particular client’s experience with your business. This can be accomplished using CSS and a bit of jQuery. Take a look at my sample demo to see what the final product will look like.

Getting Started

First you’ll want to create a new index.html file with extra folders to hold the CSS, JS, and image files. Download a local copy of jQuery and be sure to include this file within the document head section.

1
2
3
4
5
6
7
8
9
10
11
<!doctype html>
<html lang="en-US">
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Type" content="text/html">
  <title>Clients List with Hover Info - Template Monster Demo</title>
  <link rel="shortcut icon" href="http://static.tmimgcdn.com/img/favicon.ico">
  <link rel="icon" href="http://static.tmimgcdn.com/img/favicon.ico">
  <link rel="stylesheet" type="text/css" media="all" href="css/styles.css">
  <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
</head>

I’ve also created a separate styles.css for the page structure & general design. In the page body I’ve created a few divs to split up the space vertically. At the top I’ve placed a blank header with a vibrant repeating background. This just fills up whitespace and gives the page a more unique design.

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
<header id="topbg"></header>
<div id="wrapper">
  <h1>Client Logos w/ Hover Details</h1>
 
  <p class="tagline">Hover any of the logos to see more information about the client or their review of our services.</p>
 
  <br><br>
 
  <div id="clients">
    <div id="info">
      <h4 id="clients-title">Our Clients Love Us!</h4>
      <h4 id="clients-info">fdsa</h4>
    </div>
 
    <div id="client-icons">
      <ul id="logos" class="clearfix">
        <li class="logoitm nick" data-info="Nick Producer: 'We highly recommend this website'"></li>
        <li class="logoitm dropbox" data-info="Dropbox has benefitted greatly from this service and their team"></li>
        <li class="logoitm kfc" data-info="This is an outstanding webapp even for larger businesses"></li>
        <li class="logoitm soundcloud" data-info="Every startup needs to try this out!"></li>
        <li class="logoitm bk" data-info="A beautiful dashboard for all our statistics"></li>
      </ul>
    </div>
  </div>
</div>

Notice the client testimonials div separates the review content from the logo images. Inside #clients I have another div with the ID #info. This contains two h4 elements – the default shows a generic message while the 2nd heading is originally hidden from view. It will come into view when a user hovers any of the logos contained within the #client-icons div.

Each of the list items will display a logo using a resized CSS background image. This is a better solution compared to using an image tag because this allows double-sized @2x retina graphics without as much code. Also the data-info attribute contains all the text needed to display when a user hovers each logo.

Page Design & Structure

My CSS file is generally basic with just a handful of browser resets. I’m using the Open Sans web font for each of the description headers. Everything is contained within a wrapper div centered on the page. It gets a little more confusing when we look into the client logo section.

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
/** clients list **/
#clients {
  display: block;
}
 
#info {
  position: relative;
  font-size: 14px;
  line-height: 1.5em;
  padding: 10px 0;
  font-weight: bold;
  color: #b9b9b9;
  text-transform: uppercase;
  text-align: center;
}
 
#clients-title { 
  display: block;
  width: 100%;
}
#clients-info {
  position: absolute;
  display: block;
  width: 100%;
  text-align: center;
  top: 25px;
  opacity: 0;
}
 
#client-icons {
  display: block;
  border-top: 1px solid #ebebeb;
}
 
#logos {
  display: block;
  padding-top: 20px;
}
 
#logos li {
  display: block;
  float: left;
  opacity: 0.7;
  -webkit-transition: opacity 0.3s linear;
  -moz-transition: opacity 0.3s linear;
  transition: opacity 0.3s linear;
}
#logos li:hover {
  opacity: 1;
}

The #info div uses relative positioning to handle each internal heading as required. The logo description header is positioned absolutely so that it can fade in & out of view with a slight animation. Instead of completely changing the display property I’ve set the opacity to 0 which still looks fine and is much easier to animate.

Each of the list items within #logos are using a CSS3 transition effect on the opacity. Whenever a user hovers onto one of the icons they fade into 100% opacity while the others stay at 30%. It’s a neat little UX trick to give users a better understanding of which item is currently being targeted.

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
#logos li.nick {
  width: 150px; /* icon size + 40px */
  height: 87px;
  background-image: url('../img/nickelodeon-logo@2x.png');
  background-repeat: no-repeat;
  background-position-x: 20px;
  -webkit-background-size: 110px 87px;
  -moz-background-size: 110px 87px;
  background-size: 110px 87px;
}
#logos li.dropbox {
  width: 140px;
  height: 89px;
  background-image: url('../img/dropbox-logo@2x.png');
  background-repeat: no-repeat;
  background-position-x: 20px;
  -webkit-background-size: 100px 89px;
  -moz-background-size: 100px 87px;
  background-size: 100px 89px;
}
#logos li.kfc {
  width: 127px;
  height: 87px;
  background-image: url('../img/kfc-logo@2x.png');
  background-repeat: no-repeat;
  background-position-x: 20px;
  -webkit-background-size: 87px 87px;
  -moz-background-size: 87px 87px;
  background-size: 87px 87px;
}
#logos li.soundcloud {
  width: 232px;
  height: 88px;
  background-image: url('../img/soundcloud-logo@2x.png');
  background-repeat: no-repeat;
  background-position-x: 20px;
  -webkit-background-size: 192px 88px;
  -moz-background-size: 192px 88px;
  background-size: 192px 88px;
}
#logos li.bk {
  width: 125px;
  height: 85px;
  background-image: url('../img/bk-logo@2x.png');
  background-repeat: no-repeat;
  background-position-x: 20px;
  -webkit-background-size: 85px 85px;
  -moz-background-size: 85px 85px;
  background-size: 85px 85px;
}

This second large block of code initiates the background images and sets up the individual logo heights. Notice how each logo has a width/height value along with a background-size value. The latter property will resize the retina image to half of its original dimensions. This way it looks crisp on retina screens and non-retina users won’t even notice the difference.

Also take note how the width value is 40px larger than the background-size value. This is because I’m using a 20px “margin” on either side to add space between the items. I use quotes around the word “margin” because these aren’t technically CSS margins – I’m just positioning the background image 20px from the left and giving an extra 20px space on the right. The end result is still the same and looks much better than cramming all the logos together.

Client Details with jQuery

Finally let’s move back into the HTML file and open a new block of JavaScript. I’m writing this code at the very bottom of the body tag. It may seem daunting at first, but it’s all quite logical and easy to comprehend with a little practice.

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
$(function(){
  var $infoheading = $('#clients-info');
  var $mainheading = $('#clients-title');
 
  $('.logoitm').on('mouseenter', function(e) {
    $target = $(e.currentTarget);
    var newtxt = $target.attr('data-info');
 
    $infoheading.css('opacity','0');
    $infoheading.html(newtxt);
 
    $mainheading.animate({'font-size':'0px'}, 400);
    $infoheading.animate({'opacity':'1','top':'10px'}, 400);
  }).on('mouseleave', function(e) {
    if(!e && window.event)e=event;
    target = e.relatedTarget || event.toElement;
 
    if($(target).hasClass('logoitm')) {
      // still hovering a logo, do nothing
    } else {
      $infoheading.animate({'top':'25px','opacity':'0'}, 200);
      $mainheading.animate({'font-size':'14px'}, 300); 
    }
  });
});

The top two variables target each of the main headers located within the #info div. This way they can be animated without creating new jQuery objects every time.

The class .logoitm is attached to event handlers which will check for mouseenter and mouseleave events. Each list item has this class so the code will work for an unlimited number of client logos.

Inside the first function we’re running code whenever a user hovers onto a logo. The hovered list item is obtained with e.currentTarget. If the user just moves from one logo to another we only want to fade the new text into view. Otherwise they’ve left the clients logo section and we want to completely remove the client text and switch back to the default header. This is accomplished using jQuery’s animate() method.

Once the user moves their mouse off a logo(after hovering) we then need to check where the mouse is located. The mouse could be on another logo, or it could be somewhere else on the page. If they’re hovering onto a different logo then we need to show new description text without removing and re-animating the old text.

There is a code discrepancy with some older browsers and the simplest way to obtain the hovered target is with e.relatedTarget and event.toElement(event = e in this scenario). If this new target has the .logoitm class then we know the user is hovering onto another logo and only the opacity property will animate.

Otherwise the user is hovering onto a different page element. In this case the client testimonial will fade out and slide down from view while the default heading will simultaneously animate from 0px to 14px font size. All of this animation is handled through jQuery and can be easily customized if needed.

Closing

This is one of my favorite effects because it works so nicely while also saving room on the page. It is fairly common amongst bigger companies but even freelancers could take advantage of this client testimonial interface. The logos are easily editable so you can swap for new companies without a lot of hassle. Feel free to download a copy of my source code and try out this effect on your own in personal or commercial web projects.