1

I'm trying to do image "carousel" with horizontal scroll. Pure HTML + CSS without JS.

This is my HTML:

<div class="slideshow">
    <figure class="slideshow__fig">
        <img src="img/hilti-png.png" alt="" class="slideshow__fig-img">
        <figcaption>Fig.1 - Trulli, Puglia, Italy.</figcaption>
    </figure>
    <figure class="slideshow__fig">
        <img src="img/hilti-png.png" alt="" class="slideshow__fig-img">
        <figcaption>Fig.1 - Trulli, Puglia, Italy.</figcaption>
    </figure>
    <figure class="slideshow__fig">
        <img src="img/hilti-png.png" alt="p" class="slideshow__fig-img">
        <figcaption>Fig.1 - Trulli, Puglia, Italy.</figcaption>
    </figure>
</div>

This is my css:

.slideshow {

display: flex;
flex-wrap: nowrap;
overflow-y: hidden;
overflow-x: scroll;
//width: 80vw;
//margin: auto;

&::-webkit-scrollbar {
    width: 350px;
    height: 10px;
  }
  
  /* Track */
  &::-webkit-scrollbar-track {
    background: #f1f1f1; 
  }
   
  /* Handle */
  &::-webkit-scrollbar-thumb {
    background: #888; 
    border-radius: 500px;
  }
  
  /* Handle on hover */
  &::-webkit-scrollbar-thumb:hover {
    background: #555; 
  }


&__fig {
    flex: 0 0 auto;
    height: 900px;

    &-img{
        height: 100%;
        //width: 100%;
        display: block;
    }
}

}

1 - The problem is when I set the width of the .slideshow to 80vw, then naturally the scrollbar is shorter, but my images are cropped and not going full display width. When I try to adjust the width of the scrollbar with ::-webkit-scrollbar {width: 350px or 50vw or ...} exactly nothing happens.

I would like to have a scrollbar which is not full width of the div which I'm scrolling, but somehow can't figure it out.

2 - The other problem is I would like to have a figcaption at the bottom left side of the image. But somehow it doesn't show when the horizontal scroll is there. Any suggestions?

Here is the example how I would like to have it:

example image

edit: Now I finally managed to do it by adding:

&::-webkit-scrollbar-button:end:increment {
    width: 50%;
    display: block;
    background: transparent;
  }

But now the problem is that the scrollbar is not in middle, but on the left side. Margin:auto doesn't help. No idea how else to do it.

Also making img size 90% revealed the caption which is not that bad solution.

Now the only question is how to put the scroll bar in the centre.

HomoHabilis
  • 37
  • 1
  • 7

1 Answers1

1

Here is something close to the image you provided as an example. Sorry, but I really don't know how this can be achieved respecting the Pure HTML + CSS without JS criteria. I think it isn't possible at all.

So here, it uses jQuery and jQuery-ui draggable.

It uses a draggable div contained within its parent. Ondrag, it calculates the "scrolled" percentage to apply it to the scrollable width of the image slider.

For mobiles... I added the "touch punch" patch for jQuery-ui. More details about it here. I also placed the "initialisation code" in a function, so it can run on load AND on resize.

$(document).ready(function(){
  function initDisplay(){
    let slide_scrollWidth = $("#slide")[0].scrollWidth;
    let customScrollbar_width = $("#sliderScroll_outer")[0].scrollWidth;
    let percent = slide_scrollWidth/customScrollbar_width
    $("#sliderScroll").css({"width":percent+"%", "left":0})
    $("#slide")[0].scrollTo(0,0)
  }

  // On page load
  initDisplay()

  // Useful for mobile orientation change
  window.onresize = initDisplay

  $("#sliderScroll").draggable({ 
    containment: "#sliderScroll_outer",
    scroll: false,
    drag: function(e){

      let parentOffset = $(e.target).parent().offset().left
      let offset = $(e.target).offset().left
      let scrollableWidth = $(e.target).parent().width() - $(e.target).width()
      let sliderPercent = (offset-parentOffset)/scrollableWidth
      //console.log(sliderPercent)

      let imageSliderWidth = $("#slide")[0].scrollWidth - $("#slide").width()

      //console.log(imageSliderWidth)

      $("#slide")[0].scrollTo(sliderPercent*imageSliderWidth,0)
    }
  });
});
#container{
  margin: 1em;
}

#slide{
  display: flex;
  overflow: hidden;
}

#slide img{
  margin: 0 0.5em;
}

#sliderScroll_outer{
  width: 40vw;
  background: lightgrey;
  margin: 1em;
}
#sliderScroll{
  width: 0vw;
  height: 10px;
  background: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.2/jquery.ui.touch-punch.min.js"></script>

<div id="container">

  <div id="slide">
    <img src="https://via.placeholder.com/800x600.png">
    <img src="https://via.placeholder.com/400x600.png">
    <img src="https://via.placeholder.com/1000x600.png">
  </div>

  <div id="sliderScroll_outer">
    <div id="sliderScroll"></div>
  </div>

</div>

Run in full page mode or CodePen

Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64
  • Thank you very much for your input, I really appreciate it. Wow, it's much more complicated as I thought. I was thinking about something like margin: auto kind of solution, haha. I tried this code, and I think it works fine on desktop, but I think it doesn't work on mobile devices. Maybe it just need a tweak, but as I'm a beginner I wouldn't even try to change this code. Right, maybe I tried to do too much with too little knowledge :) – HomoHabilis Dec 21 '20 at 10:55
  • For Mobile, you just have to add a jQuery-ui patch called[Touch Punch](https://cdnjs.com/libraries/jqueryui-touch-punch/0.2.2) as [this other SO answer](https://stackoverflow.com/a/13940644/2159528) says... ;) I tried in my codePen and it works fine without any change to the code above. ;) – Louys Patrice Bessette Dec 21 '20 at 15:14
  • Gna! I edited anyway, size it absolutely needs an `onresize` handler for mobile. ;) – Louys Patrice Bessette Dec 21 '20 at 15:32
  • Thanks a lot. I will try definitely try it and try to understand. Would give you an upvote, but can't as my rank is too low. Already tried to do it. – HomoHabilis Dec 21 '20 at 17:06
  • You can click the green check mark to accept the answer. ;) – Louys Patrice Bessette Dec 21 '20 at 17:22