25

I am using popper.js for displaying more post categories if trigger clicked. But after i click it, the initial position is wrong (more right). When popper opened and i scroll the position of popper is updated - this state need to be initial.

I found that CSS position transform of popper is calculated wrong for my usage. But don't understand, why it is recalculated to right number after scroll or any window resize. Check the Codepen below.

My JS:

$(function () {
 var element = document.getElementById('more-cats');
 var dropdown = document.getElementById('tooltip');

 var catsTooltip = new Popper ( element, dropdown, {
      placement: 'bottom-end'
 });

 $(element).click(function(e) {
      $(dropdown).toggle();
      e.preventDefault();
 });

});

Codepen

Thank you, if you have some ideas, what part of code i wrote wrong.

freddy87
  • 265
  • 1
  • 3
  • 8

2 Answers2

39

That's because Popper.js needs the popper element to be rendered in the DOM (aka, have a position in the document) to be able to properly compute its position.

You are initializing Popper.js when the element is hidden, and then you toggle its visibility to show it, but Popper.js doesn't know that something changed.

When you scroll the page, or resize it, Popper.js updates the position of your popper because it listens by default to these events.

You should manually run catsTooltip.scheduleUpdate() after .toggle() to have it properly positioned.

https://codepen.io/FezVrasta/pen/PJjWWZ

Fez Vrasta
  • 14,110
  • 21
  • 98
  • 160
  • 2
    Thanks for taking the time in adding the codepen. Made it very clear and gave us a playground. – Nick Steele Jul 30 '18 at 13:08
  • Thanks for share! Helpful! – Ioan Apr 07 '19 at 21:17
  • 8
    In popper version 2, the `scheduleUpdate()` method has been renamed to `update()`. So, it's just `catsTooltip.update()` now and it returns a promise. https://popper.js.org/docs/v2/migration-guide/#8-update-method-names – Abdalla Arbab Feb 27 '20 at 16:21
8

Just wanted to share what i did for mine to work, just in case it helps someone else.

I think @Fez's and @Abdalla's solutions could still be helpful but for me it had to do with accidentally using display: none; for my tooltip container. Amazing what the documentation can do lol.

So what i did to my .tooltip container is this:

/* Hide the popper when the reference is hidden */
.tooltip[data-popper-reference-hidden] {
  visibility: hidden;
  pointer-events: none;
}

.tooltip {
  // display: none; <---- don't do this 
  opacity: 1; // do this

  background-color: white;
  border: 1px solid #c6c6c6;
  box-shadow: 1px 1px 8px 1px rgba(0, 0, 0, 0.2);
  line-height: 1.5;
  padding: 4px 8px;
  border-radius: 4px;
  z-index: -1; // this keeps it from blocking other elements when it's hidden

  &:hover {
    visibility: visible;
    pointer-events: auto;
    opacity: 1; // oh yeah 
    z-index: 1;
  }
}
Omar
  • 421
  • 4
  • 10
  • 2
    Amazing. Thank you very much for your answer. I was also using `display: none` in my custom react dropdown made with downshift,.js and this was the culprit for my dropdown opening completely off the initial document area, creating strange horizontal scroll in Chrome browser. After taking down that display: none and hiding it with `visibility` and `pointer-events` everything worked like a charm. No need for `opacity` if you have that `visibility` I think. – Matt Leonowicz Dec 08 '20 at 17:51