1
votes

I have something vaguely like the following:

<div id="body">
  surrounding text 
  <div id="pane" style="overflow: auto; height: 500px; width: 500px;">
    lots and lots of text here
    <span id="some_bit">tooltip appears below-right of here</span>
  </div>
  more surrounding text (should be overlapped by tooltip)
</div>

and:

<div id="tooltip" style="width: 100px; height: 100px;">Whee</div>

What I want to do is insert the tooltip such that it is positioned above the pane it's in. If it's attached to an element that's next to the pane boundary (like above), then it should be visible above the pane, and above the text surrounding the pane.

It should NOT a) extend the pane, such that you have to scroll down to see the tooltip (like in http://saizai.com/css_overlap.png), or b) be cut off, so you can't see all of the tooltip.

I'm inserting this with JS, so I can add a wrapper position:relative div or the like if needed, calculate offsets and make it position:absolute, etc. I would prefer to not assume anything about the pane's position property - the tooltip should be insertable with minimal assumptions of possible page layout. (This is just one example case.)

It's for a prototype tooltip library I'm writing that will be open source.

ETA: http://jsfiddle.net/vCb2y/5/ behaves visually like I want (if you keep re-hovering the trigger text), but would require me to update the position of the tooltip on all DOM changes and scrolling behavior. I would rather the tooltip be positioned with pure CSS/HTML so that it has the same visual behavior (i.e. it overlaps all other elements) but stays in its position relative to the target under DOM changes, scrolling, etc.

ETA 2: http://tjkdesign.com/articles/z-index/teach_yourself_how_elements_stack.asp (keep defaults except set cyan div 'a' to position:relative; imagine 'A' is the pane and 'a' the tooltip) seems to more closely behave as I want, but I've not been able to get it to work elsewhere. Note that if you make 'A' overflow: auto, it breaks the overlapping behavior of 'a'.

3
Hey Sai - I'm having trouble picturing it my head. Any chance you have a design or a sketch for it?Marko

3 Answers

2
votes

I can't think of a pure HTML/CSS solution for this.

The overflow declaration is the issue here. If the tooltip is in #pane:

  1. you establish a positioning context within #pane, then the tooltip shows next to #some_bit (regardless of scrolling, etc.) but it gets cut-off.

  2. you do not establish a positioning context, then the tooltip is not clipped but it has no clue where #some_bit is on the page.

I'm afraid you'll need JS to monitor where #some_bit is on the page and position the tooltip accordingly. You'd also need to kill that tooltip as soon as #some_bit is outside of the viewing area (not an issue if the trigger is mouseover).

Actually, if the trigger is mouseover then you may want to use the cursor coordinates to position the tooltip (versus calculating the position of #some_bit).

1
votes

I would just put the tooltip outside of the #pane div and position it absolutely using JavaScript since you're using JS anyway.

I don't use Prototype so I don't know how it's done in Prototype, but in jQuery, you'd use $(element).position() to get the element position. If you have to do it manually, it's a little more complicated.

And you'll probably want to add a little extra logic to prevent the tooltip from extending outside of the document.

1
votes

Edit: CSS used

#tooltip {
    z-index: 9999;
    display: none;
    position: absolute;
}

JS used

Note: in jQuery, but it should be easy to change it to Prototype syntax.

$('#some_bit').hover(function() {
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    // hovered element
    var offset = $(this).offset();
    var top = offset.top + docViewTop;
    var left = offset.left;
    var width = $(this).width();
    var height = $(this).height();
    var right = left + width;
    var bottom = top + height;

    // pane
    var poffset = $('#pane').offset();
    var ptop = poffset.top + docViewTop;
    var pleft = poffset.left;
    var pwidth = $('#pane').width();
    var pheight = $('#pane').height();
    var pright = pleft + pwidth;
    var pbottom = ptop + pheight;

    // tooltip
    var ttop = bottom;
    var tleft = right;
    var twidth = $('#tooltip').width();
    var theight = $('#tooltip').height();
    var tright = tleft + twidth;
    var tbottom = ttop + theight;

    if (tright > pright)
        tleft = pright - twidth;
    if (tbottom > pbottom)
        ttop = pbottom - theight;
    if (tbottom > docViewBottom)
        ttop = docViewBottom - theight;
    $('#tooltip').offset({top: ttop, left: tleft});
    $('#tooltip').css('display', 'block');
}, function() {
    $('#tooltip').hide();    
});

Edit: See it here.