0

We built a gallery using Bootstrap Carousel + Hammer.Swipe + PhotoSwipe.
Everything worked well if there were only landscapes or portraits in the gallery.
But when we tested it in small resolution and there were portraits among the landscapes at the same time then the gallery set the height of the container to the tallest portrait and it resulted big white margins above and below of every landscape image.

How can I remove the margins from the landscape images in mobile view?

Here is a simplified code:

// carousel.js
var Carousel = (function($, viewport) {
    function init() {
        var $carousels = $('.carousel');
        $.each($carousels, function() {
            var $carousel = $(this);
            swipeHorizontalMobile($carousel, viewport);
            imageNavListener($carousel);
            updateArrowVisibility(0, $carousel);
        });
    }

    // implementation of the rest of the code

    return {
        init: init
    };
})(jQuery, ResponsiveBootstrapToolkit);
Zoltán Süle
  • 1,482
  • 19
  • 26

1 Answers1

0

It turned out there are some precalculated fixed values in the carousel-inner and the slider-photo-wrapper elements.
I decided I limit the height based on the tallest landscape and overwrite the values of these elements.

Issues I faced with:

  • I had to be sure that the images loaded before I work with them otherwise I couldn't get their width and height
  • How can I get the size of a scaled image? Finally I bypassed it and used the original size because I needed only the ratio of the width to the height to calculate the maximum height based on the width of the carousel container
  • I couldn't use getBoundingClientRect() because it returns 0 for images which aren't displayed (display: hidden) and only the first image is displayed in the Bootstrap Carousel

We call CarouselNormalization.init($carousel) from the main code where we loop through the galleries:

// carousel.js
var Carousel = (function($, viewport) {
    function init() {
        var $carousels = $('.carousel');
        $.each($carousels, function() {
            var $carousel = $(this);
            swipeHorizontalMobile($carousel, viewport);
            imageNavListener($carousel);
            updateArrowVisibility(0, $carousel);

            // fixes the size of the carousel images/containers mainly for mobile devices
            CarouselNormalization.init($carousel);
        });
    }

    // implementation of the rest of the code

    return {
        init: init
    };
})(jQuery, ResponsiveBootstrapToolkit);

The code below was written in Pair programming with my colleague and we used some of the ideas of Normalize Twitter Bootstrap Carousel Slide Heights.

// carousel_normalization.js
/**
 * changes the maximum height of the carousel containers based on the tallest landscape image
 * and prevents to have big margins above and below landscape images in small resolution
 */
var CarouselNormalization = (function ($) {
    var $carousel,
        $photoWrappers,
        $imgs;


    function init($inputCarousel) {
        $carousel = $inputCarousel;
        $imgs     = $carousel.find('.item img');

        if ($imgs.length < 1) {
            return;
        }

        $photoWrappers = $carousel.find('.item .slider-photo-wrapper');

        var imgsLoadedCount = 0;

        $imgs.one('load', function () {
            imgsLoadedCount++;

            if (imgsLoadedCount < $imgs.length) {
                return;
            }

            normalizeHeights();

            $(window).on('resize orientationchange', function () {
                normalizeHeights();
            });
        }).each(function () {
            if (this.complete) {
                $(this).trigger('load');
            }
        });
    }

    /**
     * finds the tallest landscape
     * uses its height as maximum height for the 'slider-photo-wrapper' defined in the css and for the 'carousel-inner'
     */
    function normalizeHeights() {
        var widths = [];
        var heights = [];
        var maxWidth = $carousel.width();

        $imgs.each(function () {
            var width  = $(this).prop('naturalWidth');
            var height = $(this).prop('naturalHeight');

            if (width > height) {
                widths.push(width);
                heights.push(height);
            }
        });

        if (widths.length < 1 || heights.length < 1) {
            return;
        }

        var tallestLandscapeHeight = Math.max.apply(null, heights);
        var tallestLandscapeWidth  = widths[heights.indexOf(tallestLandscapeHeight)];
        var maxHeight              = maxWidth * tallestLandscapeHeight / tallestLandscapeWidth;

        $photoWrappers.css('height', maxHeight);
        $carousel.find('.carousel-inner').css('height', maxHeight);
    }

    return {
        init: init
    };
})(jQuery);
Zoltán Süle
  • 1,482
  • 19
  • 26