8

I need some help with the positioning of divs that appear on each #box's hover event. The hidden divs should appear over the box that was hovered in a way that:

  1. Each #tooltip div covers the box that was hovered plus the box next to it
  2. The tooltips of boxes 1 & 2 should cover the boxes to the right
  3. tooltips for box 3 & 4 should cover the boxes to their left

    (to make it more understandable, please see the attached image
  4. There will be several rows of boxes so positioning should be relative and not fixed to the page dimensions (i suppose)

So far I haven't managed to get the #tooltip positionings right (I know that one should be absolute and the other relative but no matter my efforts, I haven't nailed it yet).

Here's a jsfiddle to work on and this is the result i'm after:

enter image description here

Christofer Eliasson
  • 32,939
  • 7
  • 74
  • 103
bikey77
  • 6,384
  • 20
  • 60
  • 86

3 Answers3

3

I've put together a Fiddle that I think accomplishes what you describe.

The idea behind it is that i put a wrapper around the box and its tooltip. Then I listen for the mouse-hover events on the wrapper instead of the box and its tooltip individually. That way we avoid flickering when the tooltip is shown and therfor the cover the element that was initially hovered.

Making the wrappers position relative makes it possible to position the tooltip absolutely in relation to it. With a small if-statement in your jQuery hover-callback, we can then determine if the tooltip should be aligned with the left or right side of the box.

Attaching the code from the fiddle in the answer as well, if the fiddle would disappear for some reason.

Markup:

<div class="container">
    <div class="boxwrapper">
       <div id="box1" class="box">Box 1</div>
       <div id="tooltip1" class="tooltip">Description 1</div>
    </div>
    <div class="boxwrapper">
       <div id="box2" class="box">Box 2</div>
       <div id="tooltip2" class="tooltip">Description 2</div>
    </div>
    <div class="boxwrapper">
       <div id="box3" class="box">Box 3</div>
       <div id="tooltip3" class="tooltip">Description 3</div>
    </div>

    <div class="boxwrapper">
       <div id="box4" class="box">Box 4</div>
       <div id="tooltip4" class="tooltip">Description 4</div>
    </div>
    <div class="clearfix"></div>
</div>​

CSS:

.container {
    width: 450px;
    height: auto;
}

.box {
    background: #CCC;
    padding: 20px;
    float: left;
    height: 60px;
    width: 60px;
    list-style-type: none;
    margin: 5px;
    z-index: 1;
}
.tooltip {
    background: rgba(153,153,153,0.7);
    padding: 20px;
    height: 60px;
    width: 170px;
    margin: 5px;
    display:none;
    position: absolute;
    z-index: 2;
}
.clearfix {
    clear: both;
    float: none;
    height: 1px;
}
.boxwrapper {
    position: relative;
    float: left;
}

jQuery:

$(document).ready(function() {

    $(".boxwrapper").mouseenter(function() {
        var tooltip = $(".tooltip", this);
        tooltip.show();
        if ($(".boxwrapper").index(this) < 2) {
            tooltip.css("left", 0);
        } else {
            tooltip.css("right", 0);
        }
    });

    $(".boxwrapper").mouseleave(function(event) {
        $(".tooltip", this).hide();
    });

});  ​

Update:

If you are going to use it on more than one row of boxes, you will have to improve the if-statement somewhat to take that into consideration.

Christofer Eliasson
  • 32,939
  • 7
  • 74
  • 103
  • Although your solution is near perfect, there's a minor issue. When you go from box1 to box2 the box1 tooltip remains visible and the box2 hover isnt triggered. I'll upvote your answer though, its a very good one. Thank you very much. – bikey77 Sep 22 '12 at 14:02
3

Is this, what you're trying to get?

http://jsfiddle.net/xnrdp/1/

Mark
  • 6,033
  • 1
  • 19
  • 14
  • Yes! Exactly what I was trying to get! Mind to give us your insight on creating it? I know code is self explanatory but I'd like to hear the logic as well. Many, many thanks! – bikey77 Sep 22 '12 at 14:06
  • 1
    The main problem is, that the "unhover" (mouseleave or whatever) event is triggered as soon as you leave the tooltip area. This doesn't happen, if tooltip from box 1 is shown and you move your cursor to box 2. The cursor is still over the tooltip. To pass the mouse event to the element below (the box), you'll need to add pointer-events: none to the tooltip. – Mark Sep 22 '12 at 15:35
  • The wrapper around the boxes is required for positioning the tooltip. It has position: relative, so the tooltips can have absolute positioning within that container. Tooltips expanding to the right have the style "left: 0" while tooltips expanding to the left have the style "right: 0". – Mark Sep 22 '12 at 15:35
  • Thanks for explaining the logic, very simple but yet clever. I'm having a problem when browsing in IE9, the tooltip divs flicker alot. Perhaps there is a pointer-events equivalent for IE? – bikey77 Sep 23 '12 at 10:54
  • 1
    You're right, pointer-events isn't supported in IE9. You can make a workaround like that: http://jsfiddle.net/xnrdp/3/ The hover over the box is only used for displaying the tooltip. The tooltip closes, if the mouse leaves the tooltip area. On mouse movements, it checks, if the cursor is still over the 'buddy'. To make it easier to understand, I added a 'for' attribute to the tooltips, but you can also find the matching box otherwise. Oh, and you need to enable pointer-events again for the tooltips ;) – Mark Sep 23 '12 at 11:37
0

You can do this in CSS itself, using 'hover' selector and 'nth-of-type'.

Select every third-in-row:

:nth-of-type(3), :nth-of-type(7), :nth-of-type(13), :nth-of-type(15)

and fourth-in-row:

:nth-of-type(4), :nth-of-type(8), :nth-of-type(12), :nth-of-type(16)

And give its fly-out box the necessary properties.

Demo: http://dabblet.com/gist/3765761

Markup:

<div class='box'>1
    <div class='fly-out'></div>
</div>

<div class='box'>2
    <div class='fly-out'></div>
</div>

<div class='box right-aligned'>3
    <div class='fly-out'></div>
</div>
<div class='box right-aligned'>4
    <div class='fly-out'></div>
</div>

<div class='box'>5
    <div class='fly-out'></div>
</div>

<div class='box'>6
    <div class='fly-out'></div>
</div>

<div class='box right-aligned'>7
    <div class='fly-out'></div>
</div>

<div class='box right-aligned'>8
    <div class='fly-out'></div>
</div>

<div class='box'>9
    <div class='fly-out'></div>
</div>

<div class='box'>10
    <div class='fly-out'></div>
</div>

<div class='box right-aligned'>11
    <div class='fly-out'></div>
</div>

<div class='box right-aligned'>12
    <div class='fly-out'></div>
</div>

<div class='box'>13
    <div class='fly-out'></div>
</div>

<div class='box'>14
    <div class='fly-out'></div>
</div>

<div class='box right-aligned'>15
    <div class='fly-out'></div>
</div>
<div class='box right-aligned'>16
    <div class='fly-out'></div>
</div>

css:

* {
margin: 0; 
padding: 0; 
box-sizing: border-box; /* paulirish.com/2012/box-sizing-border-box-ftw/ */
position: relative; 
}

body {
    width: 440px;
    margin: 0 auto;
    }

.box {
    width: 100px;
    height: 100px;
    border: 1px solid #999;
    float: left;
    margin: 5px;
    }
    .fly-out {
        position: absolute;
        top: 0;
        background: rgba(0,0,0,.4);
        opacity: 0;
        z-index: -1;
        }
    .box:hover .fly-out {
        z-index: 1;
        opacity: 1;
        height: 100%;
        width: 210px;
        }
    .box:nth-of-type(3):hover .fly-out,
    .box:nth-of-type(7):hover .fly-out,
    .box:nth-of-type(11):hover .fly-out,
    .box:nth-of-type(15):hover .fly-out,
    .box:nth-of-type(4):hover .fly-out,
    .box:nth-of-type(8):hover .fly-out,
    .box:nth-of-type(12):hover .fly-out,
    .box:nth-of-type(16):hover .fly-out,

    .right-aligned {
        left: -110px;
        right: 0;
        background: rgba(0,0,120,.7);
        }

In your markup, the 'tool-tip' was outside the box and it had 'visibility: hidden' which is pretty much like giving it 'opacity: 0'. While it can't be seen, it's still there. To actually make it unavailable to the layout, you need 'display: none', but then you wont be able to animate it properly using CSS transitions.

Note: Like Christofer Eliason mentioned in the comment below, the ':nth-of-type' selector is not very well supported, so you can either add a class to every div you want the fly-out to be right aligned or look into using a jquery version of 'nth-of-type': https://stackoverflow.com/a/4761510/604040.

I used the ':nth-of-type' selector because you can control the fly-out's alignment from the CSS itself without having to add a class to new boxes if they are added dynamically, this can be a tad complex mathematically(at least for me).

But if you're fine with it, I've added a class '.right-aligned' to the boxes in 3rd & 4th in each row, you can delete this block in the CSS and you're still good:

.box:nth-of-type(3):hover .fly-out,
.box:nth-of-type(7):hover .fly-out,
.box:nth-of-type(11):hover .fly-out,
.box:nth-of-type(15):hover .fly-out,
.box:nth-of-type(4):hover .fly-out,
.box:nth-of-type(8):hover .fly-out,
.box:nth-of-type(12):hover .fly-out,
.box:nth-of-type(16):hover .fly-out
Community
  • 1
  • 1
carpenumidium
  • 1,193
  • 11
  • 18
  • 1
    It would probably be good to mention that the `:nth-of-type()` selector has very limited IE support (IE9+) and doesn't work well in Opera. Here is [a reference](http://www.quirksmode.org/css/contents.html) – Christofer Eliasson Sep 22 '12 at 10:54
  • Right, the reason I used it was because it'd be easier to control from the CSS itself if new boxes are added vs adding a class to every third/fourth box in the html which can be quite complex maybe. – carpenumidium Sep 22 '12 at 11:47