4

I have many boxes with differents widths. All of them are displayed inline-block so they will be distributed differently as window width changes.

Every box has a big tooltip that will show on hover. These tooltips have a fixed width and height, same for all of the boxes.

These tooltips are position:absolute over the boxes and centered with:

left: 50%;
margin-left: -halfwidth; 

My problem is that if the box is close to window left or right they will be partially hidden (I have no problem with top and bottom, they will never reach those edges)

Is there any easy way with javascript (better if jquery) to detect when the element is out of the viewport and then change the left property accordingly to prevent it?

any help, hint or comment will be greatly apreciated. Thank You

JSFIDDLE

html, body {margin:0;padding:0;height:100%;}
ul {
  width:100%; 
  text-align:center;
  position:relative;
  top:50%;
  transform:translateY(-50%);
  padding:0;
  }
li {
  display: inline-block;
  background-color: red;
  width: 100px;
  height: 25px;
  margin-right: 10px;
  position: relative;
}

.hover-element {
  position: absolute;
  background-color: yellow;
  z-index: 9999;
  width: 350px;
  height: 175px;
  left: 50%;
  margin-left: -175px;
  bottom:25px;
  display: none;
  border:1px solid #000;
}

li:hover .hover-element {
  display: block;
}
.hover-element:hover {
  visibility: hidden;
}
<ul>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
</ul>
Alvaro Menéndez
  • 8,766
  • 3
  • 37
  • 57

5 Answers5

3

Thats all you need, i detected the offset left position of the div, and added the class to li and a small tweaks in css.

$("li").mouseenter(function(){
 var f = $(this).find('.hover-element');
    var rightEdge = f.width() + f.offset().left;
    var leftEdge = f.offset().left;
    var screenWidth = $(window).width();
    if(leftEdge < 0){
    $(this).addClass("left");
    $(this).removeClass("right");
    }
    else if(rightEdge > screenWidth){
    $(this).addClass("right");
    $(this).removeClass("left");
    }
    else{
    $(this).removeClass("right lefft");
    }


});

$("li").mouseleave(function(){
$(this).removeClass("right lefft");
}) 
html, body {margin:0;padding:0;height:100%;}
ul {
  width:100%; 
  text-align:center;
  position:relative;
  top:50%;
  transform:translateY(-50%);
  padding:0;
  }
li {
  display: inline-block;
  background-color: red;
  width: 100px;
  height: 25px;
  margin-right: 10px;
  position: relative;
}

.hover-element {
  position: absolute;
  background-color: yellow;
  z-index: 9999;
  width: 350px;
  height: 175px;
  left: 50%;
  margin-left: -175px;
  bottom:25px;
  display: none;
  border:1px solid #000;
}
li.left .hover-element{
    left: 0;
    margin-left: 0;
}
li.right .hover-element{
    margin-left: 0;
    left: auto;
    right: 0;
}
li:hover .hover-element {
  display: block;
}
.hover-element:hover {
  visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
</ul>
Awsme Sandy
  • 1,398
  • 7
  • 20
  • Ty for your answer. It's correct. I upvote your answer but I have to give credit to JiangangXiong as his answer works better as it move the tooltip as I was whising, just enough right or left to avoid beign hidden. Anyway ty so much – Alvaro Menéndez Sep 20 '17 at 12:55
2

Have a look:

var windowWidth = document.body.scrollWidth || window.innerWidth;
$('li').on('mouseenter', function(e){
  var $hover = $(this).find('.hover-element');
  var coords = $hover[0] && $hover[0].getBoundingClientRect();
  var rightDistance = 0;
  
  if (coords.left <= 0) {
    $hover.css({
      'left': ($hover.css('left').split('px')[0] - coords.left) + 'px'
    })
  }
  rightDistance = windowWidth - coords.left - $hover.width() - 2 * $hover.css('borderWidth').split('px')[0];
  if (rightDistance < 0) {
    $hover.css({
      'left': ($hover.css('left').split('px')[0] - (-rightDistance)) + 'px'
    })
  }
  $('p').html($hover.css('left') + '/' + coords.left)
})
html, body {margin:0;padding:0;height:100%;overflow-x: hidden;}
ul {
  width:100%; 
  text-align:center;
  position:relative;
  top:50%;
  transform:translateY(-50%);
  padding:0;
  }
li {
  display: inline-block;
  background-color: red;
  width: 100px;
  height: 25px;
  margin-right: 10px;
  position: relative;
}

.hover-element {
  position: absolute;
  background-color: yellow;
  z-index: 9999;
  width: 350px;
  height: 175px;
  left: 50%;
  margin-left: -175px;
  bottom:25px;
  display: none;
  border:1px solid #000;
}

li:hover .hover-element {
  display: block;
}
.hover-element:hover {
  visibility: hidden;
}
<script
  src="https://code.jquery.com/jquery-2.2.4.min.js"
  integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
  crossorigin="anonymous"></script>
<ul>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
  <li>
    <div class="hover-element"></div>
  </li>
</ul>
JiangangXiong
  • 2,326
  • 1
  • 12
  • 14
1

The following links are a starting point for your question (if not the actual answer).

Is there any easy way with javascript (better if jquery) to detect when the element is out of the viewport and then change the left property accordingly to prevent it?

How to tell if a DOM element is visible in the current viewport?

Absolute position of an element on the screen using jQuery

1

I'm going to mention the steps here. If you'd need the code, just ask for it. I am currently on my mobile device, so typing the code would get hard!

Steps

  • To make things easy to include JS, change the display property using JS. Accomplish this using a mouse event on each of the list items, that changes their respective tooltip's display property. (Here's how to access the respective child)

In the same hover event, do these:

  • After changing the display, check if the tooltip element is in viewport. You can refer to the link Victor Medeiros provided.

  • If is not completely in viewport, change the margin-left property to -175px - (the number of pixels it crossed the boundary by). I just realised, if it crosses the viewport, just set the margin-left or margin-right (as applicable, find it by getBoundingClientRect) to 0.

Yep, that's it! I hope that should work, I haven't tried it out. What's the result?

Community
  • 1
  • 1
Shiven Sinha
  • 656
  • 5
  • 14
-5

Change

li {
    display: inline-block;
    background-color: red;
    width: 100px;
    height: 25px;
    margin-right: 10px;
    position: relative;
}

Whit

li {
    display: inline-block;
    background-color: red;
    width: 100px;
    height: 25px;
    margin-right: 10px;
    position: static;
}
yavonz15
  • 178
  • 6