Sunday, December 18, 2016

FlexSlider - Setting maximum height and prevent content from reflowing / shifting

I'm making a website right now (actually more like remaking an old one) and a free wordpress theme I am using has the jQuery "FlexSlider" plugin built in for displaying wordpress galleries. However, I hated how the sliders were acting by default when loaded with images of varying height; the height of the slider dynamically changes to match the active img element, which means that content below it gets pushed down or up when the slider animates. This is actually terrible for UI, because an element can move unexpectedly right as a user is about to click on it.

How I wanted the Flexslider to act was to have a fixed size container, and then resize the images, not the container, to match my height constraint. If you are having trouble understanding what I mean, perhaps an example of default vs desired behavior is the best way to illustrate my issue:

Flexslider images

  • Image 1: 300 x 200 px
  • Image 2: 300 x 400 px
  • Image 3: 300 x 200 px
  • Image 4: 300 x 200 px
Default behavior:
  • The slider starts with a height of 200px, based on the first slide. When it gets to slide 2, it dynamically changes the container (<div class="flex-container">) to have a height of 400px, which shoves/bumps all the content below the slider down by 200px from where it just was.
  • Here is a demo of this default behavior:
Desired behavior:
  • The slider container is constrained to a height of my choosing, in this example, I might pick a max-height of 200px, since that lets 3 out of the 4 images display at full size, and only negatively affects 1 image. On slide 2, the container should stay the same height, but instead of cropping (e.g. overflow:none) or squishing (e.g. setting img height to match container and disregarding aspect ratio), it should keep the aspect ratio and downscale the image to fit.
Unfortunately, I spent a while searching across forums, as well as the official github repo for the FlexSlider plugin, and I couldn't really find any easy solutions. Most of the solutions I saw either cropped images, or did something like set the height of the slider to the largest image, instead of allowing for a custom max-height to be used across all images (it looks like this is actually what the newer versions of the plugin do). Another common suggestion was just to ensure that all slider images have the same height by manually cropping them, but that is a pain and not really a solution. In the end, I gave up on finding someone else's solution and decided to take a stab at it myself.

CSS is definitely not one of my strengths, but I managed to find an excellent solution, mostly by trial and error. This solution allows for a custom height, to which the slider and all internal images will be constrained. Images that are larger than the maximum height will be automatically downscaled, while preserving aspect ratio, and they are both horizontally and vertically centered. I would highly suggest having separate maximum heights for mobile vs desktop screen sizes, which is in my example CSS by way of media-queries. In my example, the mobile size is 200px high, while larger screens get a slider with a height of 300px. Super simple fix, but I couldn't find anything that accomplished it when I was search, so I figured I would post it to share with others. Here is my CSS solution - both the CSS combined with a live demo (hit the "result" tab to see the fix in action):