Enzio
Enzio

Reputation: 387

Overflow scroll without hiding it's overflowing content

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/

Upvotes: 8

Views: 5902

Answers (5)

Данил Д
Данил Д

Reputation: 1

$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>

Upvotes: 0

Alynva
Alynva

Reputation: 558

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

Upvotes: 3

Stickers
Stickers

Reputation: 78686

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>

Upvotes: 1

Ivin Raj
Ivin Raj

Reputation: 3429

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

Upvotes: 0

Karl Dawson
Karl Dawson

Reputation: 977

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>

Upvotes: 0

Related Questions