jQuery DemoCSS3 DemoDownload Source Code

Structuring the Page

My jQuery version has a slightly different HTML setup than the CSS3 adaptation. Obviously we will need a copy of the jQuery library, but even more important is the handling of the details panel. With JS I am calling a single HTML element to replace the inner HTML content. CSS3 requires unique div elements next to each of the thumbnail links, and thus adds more bulk into your page.


This code is located in the body of my jQuery version. The thumbnails are split into list items where we extract information for the details panel from HTML attributes. These details can be found in the anchor link, the image tag, and a related meta tag which holds the content description. I’m also using an HTML5 data attribute for the publication date.
Towards the bottom you’ll notice a single container div with the ID #details-pane. Targeting this object in jQuery allows us to replace inner values for the hover details. Now let’s take a look at one list item element from the CSS3 version.


I’ve changed the ID to a class of .details-pane because we need multiple adjacent divs next to each thumbnail. CSS3 checks when the user is hovering on the link and displays the sibling div, which already contains all the information. So another benefit when using CSS3 is that we don’t need to pull out information from attributes each time the target display changes.
I want to start with the CSS3 example because my jQuery code is a bit more complicated. This could be another reason to stick with the frontend HTML/CSS version, although this effect will be lost in older legacy browsers.

Hover Details with CSS3

The way this all works is using a plus(+) sign in the selector. CSS will target the very last element of the selector, in this case our .details-pane which is found directly next to each anchor link. I’ve given the links a class of .hvrlink so they are easier to identify.


I hope there’s nothing too complicated in this initial setup block. Each list item is floated left with a wide margin to position only two thumbnails per row. These list items contain the thumbnail link and the details window. We give the
  • a relative position so that now we can use absolute positioning on the hover panel.
    What you might find interesting is the position change between the first two links. For every-other link I’ve added a class of .rightside onto the details panel container. Originally we push the hover panel over 290px to the left because this is the length of the thumbnail. But on the right column we get this panel hovering way off-screen, so instead we’d like it to appear over to the left. This uses a negative left position based on the full 530px width of the details pane itself.


    These last two selectors are all we need to get the hover setup properly. When the user mouses over a thumbnail link we immediately display the related .details-pane. The second block of code keeps it displaying even when the user mouses off the thumbnail onto the details, so that it always displays until the users completely moves out of that particular list item.

    Moving to jQuery

    Let’s tackle the JS code found at the bottom of my original index.html file. Much of the CSS code is similar, but it’s even shorter and easier to read because we don’t need absolute values. This is handled instead by jQuery calculations which may appear complicated – but it all does make sense once you think about it.


    I am targeting the thumbnail image for the hover event listener and, once this is triggered, we set up a whole bunch of variables. The first big block of code obtains all the important information we need to append into the hover panel container.
    Next we need to gather coordinates to understand where this details panel should appear. The y-coordinate won’t change based on the position, but the x-coordinate will if we are hovering on the right column. I have a logic statement checking against the current image position divided by the whole window using $(window).width(). If the image is beyond 50% of the total page width, then we need it displaying over to the left side instead of the right.


    These next set of code is replacing internal HTML values within the details pane using variables defined earlier. At the end we update inline CSS properties to change display: block and make it appear on the page. When hovering off the thumbnail, it will auto-hide the display again, unless we hover onto the details pane itself. This hover will be captured using a whole separate event listener which requires a bit of tricky logic.


    Notice I am using two separate .on() methods attached to the same jQuery selector. You might consider pairing these into a jQuery chain along with other similar event listeners. When hovering we just need to keep the panel displayed as a block element. But when leaving the details panel we only wish to hide it when the user isn’t hovering onto the same thumbnail image used for displaying in the first place.
    The variable e is returned from each mouseout event, telling us which new element is being hovered. Applying the property parentNode we can check out where this new element is contained. I have four separate logic checks inside this statement, and three of them are checking against objects within the details pane. The variable name this refers to the #details-pane.
    We need to check in case the user hovers onto the h3 element, the paragraph, or even the image(which is embedded into an anchor link and a div). If so then we do not hide anything.
    I’m also checking with the nodeName property in case the user hovers off the details pane into the body. If the node returns IMG then it shouldn’t try to hide anything right away. This is more of a hacked solution because the only images in my demo relate to the thumbnails themselves. So when hovering onto the image we still want to keep the panel displayed, otherwise it gets hidden using jQuery’s .css() method.
    I’ve been unable to solve with a better solution but I’d love to hear feedback from other developers. It may be possible to check against the image class, but unfortunately you can’t do this with a nodeName property. You’ll find my commented code console.log(e.nodeName) which you can run to check what these properties are returning to the browser.
    jQuery DemoCSS3 DemoDownload Source Code