Slick Slider - how to keep the active pagination (dot) always centered
Asked Answered
F

4

10

I am trying to achieve something which I haven't seen done so far on the web. I want the active pagination dot in the slick slider to always be in the center.

This is the expected result:

Image of dots centered

In other words I would expect the page to load showing the first slide but the pagination dot for the first slide should be centered.

If a user clicks the next slide by swiping then the dot should move the middle again, with the active slide always being centered in the pagination. Any ideas on the best way to achieve this?

Here's an example and code of what i've done so far.

$('.slider').slick({
  infinite: true,
  dots: true,
  arrows: false
});
.slider {
  width: 200px;
}

.slide img {
  display: block;
  width: 100%;
  height: auto;
}

.slick-dots {
  display: flex;
  justify-content: center;
  margin: 0;
  padding: 1rem 0;
  list-style-type: none;
}

.slick-dots li {
  margin: 0 0.25rem;
}

.slick-dots button {
  display: block;
  width: 1rem;
  height: 1rem;
  padding: 0;
  border: none;
  border-radius: 100%;
  background-color: grey;
  text-indent: -9999px;
}

.slick-dots li.slick-active button {
  background-color: blue;
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E=" crossorigin="anonymous"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/[email protected]/slick/slick.css" />
<div class="slider">
  <div class="slide">
    <img src="http://placehold.it/200x100?text=1" />
  </div>
  <div class="slide">
    <img src="http://placehold.it/200x100?text=2" />
  </div>
  <div class="slide">
    <img src="http://placehold.it/200x100?text=3" />
  </div>
  <div class="slide">
    <img src="http://placehold.it/200x100?text=4" />
  </div>
  <div class="slide">
    <img src="http://placehold.it/200x100?text=5" />
  </div>
</div>
Fransiscafransisco answered 30/8, 2018 at 10:5 Comment(4)
you can use custom events beforeChange and àfterChange to start a css animation. How the animation looks like, I dont know. But you can add a class to for the current PositionKrohn
What if you have even numbers of elements? like 6 dots or 8 dots? Which dot will be active?Cupola
@MuhammadOsama there will always be 5Fransiscafransisco
I just think that if the active dot is always in the center so why not use static HTML because nothing will change. It's just static :))Epidermis
M
13

for that you have to add one more slider as per my snippet and the use Slider Syncing functionality to bind both slider.

here is an working example for that

$(document).ready(function() {
  $(".main_slider").slick({
    infinite: true,
    dots: false,
    arrows: false,
    asNavFor: '.slider_dots',
    slidesToShow: 1,
    slidesToScroll: 1,
  });
  $('.slider_dots').slick({
    infinite: true,
    slidesToShow: 3,
    slidesToScroll: 1,
    asNavFor: '.main_slider',
    arrows: false,
    dots: false,
    centerMode: true,
    focusOnSelect: true,
    centerPadding: '20%',
  });
});
.main_slider,
.slider_dots {
  width: 200px;
}

.slide img {
  display: block;
  width: 100%;
  height: auto;
}

.slick-dots {
  display: flex;
  justify-content: center;
  margin: 0;
  padding: 1rem 0;
  list-style-type: none;
}

.slick-dots li {
  margin: 0 0.25rem;
}

.slick-dots button {
  display: block;
  width: 1rem;
  height: 1rem;
  padding: 0;
  border: none;
  border-radius: 100%;
  background-color: grey;
  text-indent: -9999px;
}

.slick-dots li.slick-active button {
  background-color: blue;
}

.slider_dots .slider_navigators {
  height: 20px;
  background-color: #9E9E9E;
  border-radius: 50%;
  margin: 10px;
  transform: scale(0.4);
  outline: none;
  cursor: pointer;
}

.slider_dots .slider_navigators.slick-active {
  transform: scale(0.70);
}

.slider_navigators.slick-active.slick-current {
  transform: scale(1);
  background-color: #00f;
}
<!DOCTYPE html>
<html>

<head>
  <title>Demo Page</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script>
</head>

<body>
  <div class="main_slider">
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
    <div class="slide">
      <img src="https://via.placeholder.com/350x150" />
    </div>
  </div>
  <div class="slider_dots">
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
    <div class="slider_navigators"></div>
  </div>
</body>

</html>

I hope you are getting your solution from my snippet code.

Mcqueen answered 17/12, 2019 at 14:34 Comment(0)
J
4
.on('beforeChange', function(event, slick, currentSlide, nextSlide){
  //appedn the bullet on center 
});

Something like this

Codepen

Jungly answered 30/8, 2018 at 11:8 Comment(1)
That's nothing like what's expected.Fransiscafransisco
M
1

Here's an example that uses a bit of jQuery to manipulate the styles of the existing slide dots. Another example of the working code can be found here: https://codepen.io/edlucas/pen/XWJRmbb

The only caveat is that the <li> tags containing the dots must all be the same width for the math to work out. This solution will work with any number of dots in a single line.

const $slideShow = $('.slider');

function offsetDots(slideNum) {
  const $slickDots = $slideShow.find('.slick-dots'),
    numDots = $slickDots.find('li').length,
    dotWidth = $slickDots.find('li:first').outerWidth(true),
    offset = dotWidth * slideNum;
  
  // Offset the dots container to center current slide dot
  $slickDots.css('marginLeft', offset * -1 - Math.ceil(dotWidth / 2));
  
  // Clear existing secondary dot class
  $slickDots.find('li').removeClass('slick-secondary');

  // Add secondary dot class to preceeding slide dot
  if (slideNum > 0) {
    $slickDots.find('li:nth-of-type('+slideNum+')').addClass('slick-secondary');
  }

  // Add secondary dot class to next slide dot
  if (slideNum < numDots - 1) {
    $slickDots.find('li:nth-of-type('+(slideNum + 2)+')').addClass('slick-secondary');
  }
}

$slideShow.on('init', function(event, slick) {
  offsetDots(0);
});

$slideShow.on('beforeChange', function(event, slick, currentSlide, nextSlide) {
  offsetDots(nextSlide);
});

$slideShow.slick({
  infinite: true,
  dots: true,
  arrows: false
});
.demo-wrapper{
  width: 200px;
  position: relative;
}

.slide img {
  display: block;
  width: 100%;
  height: auto;
}

.slick-dots {
  position: absolute;
  left: 50%;
  display: inline-flex;
  margin: 0;
  padding: 1rem 0;
  list-style-type: none;
}

.slick-dots li {
  width: 12px;
  margin: 0 3px;
}

.slick-dots button {
  display: block;
  width: 6px;
  height: 6px;
  padding: 0;
  margin: 0 auto;
  border: none;
  border-radius: 100%;
  background-color: grey;
  text-indent: -9999px;
}

.slick-dots li.slick-active button {
  background-color: blue;
  width: 12px;
  height: 12px;
  margin-top:-4px
}

.slick-dots li.slick-secondary button {
  width: 8px;
  height: 8px;
  margin-top: -1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/[email protected]/slick/slick.css" />

<div class="demo-wrapper">
<div class="slider">
  <div class="slide">
    <img src="https://loremflickr.com/200/200/lego?random=1" />
  </div>
  <div class="slide">
    <img src="https://loremflickr.com/200/200/lego?random=2" />
  </div>
  <div class="slide">
    <img src="https://loremflickr.com/200/200/lego?random=3" />
  </div>
  <div class="slide">
    <img src="https://loremflickr.com/200/200/lego?random=4" />
  </div>
  <div class="slide">
    <img src="https://loremflickr.com/200/200/lego?random=5" />
  </div>
</div>
</div>
Mythomania answered 22/12, 2019 at 13:18 Comment(0)
A
0

If you need to achieve this properly, then you can try Abhishek Pandey solution.

If you just need to solve it quickly, then you can try shortcut approach like making the slider to start from slide 3 instead of slide 1

as your slider navigations are just dots with no numbers, site users doesn't going to recognize that slider is starting from slide 3

Appendicle answered 21/12, 2019 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.