Reputation: 387
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.
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
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
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
Reputation: 78686
The idea is to set the background on a fixed element, and put the list on top of it.
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
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;
}
Upvotes: 0
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