Search code examples
javascripthtmljquerycsstippyjs

TippyJS tooltip is positioned weird but shows correctly after scrolling the page or resizing the window


I am using TippyJS to show a tooltip but for some reason when first click the tooltip it is positioned way too much to the right, and if you have a small screen it will even go outside of view.

Example:

Out of screen Weird position

While after I scroll a bit, or resize the page it gets positioned correctly.

Example:

enter image description here

What could be causing this behaviour?

Example codepen (shopping cart is empty but still has the same behaviour when clicking/scrolling): https://codepen.io/twan2020/pen/ZEBvYXv

I've tried setting boundary:viewport in the options like this:

$( ".carttip" ).each(function( i ) {
    tippy(this, {
        theme: 'blue',
        trigger: 'click',
        allowHTML: true,
        animation: 'scale-subtle',
        maxWidth: 400,
        boundary: 'viewport',
        interactive: true,
        content: function (reference) {
            return reference.querySelector('.tooltipcontent');
        },
        onShow(instance) {
            refreshcart(true);
        }
    });
});

But this changed nothing.


Solution

  • As Stavros Angelis points out, the tippy instance positioning is already calculated when the content is applied. To reposition the tooltip when the ajax call resolves, you could pass the tippy instance into the refreshcart() function and then accessing the popper instance inside it to refresh the tooltip:

    function refreshcart(force, tippyInstance) {
        $.ajax({
            type: 'post',
            url: 'includes/refreshcart.php',
            data: ({}),
            success: function(data){
                $('body #headercart').empty().append(data);
                tippyInstance.popperInstance.update(); // Here, the tippy positioning is updated
            }
        });
    }
    
    // other code...
    
    $( ".carttip" ).each(function( i ) {
        tippy(this, {
            theme: 'blue',
            trigger: 'click',
            allowHTML: true,
            animation: 'scale-subtle',
            maxWidth: 400,
            boundary: 'viewport', // This has been dropped in tippy@6
            interactive: true,
            content: function (reference) {
                return reference.querySelector('.tooltipcontent');
            },
            onShow(instance) {
                refreshcart(true, instance);
            }
        });
    });
    

    As for the boundary: seems like tippy@6 (which your example uses) has dropped this prop, so it can be removed here.

    More on the popper instance here: https://github.com/atomiks/tippyjs/issues/191