Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong owl-stage width calculation when using "autoWidth: true" #1139

Closed
danielepennati opened this issue Nov 25, 2015 · 37 comments
Closed

Wrong owl-stage width calculation when using "autoWidth: true" #1139

danielepennati opened this issue Nov 25, 2015 · 37 comments

Comments

@danielepennati
Copy link

Hello,
I have a strange bug... I have several pages with a carousel with same option

$('.owl-carousel').owlCarousel({
    margin:10,
    autoWidth:true,
    items:4,
    nav: true,
    navText: ['<span class="fa fa-angle-left"></span>', '<span class="fa fa-angle-right"></span>']
})

On same of this pages the carousel doesn't work correctly: the width of the owl-stage element is calculated wrongly and the last item of the carousel goes on a new line (under the firs item in chrome ora under the last item of the first row in firefox). for example look at this page:
http://www.galleriacarlasozzani.org/en/past?milano/2010

the main issue is that it is random... on the vast majority of page everything work fine and the pages with the bug are have exactly the same layout and template of the other one.

Do you have any idea about fixing this?

thanks
daniele

@kevindeasis
Copy link

I had the same problem too with older versions of android. The only way I could support it in older versions of anrdroid was to use the older version of carousel or remove autoWidth in owl carousel 2.

@imolorhe
Copy link

Any fix for this issue yet? Still bugging me.

@danielepennati
Copy link
Author

I've fixed it using a simple workaround:

I call a function on the owl events "onInitialized", "onRefreshed". The function simply recalculates the .owl-stage width:

var fixOwl = function(){
        var $stage = $('.owl-stage'),
            stageW = $stage.width(),
            $el = $('.owl-item'),
            elW = 0;
        $el.each(function() {
            elW += $(this).width()+ +($(this).css("margin-right").slice(0, -2))
        });
        if ( elW > stageW ) {
            $stage.width( elW );
        };
    }

$('.some-element').owlCarousel({
        margin:10,
        autoWidth:true,
        items:4,
        nav: true,
        navText: ['<span class="fa fa-angle-left"></span>', '<span class="fa fa-angle-right"></span>'],
        onInitialized: fixOwl,
        onRefreshed: fixOwl
    })

that's all :-)

daniele

@Jehu
Copy link

Jehu commented Jun 16, 2016

why is this closed?

@pascalporedda
Copy link
Collaborator

This issue should be fixed in the version 2.1.6. If you experience any unwanted behaviour, feel free to report it via an issue.

@pablo-sg-pacheco
Copy link

pablo-sg-pacheco commented Jul 6, 2016

Version 2.1.6 fixed this issue for me. Thanks

@pablo-sg-pacheco
Copy link

Actually it is still weird.
Sometime it works. Sometimes not.

The last item is still going in a new line some times. But even when the last item goes on the right place i can't move to last item

@pablo-sg-pacheco
Copy link

I think I fixed it loading the carousel on window.load, instead of document ready and adding a last fake item on html

@kampiamodikuesto
Copy link

thanks i fix this problem adding this lines of code

function recalcCarouselWidth(carousel) {
    var $stage = carousel.find('.owl-stage'),
         stageW = $stage.width(),
	 $el = $('.owl-item'),
	 elW = 0;
    $el.each(function() {
        elW += $(this)[0].getBoundingClientRect().width;
    });
    if ( elW > stageW ) {
	 console.log('elW maggiore di stageW: ' +  elW + ' > ' + stageW);
	 $stage.width( Math.ceil( elW ) );
    }
}
$(window).on('resize', function(e){
    recalcCarouselWidth( $('.owl-carousel') );
}).resize();
$('.owl-carousel').on('refreshed.owl.carousel', function(event) {
     recalcCarouselWidth( $('.owl-carousel') );
});
$('.owl-carousel').on('onResize.owl.carousel', function(event) {
    recalcCarouselWidth( $('.owl-carousel') );
});

@kampiamodikuesto
Copy link

kampiamodikuesto commented Mar 29, 2017

precendent fix don't work for me, i have to add 1 to this code

filter: [ 'width', 'items', 'settings' ],
		run: function() {
			var padding = this.settings.stagePadding,
				coordinates = this._coordinates,
				css = {
					'width': **1** + Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
					'padding-left': padding || '',
					'padding-right': padding || ''
				};

			this.$stage.css(css);
		}
	}, {

The problem i think is that coordinates function calculate ceil on negative value (es -37.5 --> -37) Css width for owl-stage is taken by last coordinates that is 1px short (es. 37 and not 38)
this isn't a problem to first load but it is a problem when resize.

@masbug
Copy link

masbug commented Apr 23, 2017

I can confirm that this is still a problem in version 2.2.1 (using autoWidth=true). If I change width on owl-stage just by adding 1px then the issue is resolved.

Another solution that worked for me is setting box display on owl-stage:
.owl-stage {
display: -webkit-box;
display: -moz-box;
display: -ms-box;
display: box;
}

Best regards,
M.

@akash-d
Copy link

akash-d commented Jun 5, 2017

@masbug Thanks alot! It works perfectly fine now.

@kwentworth
Copy link

what worked for me was adding a rule for
.owl-item {
display: inline !important;
}

@tonxxx
Copy link

tonxxx commented Jun 22, 2017

@masbug thanks!!! works well for me.. spent a lot of time finding workaround and finally it's fxed ))

@quinnvaughn
Copy link

@masbug It should be display: flex;, but it still doesn't work for me every time. I have to reload. Before I do, all the items are scrunched up.

@quinnvaughn
Copy link

Also @masbug that does seem to work, but not with center: true, as it throws the alignment of the slides off.

@adigourdi
Copy link

adigourdi commented Aug 28, 2017

I've encountered this issue this morning
It seems to happen only when there is an item that is larger than stageOuter's width, appending the difference between these items to the width of the stage solves the problem
I've written this code to test my theory

// Fix for last item creating a new line with autoWidth=true
var $this = $('.owl-carousel').owlCarousel({ autoWidth: true });
var $stageOuter = $this.find('.owl-stage-outer');
var stageOuterWidth = $stageOuter.width();
var $stage = $this.find('.owl-stage');
var stageWidth = $stage.width();
var $items = $stage.children();
var largestChild = 0;
for (var i = 0, ic = $items.length; i < ic; i++) {
	var itemWidth = $($items[i]).width();
	largestChild = largestChild > itemWidth ? largestChild : itemWidth;
}
if (largestChild > stageOuterWidth) {
	$stage.width(stageWidth + Math.ceil((largestChild - stageOuterWidth) * 1.2));
	var addedWidth = Math.ceil((largestChild - stageOuterWidth) * 1.2)
	var stageNewWidth = $stage.width();
	console.log(stageOuterWidth, stageWidth, stageNewWidth, addedWidth, largestChild);
}

The 1.2 factor is there to assure the width isn't still short, it needs to be 1 or higher, putting 0.9 will make the second line appear again

The solution I applied is triggering a refresh on the carousel right after initialisation, resizing the window recalculates the stage width correctly

var $this = $('.owl-carousel').owlCarousel({ autoWidth: true }).trigger('refresh.owl.carousel');

I tried multiple events: resize.owl.carousel, resized.owl.carousel, and refreshed.owl.carousel, none of them solved the issue

Edit: tested with current release 2.2.1

@jim22
Copy link

jim22 commented Sep 13, 2017

@adigourdi - Thanks. Triggering a refresh after initialization worked for me as well.
$('.slideshow-images').owlCarousel({ autoWidth: true, ... }).trigger('refresh.owl.carousel');

@sasha1344
Copy link

Hi. I had the same problem. The script didn't understand stage width, because images haven't been uploaded. To solve this problem I used jQuery plugin "Images Loaded" ( https://github.com/desandro/imagesloaded )

var carousel = $( '.owl-carousel' ).owlCarousel({
	margin: 25,
	loop: true,
	dots: false,
	autoWidth: true,
	items: 3
});
carousel.imagesLoaded( function() {
	carousel.trigger( 'refresh.owl.carousel' );
});

I hope this helps someone)

@EdenK
Copy link

EdenK commented Nov 19, 2017

@adigourdi - Thanks this worked for me as well.
$('.owl-carousel').owlCarousel({ autoWidth: true }).trigger('refresh.owl.carousel');

@murph133
Copy link

murph133 commented Feb 22, 2018

A simple solution. Double the preset .owl-stage width:

$('.owl-carousel').owlCarousel({
         onInitialized: fixOwlCarousel,
         onRefreshed: fixOwlCarousel
})
var fixOwlCarousel = function(){
        stage = $('.owl-stage');
        stage.width(stage.width() * 2);
}

@folkevil
Copy link

folkevil commented May 8, 2018

I got same problem today,
@sasha1344 your solution worked for me. But we can fix by css with:

.owl-stage {
display: -webkit-box;
display: -moz-box;
display: -ms-box;
display: box;
}
.owl-carousel

.owl-item img {
width: auto !important;
}

@webblufter
Copy link

Same issue solved by 'onInitialized' and 'onRefreshed' my code is below
jQuery('.owl-carousel').owlCarousel({
dots: false,
loop:false,
nav: false,
autoWidth: true,
scrollbarType: "progress",
onInitialized: function(){ stage = jQuery('.owl-stage'); stage.width(stage.width() * 2); },
onRefreshed: function(){ stage = jQuery('.owl-stage'); stage.width(stage.width() * 2); },
});

@fitnycdigitalinitiatives

I ran into this same problem and I think it's related to #604. It's not strictly limited to google fonts--any loaded font causes this problem. What happens is that it calculates the owl-stage based on a generic font and then once your font is loaded it causes the stage to be too small (because whatever font you are using causes your element to be a little bigger). A true fix would recalculate the stage whenever there's a change in the item size. I think just doubling the stage width size does the trick, but one could also use something like this which can trigger once a font is loaded and then trigger a refresh on the owl.

@oliveratgithub
Copy link

For me, the only solution that worked was the one with adding CSS-styles for box-styles as provided by @masbug – triggering a "refresh.owl.carousel" or something with "onInitialized" / "onRefreshed" didn't work.

@choogoor
Copy link

choogoor commented Jun 1, 2019

Hi all, it doesn't work well for neither solutions display: box or triggering refresh. With triggering refresh it works on firefox but on chrome problem is still there. Using display: box on .owl-stage calculate height correctly but center option then doesn't work well.

@Kayanski
Copy link

@choogoor the fix by kampiamodikuesto (the 1 + Math.ceil in owl.carousel.js ) fix worked nice for me

@GTCrais
Copy link

GTCrais commented Aug 10, 2019

None of these solutions worked for me. The only thing that worked for me is adding coordinate--; as the first line of Owl.prototype.animate function on line 938, making it:

Owl.prototype.animate = function(coordinate) {
    coordinate--;

    // rest of the function...

}

@sasikasp
Copy link

all the above solutions did not work for me, so I did it myself by using CSS

this is what i did...

.owl-carousel .owl-stage {
display: flex;
}

.owl-item {
width: max-content !important;
}

.item {
width: max-content;
}

.owl-carousel .owl-item img {
width: auto;
max-height: 460px;
margin-left: auto;
margin-right: auto;
}

This works for me, hope it helps someone too.

@forwells
Copy link

forwells commented Dec 6, 2019

I can confirm that this is still a problem in version 2.2.1 (using autoWidth=true). If I change width on owl-stage just by adding 1px then the issue is resolved.

Another solution that worked for me is setting box display on owl-stage:
.owl-stage {
display: -webkit-box;
display: -moz-box;
display: -ms-box;
display: box;
}

Best regards,
M.

More Thanks, If not work, Please try !important

@mrsoftware
Copy link

mrsoftware commented Dec 14, 2019

@masbug solution worked for me. thanks.

.owl-stage {
    display: -webkit-box !important;
    display: -moz-box !important;
    display: -ms-box !important;
    display: box !important;
}

@sabat24
Copy link

sabat24 commented Dec 19, 2020

The source of the problem is that line:

widths[iterator] = !grid ? this._items[iterator].width() : width * merge;

in Chrome you often get width as 0. I think that author tried to resolve such issues by using an autoRefresh option. However it's not reliable as you do not know how long does it take to load all images. Solutions with initialized handler may not work, because there may be not enough time to correctly load and recalculate width of all images by browser. Solution with imagesLoaded is better, but still not perfect. Firefox has no problems with it, but Chrome does. Sometimes latest elements with images may still return zero width, because browser wasn't able to calculate new width of parent elements even if images were loaded. This is why I created my own solution.

    function isOwlLoaded(carousel) {
        let iterator = carousel._items.length;
        while (iterator--) {
            if (!carousel._items[iterator].width()) {
                setTimeout(isOwlLoaded.bind(null, carousel), 100);
                return false;
            }
        }
        carousel.refresh();
    }

    $(".owl").owlCarousel({
        autoWidth: true,
        onInitialized: function () {
            isOwlLoaded(this);
        },
    });

It checks if all items return non-zero width and re-run the check if not. If that condition is met, it refreshes the owl object.

It may need some extra work if you use some lazy-loaded items, which should be ignored and so on. There also should be some limit to prevent infinite loop if image wasn't loaded.

@Khanim98
Copy link

I had the same problem, and fixed it by :

.owl-item:last-of-type{
          margin-right: 0!important;
      }

@brandondeweese
Copy link

Why is this closed? This is still happening in 2.3.4

@gkot-softwaredeveloper
Copy link

Unfortunately, I can confirm that on version 2.3.4 bug still occur.

@oriolun
Copy link

oriolun commented Sep 7, 2021

Solved by adding this code:

$(window).load(function () {
    //console.info('window loaded')
    $('.owl element').trigger('refresh.owl.carousel')
})

load event fires after all images are loaded.

@aleiakkim
Copy link

I am experiencing the same issue, and it persists even after I tried turning "autoWidth" back to false.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests