10

I'm using bxslider script to build a carousel. I can do everything fine, I'm just having a problem trying to align to center the slides vertically, as they don't have the same height. I've tried numerous align techniques, but all seem to fail when the bxslider is in action. Here's a jsfiddle example.

Currently in the example I've set a very simple CSS rule that works when the carousel is not set:

.bxslider-inner {
   vertical-align: middle;
    display: inline-block;
} 

But, as you can see in the jsfiddle, when the carousel is active, the vertical alignment doesn't work anymore.

I'm starting to suspect I might have to change the core code of the script to achieve this.

CRABOLO
  • 8,322
  • 38
  • 38
  • 66
CMoreira
  • 1,650
  • 1
  • 12
  • 25
  • Try the answer of this SO question: [CSS - vertically center an image within a floated div](http://stackoverflow.com/questions/3655331/css-vertically-center-an-image-within-a-floated-div). – darthmaim Mar 24 '13 at 02:53
  • I've added a new answer, I hope it fits your needs. Good luck! –  Mar 24 '13 at 13:51

6 Answers6

16

Update your CSS like this. The key is not floating the element because you are always making it inline-block

.bxslider-inner {
    vertical-align: middle;
    display: inline-block;
    float: none !important;
}

One more thing... To make it match your example, change slideMargin:20 to slideMargin:10 after you have done the float: none !important;

Fiddle: http://jsfiddle.net/sSqAx/9/

Matt Coughlin
  • 17,170
  • 3
  • 42
  • 57
doitlikejustin
  • 6,107
  • 2
  • 37
  • 64
  • Not a fan of `!important`, but a nice clean fix. +1 –  Mar 24 '13 at 14:02
  • When looping through the carousel, I'm seeing the space between some of the elements collapsing and reappearing at certain times. It happens in all browsers. It's caused by the implicit 4px or so of space between `inline-block` elements that have whitespace between them. This solution may require editing the HTML to remove any whitespace between the tags for the `.bxslider-inner` elements (if that's an option), and re-adjusting the value of `slideMargin`. [Updated demo](http://jsfiddle.net/Matt_Coughlin/z6Fmj/). – Matt Coughlin Mar 24 '13 at 15:03
  • Actually no... It is rendering properly instead and adding more space then needed because before the JS was adding 100px total width where in the hardcoded HTML with true width is 90px. So you need to adjust the width or the margin in the JS to equal a total of 90px instead of 100px. – doitlikejustin Mar 25 '13 at 01:05
  • Uau, nice and clean solution! Very easy to implement and it is also working on my real implementation of the code. I still have to check a bit better the slideMargins and paddings and other stuff, but the vertical alignment is working good! Thanks a lot for this! – CMoreira Mar 25 '13 at 02:02
  • 1
    "float: none" ... man, this saved my live. i was on this problem for a whole day ... :-P. THX a lot! –  Nov 30 '13 at 00:37
  • It worked after I changed `.bxslider-inner` to `.bxslider li` – Avatar Mar 13 '14 at 09:27
3

CSS tables

Ordinarily, as long as support for IE7 or earlier wasn't needed, I'd suggest adding display: table-cell; (along the lines of the question @darthmaim linked to above):

.bxslider-inner {
    display: table-cell;
    vertical-align: middle;
}
...
<div class="bxslider-inner"><div>Content goes here</div></div>

However, display: table-cell; doesn't work on floated elements (tested in IE8/9/10, Firefox, Safari, Chrome, Opera), as shown in this JSFiddle Demo. In the question @darthmaim linked to, the parent of the element is the one that's floated; that works fine. Here the child element is floated; that doesn't work.

Workaround

If editing the HTML source code is an option, you can add a div wrapper inside each .bxslider-inner, so that the use of display: table-cell; can be moved to a non-floated element: Updated demo.

.bxslider-inner > div {
    display: table-cell;
    vertical-align: middle;
    height: 90px;
}
...
<div class="bxslider-inner"><div><div>Content goes here</div></div></div>

This assumes that the carousel container is intended to have a fixed height of 90px. Supporting a variable-height container (which varies based on the height of the tallest carousel element), would require additional work.

JavaScript

If editing the HTML source code isn't an option, there are two solutions using JavaScript or jQuery:

  1. Dynamically inject div wrappers of the type described above, rather than adding them to the static HTML: Updated demo
  2. Dynamically add the appropriate amount of top spacing to each element, based on the calculated height of each element.
Community
  • 1
  • 1
Matt Coughlin
  • 17,170
  • 3
  • 42
  • 57
  • Hello Matt! Thanks a lot for your input. In my case, yes, editing the HTML is an option. +1 I'm giving a try to the solution of doitlikejustin as it was easier to implement and it's working great also. But thanks for the input anyway! – CMoreira Mar 25 '13 at 02:03
1

We can vertcal align a div to the center by adding "vertical-align:middle" in the css and giving a fixesd height to the outer div. OR we can set by margin-top or can also use top attribute in css

Vish
  • 171
  • 3
0

You can do it by adding top:30px

Here vertical-align did not works because in the bxslider-inner div it adds additional style so it doesn't apply vertical-align here. So, in this case you can use top for that element.

Fiddle http://jsfiddle.net/sSqAx/3/

Rohan Kumar
  • 38,998
  • 11
  • 69
  • 99
  • Hello Rohan! Thank you for your input! This solution works in this case, but it's not the best solution, since it's specific to that element. The problem is that I'll have images loading dynamically, with different heights, so this solution wont work. I'm guessing I'll have to search on the core files where the scripts adds the additional styles and edit the script there? – CMoreira Mar 21 '13 at 13:27
0

Set the values slideMargin:0 and slideWidth: 100

It works.

Hassaan
  • 226
  • 1
  • 2
  • 9
  • Hello! Thank you for your input. I tried this values, but nothing changes. What it does is to set the space between slides to be the same, but it doesn't solve the vertical aligment of the smaller div. Or I'm missing something? – CMoreira Mar 21 '13 at 13:28
0

This should fix your problem:

JSfiddle

And one with different heights: JSfiddle

HTML

<div class="bxslider">
    <div class="bxslider-inner"><div style="width:80px; height:80px; background:#CCC; padding:5px;"></div></div>
    <div class="bxslider-inner"><div style="width:80px; height:80px; background:#F5F5F5; padding:5px;"></div></div>
    <div class="bxslider-inner"><div style="width:80px; height:10px; background:#6699cc; padding:5px;"></div></div>
    <div class="bxslider-inner"><div style="width:80px; height:80px; background:#F5F5F5; padding:5px;"></div></div>
</div>

CSS

body {
    background: orange;
    margin-top: 50px;
}

.bxslider-inner {
   vertical-align: middle;
    display: inline-block;
    height: 80px;
}

JavaScript

'use strict';

jQuery(document).ready(function(){
    jQuery('.bxslider').bxSlider({
        mode: 'horizontal',
        speed: 500,
        slideMargin:20,
        infiniteLoop: true,
        pager: false,
        controls: true,
        slideWidth: 80,
        minSlides: 1,
        maxSlides: 5,
        moveSlides: 1
        }
    });

    // Initial
    $('.bxslider-inner').each(function(){
        var height_parent = $(this).css('height').replace('px', '') * 1;
        var height_child = $('div', $(this)).css('height').replace('px', '') * 1;
        var padding_top_child = $('div', $(this)).css('padding-top').replace('px', '') * 1;
        var padding_bottom_child = $('div', $(this)).css('padding-bottom').replace('px', '') * 1;
        var top_margin = (height_parent - (height_child + padding_top_child + padding_bottom_child)) / 2;

        $(this).html('<div style="height: ' + top_margin + 'px; width: 100%;"></div>' + $(this).html());
    });
});

Keep in mind that the calculated middle is very dependent on other height variables like padding, margin and borders. If you add styles like that, keep in mind that you need to add those to the calculation. Another option is to use box-sizing: border-box;, so all of that collapses to the inside of the div.

bxslider-inner MUST have a height, or you need to somehow fetch the calculated DOM height to avoid it. If you really want that, please leave a note and I'll look into it.

Good luck!

UPDATE

  • JSfiddle updated, should not stuck in a loop now.
  • Tested with a too high height, code doesn't seem to break, but might overflow to hidden
  • Look at http://bxslider.com/options (> Callbacks > onSlideAfter). You can do modifications after each cycle if needed too. Here you can modify your code again if needed for complexion
  • Thank you for your input! This solution works also. I am however going with the solution from doitlikejustin, which is more simple to implement. But thanks for this! +1 – CMoreira Mar 25 '13 at 02:04