flexslider

Implementing, Styling and Extending Flexslider

Looking for implementing a zoom function with flexslider? Then you want to go here.
So we all have adapted to responsive design now right? If you haven’t I strongly suggest you do!

You have your site all working nice and resposive and want a responsive sliding gallery to showcase some of your work, this is a usual story. There are many of these sliders out there and one of my favourites is Flexslider.

To use Flexslider is incredibly simple, you can go get the code put it in place and job done! But for most of us that isn’t enough, we want to make it fit with our design, to make it more “yours” a few people have asked me how recently and have also wanted to extend it to do things such as navigating to a certain slide. When giving these answers it was suggested I share it with the tinterweb world so here it is.

What is Flexslider?

In a nutshell flexslider is an awesome, fully responsive jQuery slider toolkit that has all of the following niceties.

  • Simple, semantic markup
  • Supported in all major browsers
  • Horizontal/vertical slide and fade animations
  • Multiple slider support, Callback API, and more
  • Hardware accelerated touch swipe support
  • Custom navigation options
  • Compatible with the latest version of jQuery

Let’s get started

Firstly and if it was not obvious enough you will want to go and get the files from woo themes and uplaod them to your site wherever you see fit (for examples in this article I will use my chosen structure, you will just need to adjust these).

The HTML Markup

All the code you need to implement a 3 item slider is this:

<div class="flex-container">
    <div class="flexslider">
        <ul class="slides">
            <li>
                <a href="#"><img src="img/slide1.jpg" /></a>
            </li>
            <li>
                <img src="img/slide2.jpg" />
            </li>
            <li>
                <img src="img/slide3.jpg" />
                <p>Designing The Well-Tempered Web</p>
            </li>
        </ul>
    </div>
</div>

Next we’ll include the jQuery library and the FlexSlider plugin. To load the slider include the following code, you can set the settings there too, for more setting visit the plugin website. All I have set in this one is to make the animation fade and the controls container to be the flexslider container, pretty standard stuff we will move onto more advanced things later.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="js/jquery.flexslider-min.js"></script>
<script>
    $(document).ready(function () {
        $('.flexslider').flexslider({
            animation: 'fade',
            controlsContainer: '.flexslider'
        });
    });
</script>

Style it up

Let’s add some basic reset styles to keep all margins, paddings etc consistent.

.flex-container a:active,
.flexslider a:active,
.flex-container a:focus,
.flexslider a:focus  { outline: none; }

.slides,
.flex-control-nav,
.flex-direction-nav {
    margin: 0;
    padding: 0;
    list-style: none;
}

.flexslider a img { outline: none; border: none; }

.flexslider {
    margin: 0;
    padding: 0;
}

Next we will hide the slides initally to stop the page from jumping as it loads and everyone seeing all the images.

.flexslider .slides > li {
    display: none;
    -webkit-backface-visibility: hidden;
}

.flexslider .slides img {
    width: 100%;
    display: block;

    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
}

Then we will clear the floats from the slides.

.slides:after {
    content: ".";
    display: block;
    clear: both;
    visibility: hidden;
    line-height: 0;
    height: 0;
}

html[xmlns] .slides { display: block; }
* html .slides { height: 1%; }

Container styles

Let’s get a little snazzy but it is really simple stuff I promise! We can just add a white background and some rounded corners and a nice little shadow using good old box-shadow.

.flexslider {
    position: relative;
    zoom: 1;
    padding: 10px;
    background: #ffffff;

    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;

    -webkit-box-shadow: 0px 1px 1px rgba(0,0,0, .2);
    -moz-box-shadow: 0px 1px 1px rgba(0,0,0, .2);
    box-shadow: 0px 1px 1px rgba(0,0,0, .2);
}

In my demo version I have set a maximum and minimum width just so it did not stretch too far wide on larger screens. You can change or remove this to make them fit your design. I have also set a zoom to 1 just to stop mobile browsers from resiizing.

.flex-container {
    min-width: 150px;
    max-width: 960px;
}

.flexslider .slides { zoom: 1; }

Now for the arrows

This is where the styling gets a little more interesting. First the basics, we set the width and height etc. Then to make the arrows a little nice and to reward those with modern browsers I have added a subtle gradient using css3, nice ey! These then need to be position centered vertically, we just have to position then 50% from the top and then give them a negative margin half of the buttons height.

.flex-direction-nav a {
    display: block;
    position: absolute;
    margin: -17px 0 0 0;
    width: 35px;
    height: 35px;
    top: 50%;
    cursor: pointer;
    text-indent: -9999px;

    background-color: #bfab8b;
	background-image: -webkit-gradient(linear, left top, left bottom, from(#bfab8b), to(#f5e2c1));
	background-image: -webkit-linear-gradient(top, #bfab8b, #f5e2c1);
	background-image: -moz-linear-gradient(top, #bfab8b, #f5e2c1);
	background-image: -o-linear-gradient(top, #bfab8b, #f5e2c1);
	background-image: linear-gradient(to bottom, #bfab8b, #f5e2c1);
}

Next, to add the actual arrows into the boxes we use the :before pseudo selector. This pseudo selector allows us to include some content without adding a new tag in the html. Then you have a couple of options. If you want to be really snazzy and are not to worried about all browser support and just want to be really modern and cool, you can draw the arrows yourself using a series of gradients like this:

.flex-direction-nav a:before {
	display: block;
	position: absolute;
	content: '';
	width: 9px;
	height: 13px;
	top: 11px;
	left: 11px;
	background-image:
        linear-gradient(-45deg, #dac6a6 4px, transparent 4px),
        linear-gradient(-135deg, #dac6a6 4px, transparent 4px),
        linear-gradient(-45deg, #69604f 6px, transparent 6px),
        linear-gradient(-135deg, #69604f 6px, transparent 6px);

}

.flex-direction-nav a.flex-prev:before {
	background-image:
        linear-gradient(45deg, #dac6a6 4px, transparent 4px),
        linear-gradient(135deg, #dac6a6 4px, transparent 4px),
        linear-gradient(45deg, #69604f 6px, transparent 6px),
        linear-gradient(135deg, #69604f 6px, transparent 6px);
}

Or to be more supportive and the more standard way of doing it is to create a little sprite with the arrows in and just using this as a background image (you can see the sprite in my demo if you want to set it up the same).

.flex-direction-nav a:before {
    display: block;
    position: absolute;
    content: '';
    width: 9px;
    height: 13px;
    top: 11px;
    left: 11px;
    background: url(../img/arrows.png) no-repeat;
}

To create the nice wrap ribbon effect we can use another pseudo selector :after. Then to create the actual shape we can use pure css with a little border trick that makes the triangle shape.
While we are at it let’s give them buttons some nice rounded corners. I have also included some of the positional styling below.

.flex-direction-nav .flex-next {
    right: -5px;

    -webkit-border-radius: 3px 0 0 3px;
    -moz-border-radius: 3px 0 0 3px;
    border-radius: 3px 0 0 3px;
}

.flex-direction-nav .flex-prev {
    left: -5px;

    -webkit-border-radius: 0 3px 3px 0;
    -moz-border-radius: 0 3px 3px 0;
    border-radius: 0 3px 3px 0;
}

.flex-direction-nav .flex-next:before { background-position: -9px 0; left: 15px; }
.flex-direction-nav .flex-prev:before { background-position: 0 0; }

.flex-direction-nav .flex-next:after {
    right: 0;
    border-bottom: 5px solid transparent;
    border-left: 5px solid #31611e;
}

.flex-direction-nav .flex-prev:after {
    left: 0;
    border-bottom: 5px solid transparent;
    border-right: 5px solid #31611e;
}

The controls AKA Pagination Icons

The slider controls are the little circles at the end of the slider that allows you to click on a slide. We’ll position this container at the bottom of the slider. Then we will create the circles using the “border-radius” and “box-shadow” property. For the active slide circle we will remove the box shadow and add the same CSS3 gradient that we used on the buttons.

.flexslider .flex-control-nav {
	position: absolute;
	width: 100%;
	bottom: -40px;
	text-align: center;
	margin: 0 0 0 -10px;
}

.flex-control-nav li {
	display: inline-block;
	zoom: 1;
}

.flex-control-paging li a {
	display: block;
	cursor: pointer;
	text-indent: -9999px;
	width: 12px;
	height: 12px;
	margin: 0 3px;
	background-color: #b6b6b6 9;

	-webkit-border-radius: 12px;
	-moz-border-radius: 12px;
	border-radius: 12px;

	-webkit-box-shadow: inset 0 0 0 2px #b6b6b6;
	-moz-box-shadow: inset 0 0 0 2px #b6b6b6;
	box-shadow: inset 0 0 0 2px #b6b6b6;
}

.flex-control-paging li a.flex-active {
	background-color: #bfab8b;
	background-image: -webkit-gradient(linear, left top, left bottom, from(#bfab8b), to(#f5e2c1));
	background-image: -webkit-linear-gradient(top, #bfab8b, #f5e2c1);
	background-image: -moz-linear-gradient(top, #bfab8b, #f5e2c1);
	background-image: -o-linear-gradient(top, #bfab8b, #f5e2c1);
	background-image: linear-gradient(to bottom, #bfab8b, #f5e2c1);

	-webkit-box-shadow: none;
	-moz-box-shadow: none;
	box-shadow: none;
}

Captions, Should you choose

A lot of people like to use captions with these sliders too, you do not have to but if you want them then here is how you can style them. To actually have captions all you need to do is include a paragraph in the slide.

.flexslider .slides p {
    display: block;
    position: absolute;
    left: 0;
    bottom: 0;
    padding: 0 5px;
    margin: 0;

    font-family: Helvetica, Arial, sans-serif;
    font-size: 12px;
    font-weight: bold;
    text-transform: uppercase;
    line-height: 20px;
    color: white;

    background-color: #222222;
    background: rgba(0,0,0, .9);

    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
}

Before we look at extending Flexslider here is a demo of your basic Flexslider all styled up and looking rather beautiful.

Extending Flexslider

Now how can you get more out of Flexslider? Well one thing that gets asked a lot of me is URL manipulation so that a user can get a link and it will take them straight to slide 3 for example.

This is where the “after” and “startAt” function used with Flexslider comes in really handy! You can use them mixed with a hash url function to get this to work easily.

$(window).load(function() {

	var index = 0, hash = window.location.hash;
	if (hash) {
            index = /d+/.exec(hash)[0];
            index = (parseInt(index) || 1) - 1;  
        }

var $slideshow = $('#slider');
$slideshow.flexslider({
    animation: 'fade',
    controlsContainer: '.flexslider'
    startAt: index, //now foo.html#3 will load item 3
    after:function(slider){
        window.location.hash = slider.currentSlide+1;
    });
});

That’s great but you want more!! So you have a little showcase slider and you want an opening cover then when you go through each slide you need a div to show the products featured on that slide… no problem! With some simple if and else statements we can get the slider to know what slide it is on and then run whatever function you see fit. The example below uses a div with the class of “products_slide” and then each would have a unique id. This is so the function can hide all the product divs first and then show a specific one that relates to the slide in view.

$(window).load(function() {

	var index = 0, hash = window.location.hash;
	if (hash) {
            index = /d+/.exec(hash)[0];
            index = (parseInt(index) || 1) - 1;  
        }

var $slideshow = $('#slider');
$slideshow.flexslider({
    animation: 'fade',
    controlsContainer: '.flexslider'
    startAt: index, //now foo.html#3 will load item 3
    after:function(slider){
        window.location.hash = slider.currentSlide+1;
        if (slider.currentSlide == 0) {
            $(".products_slide").hide();
            $("#products_slide1").show();
        }
        else if (slider.currentSlide == 1) {
            $(".products_slide").hide();
            $("#products_slide2").show();
        }	
        else if (slider.currentSlide == 2) {
            $(".products_slide").hide();
            $("#products_slide3").show();
        }			
    });
});

Pretty neat! Maybe on the cover it has a magazine type layout too and there are areas you want clickable to jump through to certian slides. For example you have a “find out more” link that shows you more detail on slide 3, then you would simply write this function:

$('.find-out-more').click(function(){
    $slideshow.flexslider(3);
});

Hope You Had Fun!

That should give you enough to get your teeth into and hopefully shows you that you can get a ready made plugin but then adapt to suit you more or make it more powerful. Know any more cool ways of extending Flexslider or other sliders? Then let me know, I want to know!!

A lot of you lovely folk have been asking how you can have a zoom function within flexslider, if that is what you are looking for then you might want to visit here.

30 thoughts on “Implementing, Styling and Extending Flexslider

  1. Mike

    Have you managed to put curved shadow effect on the slider like this(example 2)? Follow the url.
    I managed to make it, the problem now is that the z-index makes the shadows visible through the image slide area every time it fades.

    Reply
  2. Mundo Ecopet

    Great tips! thanks, thumbs up for you and success! I was actually looking for a slow zoom effect on every slide, like the one seen on other sliders, for a more dramatic effect, and think it may be not hard to implement, i hope. thanks again!

    Reply
  3. XParth

    Hello,

    I have implemented flexslider with a Drupal site. I am stuck at a point. The problem is my slides are building dynamically as they are configurable from Admin side. Like this:

    nid);
    $slide_text = $node->body[‘und’][0][‘value’];
    $slide_image = $node->field_slide_image[‘und’][0][‘uri’];
    ?>

    nid); ?>

    <img src="”>

    I need slide bullet thumbnails(DIV with “custom-navigation” class) below the as per the project designs. The problem here is that .read-more is within a foreach loop, So we what can’t put custom-navigation(bullets) inside the any loop. So what is the solution here?

    Any help would be appreciated.
    Thanks.

    Reply
  4. Paggio

    thanks for this great article. I really like it. One quick question: is it possible to extend the slider to dynamically load the images.
    Suppose that I have 20 images to display. Instead of displaying all of them, I would display 5 and on scrolling, load the others.

    Reply
    1. SHH DesignSHH Design Post author

      Hi

      You could try lazyloading in your slides, something like this?

      <section class="slider">
        <div class="flexslider">
          <ul class="slides">
            <li>
              <img src="your_image_link.jpg" alt="">
            </li>
            <li>
              <img class="lazy" data-src="your_image_link.jpg" alt="">
            </li>
            <li>
              <img class="lazy" data-src="your_image_link.jpg" alt="">
            </li>
            <li>
              <img class="lazy" data-src="your_image_link.jpg" alt="">
            </li>
            <li>
              <img class="lazy" data-src="your_image_link.jpg" alt="">
            </li>
          </ul>
        </div>
      </section>
      
      <!-- Scripts inserted before closing body tag of markup -->
      <script src="jquery.flexslider.min.js"></script>
      <script>
      $(window).load(function() {
        $('.flexslider').flexslider({
          touch: true,
          slideshow: false,
          controlNav: true,
          slideshowSpeed: 7000,
          animationSpeed: 600,
          initDelay: 0,
          start: function(slider) { // Fires when the slider loads the first slide
            var slide_count = slider.count - 1;
      
            $(slider)
              .find('img.lazy:eq(0)')
              .each(function() {
                var src = $(this).attr('data-src');
                $(this).attr('src', src).removeAttr('data-src');
              });
          },
          before: function(slider) { // Fires asynchronously with each slider animation
            var slides     = slider.slides,
                index      = slider.animatingTo,
                $slide     = $(slides[index]),
                $img       = $slide.find('img[data-src]'),
                current    = index,
                nxt_slide  = current + 1,
                prev_slide = current - 1;
      
            $slide
              .parent()
              .find('img.lazy:eq(' + current + '), img.lazy:eq(' + prev_slide + '), img.lazy:eq(' + nxt_slide + ')')
              .each(function() {
                var src = $(this).attr('data-src');
                $(this).attr('src', src).removeAttr('data-src');
              });
          }
        });
      });
      </script>
      Reply
  5. Aaron

    This is a great article. Thanks. Is there a way to add functional buttons to a slide?

    For example…I want to redirect users to another page on my site when they click a button that is inserted on a particular slide.

    Reply
    1. SHH DesignSHH Design Post author

      Hi

      Of course that would be no problem at all. You can add any html you like inside the code for each slide (inside the list items if you used that structure) and then position it over the top if need be. That is what I have to do with this plugin on a regular basis.

      Reply
  6. Harry

    Can’t tell you how helpful this post was. Just started playing with FlexSlider and can only imagine how much time this would saved me if I’d read it first…:-)

    Quick question…

    I’m trying to position the pagination on FlexSlider in the upper right hand corner of each slide on Desktop and tablets (in both portrait and landscape mode) and centered below the slide show on mobile.

    My slides are 600×300, but I’d like to be able to do it for different sized slideshows.

    I’m assuming I need to write media queries for each, but am not clear on how to write the CSS.

    Thanks in advance for any help you can be.

    Reply
    1. SHH DesignSHH Design Post author

      Hi

      You would need to have the slides themselves positioned relatively and then the pagination positioned absolutely to the top and right as needed. Then when you have your media queries for mobile take the pagination back to position relative and it should drop out below. Adjust the css to something like this:

      .flexslider .flex-control-nav {
      position: absolute;
      top: 20px;
      right: 20px;
      text-align: center;
      margin: 0 0 0 -10px;
      }

      and then at your media queries:

      @media screen and (max-width: 739px) {
      .flexslider .flex-control-nav {
      position: relative;
      width: 100%;
      top: 10px;
      right: 0px;
      }
      }

      I have a demo here if that helps and you can downlaod the files here too.

      Hope that helps!

      Reply
  7. Harry

    Wow! Thanks so much for not just getting back to me so quickly, but for creating a demo with files for me to use.

    Will let you know if I have any questions, but it seems simple enough… even for a newbie like me.

    Best,

    Harry

    Reply
    1. Harry

      Okay, I’m closer, but could use a little more help if you can spare the time.

      Take a look at the test I put up here:

      http://energywitness.com/test/

      Couple of questions:

      1. The only way I could get the pagination to not be hidden behind the first slide with the background was to to change the padding for the flexslider class from 10px to 40px, but that puts a border around the slide where I don’t want one. Ideally I’d prefer to have no border at all. How do I fix this?

      2. There also seems to be a layout issue with the Prev/Next controls, as there is a little red triangle right below each one.

      Thanks again for your help with this.

      Best,

      Harry

      Reply
      1. SHH DesignSHH Design Post author

        not a problem, glad to help. So first off the pagination is an easy one, you just need to give it a higher z-index like so:

        .flexslider .flex-control-nav {
        z-index: 2;
        }

        Then once you have removed the padding from the container you may see the direction arrows go behind the slides as well, again this is just a simple z-index fix:

        .flex-direction-nav a {
        z-index: 2;
        }

        I am not sure what little red arrows you can see as I cannot see any. If you perhaps mean the little shadows that are in place below the main squares with the direction arrow in, then this is there as a shadow to look like the direction buttons wrap around the slides. You can fix that by removing the :after styles, so you can remove this and it will fix that:

        .flex-direction-nav .flex-next::after {
        border-bottom: 5px solid transparent;
        border-left: 5px solid #580018;
        right: 0;
        }

        Hope that helps you further.

        Reply
        1. Harry

          Thanks so much. Now I get it about the shadows. Really great effect (especially without needing a graphic). Can’t wait to dig into more of your work. Can only imagine how much fun stuff I’ll find.

          Best,

          Harry

          Reply
  8. Harry

    At the risk of overstaying my welcome, was hoping you could help with one more.

    For the standard arrows that appear when you rollover the slide (http://tinyurl.com/nkdnlxd), they are always visible on mobile and in tablet portrait view. Is there a way to get them to hide until you rollover or touch the slide in all views?

    Thanks,

    Harry

    Reply
    1. SHH DesignSHH Design Post author

      Hi Harry

      Not a problem at all. It looks like on that demo in the flexslider.css file there is this code:

      @media screen and (max-width: 860px) {
      .flex-direction-nav .flex-prev {
      left: 0;
      opacity: 1;
      }
      .flex-direction-nav .flex-next {
      opacity: 1;
      right: 0;
      }
      }

      If you remove that it should work how you require. Although I would advise from a usability point of view it is probably best to have the arrows visible on touch devices and positioned in place so it easier for visitors to use.

      Reply
      1. Harry

        Thanks so much. Was wondering what that code was and then completely forgot about it…:-)

        Good point on the navigation, but good to know I have the option.

        Best,

        Harry

        Reply
  9. Hamizan Hamaffi

    Hi, i was wondering if i can make the caption on the slider be on the left/right side of the picture, and resize the picture in the preview

    Reply
    1. SHH DesignSHH Design Post author

      Hi

      If you inspect the version I have coded you should be able to see the CSS needed to achieve what you want. It will be a case of setting a width and height on the numbers and text-indent etc. It is detailed above if you look at the section about pagination.

      Reply
      1. newcaredentist

        Hi! Thank you for your answer.
        It’s a little complicated. The numbers I mentioned can’t be deleted. If I alter the text-indent, then a second set of numbers appears. The only way to make the first numbers disappear is to give them the property of “color:transparent;”. Weird thing.. Anyway, thanks again for your effort.

        Reply
  10. shawn

    First of all, i would like to say thank you for your sharing. I have one question to ask you.

    Take a look at my website I put up here: http://inbosz.com/

    My question is how can i change by background image for my next slider? I want to change the background according to the test show on it.

    Hope you can help me

    Thankx

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *