8

I am trying to create a 'slider' where a user is able to scroll horizontally to navigate to certain 'slider items'. I'm trying to create this with pure css, however; I can't seem to get it working right.

Start: enter image description here

End: enter image description here

Alright, let me explain the pictures a little. Everything within 'Window' is visible. That means also the overflow from the unordered list. What I want is to make the user able to scroll horizontally within the container to move the unordered list. However; I can't use overflow: hidden or overflow: scroll on the 'container' since it will hide all the overflowing content, which I do not want.

How can I achieve this or is it even possible to achieve with pure CSS?

My current code: https://jsfiddle.net/f0exzxkw/2/

4
  • 3
    can you add your code Commented Jan 18, 2016 at 10:36
  • Just to confirm: you want a solution whereby none of the content of the Unordered list is visible outside of the container, but you can scroll through each element of the list within the container? On what element do you want the scrollbar to be? Commented Jan 18, 2016 at 11:15
  • please Check it sir @EnzioPixel Commented Jan 18, 2016 at 11:35
  • @IStanley No, I want the content of the Unordered list to be visible. And I want the 'container' to act like an 'overflow: scroll' but without hiding the overflowing content. Commented Jan 18, 2016 at 11:38

5 Answers 5

3

I started using the SwiperJs as @Karl mentioned (demo: https://swiper-demo-13-centered-1j4bnx.stackblitz.io/), but after that i started try without it. There is a lot of tricks, and a lot of them can be different and be improved. But, to align correctly the scrollbar, you have to use a custom one. The main idea was have a negative margin on .scroll-container, using CSS Variables to calculate the space scross the elements.

:root {
    --WINDOW-X-SPACE: 20px;
    --CONTAINER-X-SPACE: 30px;
}

* {
    box-sizing: border-box;
}
html, body {
    height: 100vh;
}
body {
    background: teal;
    margin: 0;
    padding: 20px var(--WINDOW-X-SPACE);
    overflow-x: hidden;
}
main {
    padding: 10px var(--CONTAINER-X-SPACE);
    background: purple;
}
.scroll-container {
    height: 200px;
    margin: 0 calc(-1 * calc(var(--WINDOW-X-SPACE) + var(--CONTAINER-X-SPACE)));
    padding: 0 var(--WINDOW-X-SPACE);
    display: flex;
    overflow: auto;
}
.scroll-container::-webkit-scrollbar {
    all: unset;
}
 
.scroll-container::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); 
    border-radius: 10px;
    margin: 0 var(--WINDOW-X-SPACE);
}
 
.scroll-container::-webkit-scrollbar-thumb {
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5); 
    background-color: white;
}
.list-wrapper {
    background: orange;
    width: fit-content;
    height: 100%;
    display: flex;
    margin: 0;
    padding: 0;
    padding-top: 40px;
    position: relative;
}
.list-wrapper:before {
    content: "Unordened list";
    display: block;
    position: absolute;
    left: 15px;
    top: 12px;
}
.list-item {
    text-align: center;
    font-size: 18px;
    background: rgba(255, 255, 255, .5);
    border: solid 1px orange;
    width: 100px;
    flex-shrink: 0;
    height: 100%;

    /* Center slide text vertically */
    display: flex;
    justify-content: center;
    align-items: center;
}

.fix-offset {
    width: var(--WINDOW-X-SPACE);
    flex-shrink: 0;
}
<h4>Window</h4>
<main>
    <h4>Container</h4>
    <div class="scroll-container">
        <ul class="list-wrapper">
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
            <div class="list-item">List item</div>
        </ul>
        <span class="fix-offset"></span>
    </div>
</main>

Try it: https://codepen.io/Alynva/full/gOPaGVX

Sign up to request clarification or add additional context in comments.

Comments

1

The idea is to set the background on a fixed element, and put the list on top of it.

Jsfiddle Example

body {
  background: teal;
  margin: 0;
}
.background {
  background: purple;
  width: 80vw;
  height: 80vh;
  position: fixed;
  left: 10vw;
  top: 10vh;
}
.scrollable {
  list-style-type: none;
  position: relative;
  display: flex;
  padding: 0;
  margin: 20vh 0 0 10vw;
  height: 60vh;
}
.scrollable li {
  padding: 10px;
  background: orange;
  height: 100%;
  flex: 0 0 50vw;
  border: 1px solid darkorange;
  box-sizing: border-box;
}
<div class="background"></div>
<ul class="scrollable">
  <li>List item</li>
  <li>List item</li>
  <li>List item</li>
  <li>List item</li>
</ul>

Comments

0

Try this (adjust specific values / units to suit):

html, body {
  margin: 0;
  padding: 0;
  background: #12969D;
}

.container {
  height: 90vh;
  width: 90vw;
  padding: 40px 0;
  box-sizing: border-box;
  border: 1px solid black;
  background: #6B00BE;
  margin: 5vh auto;
}

ul {
  height: 100%;
  width: calc(100% + 75px);
  padding: 0;
  background: #FFBD37;
  list-style-type: none;
  box-sizing: border-box;
  overflow-x: scroll;
  overflow-y: hidden;
  white-space:nowrap;
}

li {
  padding: 10px;
  display: inline-block;
  background: #FFD787;
  height: 100%;
  width: 50vw;
  border: 1px solid black;
}
<div class="container">
  <ul>
    <li>List item</li>
    <li>List item</li>
    <li>List item</li>
    <li>List item</li>
  </ul>
</div>

2 Comments

Thanks for the code example, however indeed the end position is not right plus the overflow on the left side is hidden. I want all overflow to be visible but to act like an 'overflow: scroll'.
Hmmm, at the risk of leaping to JavaScript too soon and accepting that the overflow thing isn't going to work out for you, this swiper demo: idangero.us/swiper/demos/13-scrollbar.html is pretty close. Have you seen the pattern you're after in the wild at all - maybe try and reverse engineer it?
0

please try this one:

html

<div id="project-slider">
   <div class="container">
      <ul class="items-holder">
         <li class="item" style="background: blue;"></li>
         <li class="item" style="background: red;"></li>
         <li class="item" style="background: green;"></li>
      </div>
   </div>
</div>

<div>
  <p>
    Just to show that currently the window is scrolling instead of the container.
  </p>
</div>

css

html, body {
  margin: 0;
  padding: 0;
  background: #12969D;
}

.container {
  height: 90vh;
  width: 90vw;
  padding: 40px 0;
  box-sizing: border-box;
  border: 1px solid black;
  background: #6B00BE;
  margin: 5vh auto;
}

ul {
  height: 100%;
  width: calc(100% + 75px);
  padding: 0;
  background: #FFBD37;
  list-style-type: none;
  box-sizing: border-box;
  overflow-x: scroll;
  overflow-y: hidden;
  white-space:nowrap;
}

li {
  padding: 10px;
  display: inline-block;
  background: #FFD787;
  height: 100%;
  width: 50vw;
  border: 1px solid black;
}

DEMO HERE

1 Comment

Thanks for the comment. Please read my response on Karl's comment.
0

$container-width: 1160px;
$responsive-padding: 16px;

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  max-width: $container-width;
  margin: 0 auto;

  padding: 0 $responsive-padding;
  box-sizing: content-box;
}

.slider {
  background: rgb(210, 208, 255);
  padding: 80px 0;
  min-height: 100vh;
  

  &__track {
    margin-top: 30px;
    display: flex;
    gap: 20px;
    overflow: scroll;
    padding: 10px 0;

    /* Hide scrollbar for IE, Edge and Firefox */
    -ms-overflow-style: none; /* IE and Edge */
    scrollbar-width: none;
  }

  /* Hide scrollbar for Chrome, Safari and Opera */
  &__track::-webkit-scrollbar {
    display: none;
  }

  &__item {
    min-width: 600px;
    min-height: 180px;
    background: rgb(255, 255, 255);
    border-radius: 20px;

    /* CORE LOGIC */
    &:first-child {
      margin-left: calc((100vw - $container-width) / 2);
    }
    &:last-child {
      margin-right: calc((100vw - $container-width) / 2);
    }
  }
}

/* CORE LOGIC (responsive) @optional */
@media (max-width: calc($container-width + $responsive-padding)) {
  .slider {
    &__item {
      &:first-child {
        margin-left: $responsive-padding;
      }
      &:last-child {
        margin-right: $responsive-padding;
      }
    }
  }
}
  <section class="slider">
    <div class="container">
      <h2 class="slider__title">Slider track</h2>
      <p>Without container, but with left side space</p>
    </div>
      <div class="slider__track">
        <div class="slider__item"></div>
        <div class="slider__item"></div>
        <div class="slider__item"></div>
        <div class="slider__item"></div>
        <div class="slider__item"></div>
      </div>
  </section>

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.