0

It was noticed that when fancybox is calculating how wide it needs to be to fit the content, it doesn't handle decimal places/floating point numbers.

For example if we had 2 <div> of 300px and 217.367px respectively, fancybox would round the width of its content to 300px + 217px = 517px. This means the second div would not fit and would therefore drop down to the next line.

It seems this is due to the use of the jQuery width() method.

Relevant code

html :

<a class="fancybox" href="#inline">open inline</a>

<div id="inline" class="cf">
    <div id="content">
         <h3>Lorem Ipsum</h3>
        <p>More text content etc</p>
    </div>
    <div id="red">Other floating content</div>
</div>

css :

#inline {
    position: relative;
    white-space: nowrap;
}
#content {
    width: 15.526em; /* 217.367px */
    height: 150px;
    display: block;
    float: left;
}
#red {
    height: 150px;
    width: 300px;
    display: block;
    float: left;
}

jQuery :

$(".fancybox").fancybox({
    padding: 0
});

JSFIDDLE

Notice in the fiddle the #inline container is always visible for demonstration purposes only. Also notice the width of one of the containers was set in ems, which is a pretty common scenario so changing it to a fixed width in px may not be the way to go (although it's possible to set width: 217.367px on the css with the same result)

Is there a fix or a workaround?

A possible and easy solution would be to add an extra pixel to the fancybox container but it would be better to add it only when it's needed and not as a general rule.

JFK
  • 40,963
  • 31
  • 133
  • 306

1 Answers1

0

Since using the jQuery .width() method will always return a rounded value of the element's width, even within the parseFloat() function :

parseFloat($("#element").width());

see jsfiddle

... we would need to get the computed width of each element within the fancybox content to get an incremental total width of the fancybox container.

To do this, we can use getComputedStyle() along with the getPropertyValue("width") method to get the computed width of each element like :

var compWidth = window.getComputedStyle(element).getPropertyValue("width");

Notice that compWidth will return the string 248.417px so we still need to parse the floating value to get the right calculation. We could do something like :

parseFloat(compWidth.split("px")[0]);

Then, we can compare if the total computed width has a remainder to decide whether we should add an extra pixel to the fancybox container or not. We can achieve this by using a modulo operation (Check this answer for reference) like :

if (totalWidth % 1 != 0) {
    totalWidth++; // or Math.ceil(totalWidth);
}

See the full code with calculations within the afterLoad callback :

jQuery(document).ready(function ($) {
    $(".fancybox").fancybox({
        padding: 0,
        afterLoad: function () {
            // get the computed width of elements inside fancybox
            var totalWidth = 0;
            $("#inline").find("div").each(function (i) {
                // increment total width with each element's width
                totalWidth += parseFloat(
                window.getComputedStyle(this)
                      .getPropertyValue("width")
                      .split("px")[0]);
            });
            // compare if the result has a remainder
            if (totalWidth % 1 != 0) {
                // increase total width by 1px
                totalWidth++; // or Math.ceil(totalWidth);
                // set the new fancybox width
                $.extend(this, {
                    fitToView: false, // cause will set a fixed width
                    autoWidth: false,
                    width: totalWidth
                });
            }
        }
    });
}); // ready

See JSFIDDLE

NOTE: this is a workaround that can be useful for some specific scenarios. Also notice getComputedStyle() is only supported in IE9+

Community
  • 1
  • 1
JFK
  • 40,963
  • 31
  • 133
  • 306