Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent an absolutely positioned popover from clipping out of its container?

function myclick() {
  let node = document.createElement("div");
  node.className = "popover";
  node.innerText = "hello world hello world";
  event.srcElement.appendChild(node);
}
.container {
  width: 230px;
  height: 200px;
  border: 1px solid #ddd;
  display: flex;
  flex-flow: wrap;
}

.tag {
  border: 1px solid #ddd;
  padding: 5px;
  margin: 5px;
  display: flex;
  height: 20px;
  position: relative;
}

.popover {
  position: absolute;
  top: 30px;
  width: 60px;
  left: 0px;
  background-color: #dfdfdf;
}
<div class="container">
  <div class="tag" onclick="myclick();">apple</div>
  <div class="tag" onclick="myclick();">banana</div>
  <div class="tag" onclick="myclick();">carrot</div>
  <div class="tag" onclick="myclick();">dog</div>
  <div class="tag" onclick="myclick();">elephant</div>
  <div class="tag" onclick="myclick();">firetruck</div>
</div>

I've developed a complete reproduction of the issue I'm facing above. Basically, I have popovers appear from tags when you click on them. This all works perfectly, except for when the tag is near the edge of its container. In this case the tag clips out of the container. In the provided example if you click "dog" then the popover clips outside of the container div.

Rather, I would like the popover to move to the left as much as necessary in order to prevent itself from clipping out of the container. I've been messing with it for a while but I cannot quite figure out how to accomplish this.

like image 836
Ryan Peschel Avatar asked Dec 05 '25 08:12

Ryan Peschel


1 Answers

You can try this. I added a javascript function called onEdge that is suppose to detect how close a child element is to the edge. This will probably need modified for your needs (like setting how close to the parents edge you consider "too close").

function onEdge(child) {
  if (child.parentElement.offsetWidth < (child.offsetLeft + child.offsetWidth))
    return true;
  return false;
}

function myclick(elm) {
  var addClass = onEdge(elm);

  let node = document.createElement("div");
  node.className = "popover" + (addClass ? " right" : "");
  node.innerText = "hello world hello world";
  event.srcElement.appendChild(node);
}
.container {
  width: 230px;
  height: 200px;
  border: 1px solid #ddd;
  display: flex;
  flex-flow: wrap;
}

.tag {
  border: 1px solid #ddd;
  padding: 5px;
  margin: 5px;
  display: flex;
  height: 20px;
  position: relative;
}

.popover {
  position: absolute;
  top: 30px;
  width: 60px;
  left: 0px;
  background-color: #dfdfdf;
}

.popover.right {
  left: auto;
  right: 0;
}
<div id="tag-container" class="container">
  <div class="tag" onclick="myclick(this);">apple</div>
  <div class="tag" onclick="myclick(this);">banana</div>
  <div class="tag" onclick="myclick(this);">carrot</div>
  <div class="tag" onclick="myclick(this);">dog</div>
  <div class="tag" onclick="myclick(this);">elephant</div>
  <div class="tag" onclick="myclick(this);">firetruck</div>
</div>
like image 94
zgood Avatar answered Dec 07 '25 20:12

zgood