uf2pka
Last Updated: August 08, 2017
·
40.92K
· estaples

Normalize Twitter Bootstrap Carousel Slide Heights

Bootstrap carousel is fantastic, but its flexibility can be a challenge. Since each slide item is pretty much freeform HTML, varying slides can have varying heights. This is problematic when page content exists in normal flow after and beneath the carousel, since a shape-shifting carousel is constantly pushing content down or pulling it up on slide transition, making reading difficult—especially on mobile devices. I found that its possible to replicate the behavior of other carousels that dynamically set a consistent height for the whole carousel based on the tallest slide item found in the HTML.

You’ll want to execute jQuery akin to the following, after the carousel HTML exists on the page, or once the DOM is ready (either inside $(document).ready()* or at the end of the page body):

function carouselNormalization() {
var items = $('#carousel-example-generic .item'), //grab all slides
    heights = [], //create empty array to store height values
    tallest; //create variable to make note of the tallest slide

if (items.length) {
    function normalizeHeights() {
        items.each(function() { //add heights to array
            heights.push($(this).height()); 
        });
        tallest = Math.max.apply(null, heights); //cache largest value
        items.each(function() {
            $(this).css('min-height',tallest + 'px');
        });
    };
    normalizeHeights();

    $(window).on('resize orientationchange', function () {
        tallest = 0, heights.length = 0; //reset vars
        items.each(function() {
            $(this).css('min-height','0'); //reset min-height
        }); 
        normalizeHeights(); //run it again 
    });
}
}

*With older versions of jQuery at least, IE8 and below don’t respond to $(document).ready(), so you may need a workaround for that.

9 Responses
Add your response

16364

saved me some time, thank you Eddie. One thing you might mention for is you need to call 'carouselNormalization();' at the end of the function declaration.

over 1 year ago ·
16429

A little cleaner

// Normalize Carousel Heights - pass in Bootstrap Carousel items.
$.fn.carouselHeights = function() {

    var items = $(this), //grab all slides
        heights = [], //create empty array to store height values
        tallest; //create variable to make note of the tallest slide

    var normalizeHeights = function() {

        items.each(function() { //add heights to array
            heights.push($(this).height()); 
        });
        tallest = Math.max.apply(null, heights); //cache largest value
        items.each(function() {
            $(this).css('min-height',tallest + 'px');
        });
    };

    normalizeHeights();

    $(window).on('resize orientationchange', function () {
        //reset vars
        tallest = 0;
        heights.length = 0;

        items.each(function() {
            $(this).css('min-height','0'); //reset min-height
        }); 
        normalizeHeights(); //run it again 
    });

};

jQuery(function($){

    $(window).on('load', function(){
        $('#carousel-hero .item').carouselHeights();
    });

});
over 1 year ago ·
16475

great article! thanks so much!

over 1 year ago ·
18158

Thank you!

over 1 year ago ·
18360

This code makes the opposite:
takes the shortest image and sets that value as the maximum height.
All other slides appear cropped

HOW TO USE: change the carousel id (#carousel-single) and paste after your carousel

<script> 
jQuery('.carousel').carousel({interval: 3000 });
// Normalize Carousel Heights - pass in Bootstrap Carousel items.
function carouselNormalization() {
var items = jQuery('#carousel-single .item'), //grab all slides
heights = [], //create empty array to store height values
shortest; //create variable to make note of the shortest slide

if (items.length) {
function normalizeHeights() {
items.each(function() { //add heights to array
heights.push(jQuery(this).height());
});
shortest = Math.min.apply(null, heights); //cache largest value
items.each(function() {
jQuery('.carousel-inner').css('height',shortest + 'px').css('overflow','hidden');

});
};
normalizeHeights();

jQuery(window).on('resize orientationchange', function () {
shortest = 0, heights.length = 0; //reset vars
items.each(function() {
jQuery('.carousel-inner').css('height','0'); //reset min-height
});
normalizeHeights(); //run it again
});
}
}
carouselNormalization();
</script>
over 1 year ago ·
20707

I made another version that worked better for me. This one fixes the height of the carousel div to such a height that the biggest image fits in it.

Note that I use a custom way to measure images because, when they are hidden, they sometimes are 0px.

This version supports multiple carousel in one document and does not assume one 'id' is used


function normalizeSizesAllCarousels(){ jQuery('.carousel.slide').each(function(){//we loop all the present carousels normalizeSizesOneCarousel('#' + jQuery(this).attr('id')); }); } function normalizeSizesOneCarousel(idSelectorCarousel){ var images=jQuery(idSelectorCarousel + ' .carousel-inner .item img'); var availableWidht=jQuery(idSelectorCarousel).innerWidth(); var maxHeight=0; var imageHeight=0; var aspectRatio=1;//width/height images.each(function(){ aspectRatio=calcImgWidth(this)/calcImgHeight(this); imageHeight=availableWidht/aspectRatio; if(imageHeight>maxHeight){maxHeight=imageHeight;} }); jQuery(idSelectorCarousel).height(maxHeight); } function calcImgWidth(img){ var width=img.width; if (width>0){ return width; }else{ jQuery('body').append('<div id="tempContainer" style="visibility:hidden;position:absolute"></div>'); jQuery('#tempContainer').append(img.clone().attr('id',false)); width= jQuery('#tempContainer img').width; jQuery('#tempContainer').remove(); return width; } } function calcImgHeight(img){ var height=img.height; if (height>0){ return height; }else{ jQuery('body').append('<div id="tempContainer" style="visibility:hidden;position:absolute"></div>'); jQuery('#tempContainer').append(img.clone().attr('id',false)); height= jQuery('#tempContainer img').height; jQuery('#tempContainer').remove(); return height; } } jQuery(document).ready(function(){normalizeSizesAllCarousels();}); jQuery(window).on('resize orientationchange', function () {normalizeSizesAllCarousels();}); </code> </pre>
over 1 year ago ·
25005

The resize event fires twice on my webpage, and I had to use "height" instead of "min-height", that's my version of your script:


$(window).load(function() {
$('.carousel').each(function(){
$(this).carouselHeights();
});
});

// Normalize Bootstrap Carousel Heights
$.fn.carouselHeights = function() {
var items = $(this).find('.item'), // grab all slides
heights = [], // create empty array to store height values
tallest, // create variable to make note of the tallest slide
call;
var normalizeHeights = function() {
items.each(function() { // add heights to array
heights.push($(this).outerHeight());
});
tallest = Math.max.apply(null, heights); // cache largest value
items.css('height', tallest);
};
normalizeHeights();
$(window).on('resize orientationchange', function() {
// reset vars
tallest = 0;
heights.length = 0;
items.css('height', ''); // reset height
if(call){
clearTimeout(call);
};
call = setTimeout(normalizeHeights, 100); // run it again
});
};
</pre>

over 1 year ago ·
25022

Does anyone have a working page with this working. I am struggling to get any of the above versions to work.

over 1 year ago ·
29180

Thank you very much Eddie and also tonycronin for providing this efficient solution to Bootstrap's carousel height issue. The code from tonycronin worked great for me.

over 1 year ago ·