Home > Blockchain >  How to make cursor tooltip not go offscreen
How to make cursor tooltip not go offscreen

Time:04-20

I'm working on a popup box that shows some text some position away from an element when the cursor hovers over it. You can see a simplified demo here: Demo image

CodePudding user response:

Sadly, I don't believe there is a way to do it with CSS only. However, by working on your fiddle, I've managed to add the functionality you wanted.

The way I went about it was just to include a reference to the container and check whether the popup position and size were inside the container BoundingClientRect.

This is the updated code for the popupShow function:

const showPopup = (top, left, text, container) => {
    popup.textContent = text;
  
  const containerBCR = container.getBoundingClientRect();
  const popupBCR = popup.getBoundingClientRect();
  const popupWidth = popupBCR.width,
        popupHeight = popupBCR.height;
  
  let popupTop = top   20,
        popupLeft = left   20,
      newPopupWidth;
  
  console.log("height: ", popupHeight);
  console.log("top: ", top);
  console.log("bottomPopup: ", top   20   popupHeight);
  console.log("bottomBoundary", containerBCR.bottom);
  
  if (left   20   popupWidth > containerBCR.right) {
    popupLeft = left - popupWidth;
    
    if (popupLeft < containerBCR.left) {
        popupLeft = containerBCR.left;
      newPopupWidth = left - containerBCR.left;
    }
  }
  
  if (top   20   popupHeight > containerBCR.bottom) {
    popupTop = top - popupHeight;
    
    if (popupTop < containerBCR.top) {
        popupTop = containerBCR.top;
    }
  }
  
  popup.style.top = popupTop   "px";
  popup.style.left = popupLeft   "px";
  popup.style.width = newPopupWidth;
  popup.style.visibility = 'visible';
}

As you can see, I've also edited the popup to use "visibility: hidden" instead of "display: none". This is because if the display is set to "none", we won't be able to get his size (there might be workarounds for this, though).

Try checking out the updated fiddle and tell me what you think.

I've pushed one circle a little bit further down because the code doesn't currently check for the padding of the popup, so it was overflowing a little (few pixels).

CodePudding user response:

This is based on quadrants, simple calculates if we are over 50% width and/or height and swaps the style to use the right or bottom instead. This doesn't care about the content of the popup, no measuring required.

const popup = document.getElementById("pop-up")

const parsePx = (px) => parseFloat(px.slice(0, -2))

const showPopup = (text, position) => {
  popup.textContent = text;
  popup.style.top = position.top;
  popup.style.left = position.left;
  popup.style.right = position.right;
  popup.style.bottom = position.bottom;
  popup.style.display = 'inline-block';
}

const hidePopup = () => {
  popup.style.display = 'none';
}

const circles = document.querySelectorAll(".red-circle")
circles.forEach(el => el.addEventListener('mouseover', (e) => {

  const hoveredEl = e.target;

  const textContent = hoveredEl.getAttribute('data-content');
  
  //get absolute position of elements
  let elBounds = hoveredEl.getBoundingClientRect();
    
  //get absolute position of parent;
  let ctBounds = popup.parentElement.getBoundingClientRect();
    
  //calculate relative positions
  let left =  elBounds.left - ctBounds.left   (elBounds.width / 2), 
    top = elBounds.top - ctBounds.top   (elBounds.height / 2),
    width = ctBounds.width,
    height = ctBounds.height

  //prepare position settings
  let position = { left: "auto", top: "auto", bottom: "auto", right: "auto" }
  
  //calculate if we're over 50% of box size
  if(top>ctBounds.height/2) position.bottom = ctBounds.height - top   20   'px'; else position.top = top   20   'px';
  if(left>ctBounds.width/2) position.right = ctBounds.width - left   20   'px'; else position.left = left   20   'px';
  
  showPopup(textContent, position);
  
}))

circles.forEach(el => el.addEventListener('mouseout', (e) => { hidePopup() }))
.container {  width: 200px;  height: 200px; border: 1px solid black;  position: relative;}
.red-circle { border-radius: 50%;  background: red;  width: 20px;  height: 20px;  position: absolute;}
#pop-up {  background-color: #EFEFEF;  padding: 0.25em;  position: absolute;}
<div >
  <div style="top:20px;left:20px;"  data-content="This is a red circle"></div>
  <div style="top:10px;left:150px;"  data-content="This is the top-right red circle"></div>
  <div style="top:140px;left:150px;"  data-content="This is the bottom-right red circle"></div>
  <div style="top:140px;left:15px;"  data-content="This is the bottom-left red circle"></div>
  <span style="display:hidden" id="pop-up"></span>
</div>

  • Related