Deedub
Deedub

Reputation: 349

Trying to Code a Simple Carousel

I am trying to build a simple carousel, I know there are many out there, but I prefer to try and figure this out.

Here is my the carousel code

<div class="amnavigation">
<div class="previous"><</div>
    <ul>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
        <li>icon</li>
    </ul>
    <div class="next">></div>

  </div>

and the css

.amnavigation {
  height: 140px;
  overflow: hidden;
  display: flex;
  height: 140px;
  overflow: hidden;
  display: flex;
  max-width: 1000px;
  margin: auto; }
  .amnavigation ul li {
    width: 140px;
    height: 140px;
    background: #999;
    display: inline-block;
    margin: 5px; }

I am not even sure where to begin with and what function to use.

would I position the inner ul in the parent container, then move that container by 140px (or whatever) left or right depending?

here is a fiddle
https://jsfiddle.net/L1v2uyxd/

ANY advice is much appreciated as is patience since am trying to learn.

Upvotes: 2

Views: 657

Answers (1)

tao
tao

Reputation: 90287

Here's a few things to consider, before you start:

  • There is no point in telling the browser to style those items as an unordered list only to have to override those display rules. Use <div>isions and <span>s. Or even custom elements (no default styling!)

  • Decide if your carousel will be a proper slider or just fade items in/out. Because the fader is rather simple and straight forward (you just animate opacity), I'm going to assume it's a slider.

  • On larger screens you want to decide if your carousel is boxed or goes full width. I personally find the full width more natural but some prefer it boxed. I made it full here.

  • Decide if you want finite or infinite slider. I'm going to assume it's a looper. If you don't want that, just remove the js that appends/prepends the items on slide.

  • Decide if the track will have variable height. This is important because you might want to wrap it in an extra height placeholder, so you can separate the animations. When doing something as complex as a slider, you want to keep things as tidy and clean as possible regarding animations. They get complex enough later on.

Now, given the above, go through this, starting with CSS. I've layed it out in steps (basic setup, slider layout, animations). The js was made at animations step. The point was not to create a slider for you, but to walk you through the process so you have an example.

/* 
 * go to CSS first, I'll send you back here when when it's time
 */

$(window).on('load', function(){
  var slides = $('slider slide');
  slides.each(function(){
    // add 'before' and 'after' classes to all and `active` to first
    $(this).addClass( 
      $(this).index() ? (
        $(this).index() > (slides.length / 2) ?'before':'after'
      ) : 'active'
    );
  });
  
  // place all `.before` slides before `.active` in DOM
  $(slides.get().reverse()).each(function(){
    if ($(this).is('.before')) {
      $(this).prependTo($(this).parent());
    }
  });
})

function goNext() {
    active = $('slider .active');
    active.next().addClass('active').removeClass('after');
    active.addClass('before').removeClass('active');
    $('slider slide').first().removeClass('before').appendTo($('slider')).addClass('after')
  }
  function goPrev() {
    active = $('slider .active');
    active.prev().addClass('active').removeClass('before');
    active.addClass('after').removeClass('active');
    $('slider slide').last().removeClass('after').prependTo($('slider')).addClass('before')
 }
body {
  margin: 0;
  text-align: center;
  overflow-x: hidden;
}
[flex] {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
* {
  box-sizing: border-box;
}
.content {
  width: 80vw;
  border: 1px solid #aaa;
  text-align: initial;
  margin: 0 auto;
  min-height: 100vh;
}
.header {
  min-height: 4rem;
  text-align: center;
 
}
.rest-of-page {
  padding: 1rem;
}
/* the above is just setup - ignore it 
 * here comes the juice.
 * I used custom html elements so nothing would be default
 * this way I needed to put in all required css attributes
 * not relying on default styles by browser
 */

slider-container {
  border: solid red;
  border-width: 1px 0;
  display: block;
  width: 100vw;
  
  /* left margin equal with half the difference 
   * between .content width and and viewport width:
   */
  left: calc((100% - 100vw) / 2); 
  position: relative;
  overflow: hidden;
  min-height: 300px;
  text-align: center;
}
slide[flex] {
  position: absolute;
  top: 1rem;
  width: 80vw;
  margin: 0 10vw;
  height: calc(100% - 4rem);
  background-color: #777;
  color: white;
  
  /* making sure slides don't render before everything loads */ 
  display: none;
    
  transition: transform .42s cubic-bezier(.4,0,.2,1);
}
slider-container .navigation {
  position: absolute;
  bottom: 0;
  display: flex;
  width: 100%;
  justify-content: center;
}
slider-container .navigation > * {
  width: 2rem;
  height: 2rem;
  border: 1px solid #242424;
  margin: .5rem .25rem;
  cursor: pointer;
}

/* all the layout is set so far - all items in place 
 * now we want to handle slider positions and animations
 * disable the code below to see what we got so far
 * this is where javascript steps in
 */

slider .active,
slider .before,
slider .after {
  display: flex;
}
.before {
  transform: translateX(-100vw);
}
.after {
  transform: translateX(100vw);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
  <div class="header" flex>Header here</div>  
  <slider-container>
    <slider>
      <slide flex>icon 1</slide>
      <slide flex>icon 2</slide>
      <slide flex>icon 3</slide>
      <slide flex>icon 4</slide>
      <slide flex>icon 5</slide>
      <slide flex>icon 6</slide>
      <slide flex>icon 7</slide>
      <slide flex>icon 8</slide>
      <slide flex>icon 9</slide>
      <slide flex>icon 10</slide>
      <slide flex>icon 11</slide>
      <slide flex>icon 12</slide>
      <slide flex>icon 13</slide>
      <slide flex>icon 14</slide>
      <slide flex>icon 15</slide>
    </slider>
    <div class="navigation">
      <div class="previous" flex onclick="javascript:goPrev()">&lt;</div>
      <div class="next" flex  onclick="javascript:goNext()">></div>
    </div>
  </slider-container>
  <div class="rest-of-page">Content here</div>  
</div>

After this, you need a few more things:

  • adaptive height
  • dot controls
  • go to slide
  • touch events and behavior
  • more responsiveness (proper)
  • de-registering events/behavior (you might want to remove all events/behavior on mobile and just display all slides one below the other) - de-register is important if you want to be able to re-init.
  • have more than one active slide
  • implement step (slide more than one item at a time)
  • enable swipe (and stickyness)
  • zoom to full screen
  • zoom in full size with panning inside a single slide on device that have smaller screen than your slides (it's a feature sometimes required for e-commerce product sliders)

I'm not saying: do like me. You should build yours. But I laid out how I'd do it, with the hope it might help. I assume this is why you asked.

Upvotes: 1

Related Questions