2

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.

ErmIg
  • 3,980
  • 1
  • 27
  • 40
Deedub
  • 349
  • 2
  • 7
  • 20
  • yes, you can position the inner ul and move it, or you can also hide all the li's and show them one by one – Thapedict Feb 16 '17 at 01:17
  • i'd rather they fill the space depending on the amount available. So I could use .animate and then move it every 140px + or - depending? If I position it absolute, it loses the overflow hidden – Deedub Feb 16 '17 at 01:35
  • you can get sample from https://jsbin.com/cokosodone/edit?html,css,js,output which i tried for you. for reference you can use https://www.w3schools.com/howto/howto_js_slideshow.asp – Ranjith Feb 16 '17 at 05:20
  • Possible duplicate of [JavaScript carousel](http://stackoverflow.com/questions/12527470/javascript-carousel) – Bill Feb 16 '17 at 15:37
  • @Bill, i need to ask you something. Do you consider that, if a person set out to create a carousel from scratch and wanted to shoot a question on SO, giving a few, not many, specifics, nobody else should ever ask how to create a carousel again? Especially if the answer to the first question (being a fairly general one) would just be some links? What should I do tomorrow, when you'll ask, with slightly different concerns? Mark it as duplicate? Or would like me to answer yours, too? – tao Feb 16 '17 at 15:58
  • @AndreiGheorghiu The correct approach would be to suggest an edit to the question and/or answer such that it is more generic. Questions which focus on specific use cases or implementations are not really helpful to others. – Bill Feb 17 '17 at 10:42
  • @Bill If the carousel is for a different purpose/use-case, i think the correct approach would be fairly difficult to apply to this particular question. In the sense that it doesn't seem fair (nor simple) to modify someone else's request for advice on a particular type of carousel and make it apply to all carousel types. I agree with you on the general principle, though. I think it's an interesting *niche* regarding question types. – tao Feb 17 '17 at 14:26

1 Answers1

1

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.

tao
  • 82,996
  • 16
  • 114
  • 150
  • wow, Andre, thanks so much this is great. Am gonna goof around with it. thank you!! A quick question, how do I have multiple slides in one? say the container is 1000px but each slider is only 140px and I want them to fit in there as many as possilbe? – Deedub Feb 16 '17 at 15:23
  • If the number of slides is equal to the step, than you don't really have multiple slides, do you? You just put more than 1 item inside a container, which is the actual slide, right? If you have different step... Well, this solution doesn't scale so well with that. It can be tinkered via js, but it will probably take a bit of fooling around to get right. :) – tao Feb 16 '17 at 15:50