Home > database >  Apply CSS styling to left and right arrows for this div slide?
Apply CSS styling to left and right arrows for this div slide?

Time:06-16

I've got this little project I'm hoping to add to my website. It's a simple div slider with arrows. So far, I've coded up to this extent, and I need help to include two key features to this slider:

------------------------------ Two features I'm trying to achieve ------------------------------

Feature One: I want to apply some sort of CSS styling to this slider, telling the user that they have reached the end of the slider. That is, if a user clicks left to the last item, disable or change style of the left arrow. Likewise, if a user clicks right to the last item, disable or change style of the right arrow.

Feature Two: You will notice that currently, there are eight div slides in the slider. Now, try commenting four of the slides. Clicking any arrow naturally wouldn't work as 4 slides is the maximum limit. I want both arrows to be disabled when the div slides are less than or equal to 4.

let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')

let container = document.getElementById('slider')

buttonLeft.addEventListener('click', function() {
  container.scrollLeft -= 90
})

buttonRight.addEventListener('click', function() {
  container.scrollLeft  = 90
})
body {
  background-color: #555;
  height: 100vh;
  display: grid;
  align-items: center;
  justify-items: center;
  font-family: 'Helvetica';
}

div#slide_wrapper {
  width: 440px;
  display: flex;
  justify-content: space-between;
  height: fit-content;
}

div#slider {
  width: 350px;
  display: flex;
  height: fit-content;
  flex-wrap: nowrap;
  overflow: hidden;
}

div.thumbnail {
  min-width: 80px;
  min-height: 80px;
  cursor: pointer;
  display: grid;
  place-items: center;
  font-size: 30px;
}

div.thumbnail:not(:last-child) {
  margin-right: 10px;
}

div.thumbnail:nth-child(1) {
  background-color: darkturquoise;
}

div.thumbnail:nth-child(2) {
  background-color: goldenrod;
}

div.thumbnail:nth-child(3) {
  background-color: rebeccapurple;
}

div.thumbnail:nth-child(4) {
  background-color: powderblue;
}

div.thumbnail:nth-child(5) {
  background-color: firebrick;
}

div.thumbnail:nth-child(6) {
  background-color: sienna;
}

div.thumbnail:nth-child(7) {
  background-color: bisque;
}

div.thumbnail:nth-child(8) {
  background-color: navy;
}

div#slide_wrapper>button {
  height: fit-content;
  align-self: center;
  font-size: 24px;
  font-weight: 800;
  border: none;
  outline: none;
}

div#slide_wrapper>button:hover {
  cursor: pointer;
}
<div id="slide_wrapper">
  <button id="slide_left" >&#10094;</button>
  <div id="slider">
    <div >1</div>
    <div >2</div>
    <div >3</div>
    <div >4</div>
    <div >5</div>
    <div >6</div>
    <div >7</div>
    <div >8</div>
  </div>
  <button id="slide_right" >&#10095;</button>
</div>

Please help me solve this.

CodePudding user response:

I just added a fe JS lines to do the tasks for you. If the end of oen slide is reached a class to the button is added to change the visibility to hidden. You can change the CSS settings as you deem fit or apply other changes directly through JS however you like. This example is just to show you how you could do it:

At start I added a few variables:
slidesAmount => The number of your total slides. EDIT: Is now calculated by the script so you do not have tos et it manually
slidesPerScreen => How many slides are dispalyed at the same time on screen
currentSlideCounter => The slide numebr that is display at the very left
maxSlideCounter => is a calculated variable to mark the end of the possible slides to the right.

Then I added to your functiosn an if-statement to raise or lower the counter currentSledeCounter to keep it updated. The if-statement ensures that you dont lwoer or raise that counter when you reached that specific end.

Last but not least I added a function with a switch-statement that applies a class to the button when an end has reached or removes the classes when not end is reached yet.

EDIT: I added an eventLister onl oad to run the script at the start so that by default the left arrow is hidden.

EDIT 2: There was a bug that occured because of the switch-statement logic if there is just one more slideAmount then the slidesPerScreen. So I remoevd the switch statement and simpliefied the logic. It now removes all class by start and adds the class if a certain end has reached:

/* eventListener to run the script at the start and hdie left button automatically */
window.addEventListener("load", change);


var slidesAmount = document.querySelectorAll('#slider .thumbnail').length,
    slidesPerScreen = 4;
var currentSlideCounter = 1;
var maxSlideCounter = slidesAmount - slidesPerScreen   1;


let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')

let container = document.getElementById('slider')

buttonLeft.addEventListener('click', function() {
  container.scrollLeft -= 90;
  if (currentSlideCounter > 1) {
    currentSlideCounter -= 1;
  }
  change();
})

buttonRight.addEventListener('click', function() {
  container.scrollLeft  = 90;
  if (currentSlideCounter < maxSlideCounter) {
    currentSlideCounter  = 1;
  }
  change();
})

function change() {
  document.querySelectorAll('.slide_arrow').forEach(el => el.classList.remove('changes'));
  if (currentSlideCounter == 1) {
    document.querySelector('#slide_left').classList.add('changes'); 
  }
  if (currentSlideCounter == maxSlideCounter) {
    document.querySelector('#slide_right').classList.add('changes'); 
  }
}
body {
  background-color: #555;
  height: 100vh;
  display: grid;
  align-items: center;
  justify-content: center; /* justify-items is incorrect, it's justify-content */
  font-family: 'Helvetica';
}

div#slide_wrapper {
  width: 440px;
  display: flex;
  justify-content: space-between;
  height: fit-content;
}

div#slider {
  width: 350px;
  display: flex;
  height: fit-content;
  flex-wrap: nowrap;
  overflow: hidden;
}

div.thumbnail {
  min-width: 80px;
  min-height: 80px;
  cursor: pointer;
  display: grid;
  place-items: center;
  font-size: 30px;
}

div.thumbnail:not(:last-child) {
  margin-right: 10px;
}

div.thumbnail:nth-child(1) {
  background-color: darkturquoise;
}

div.thumbnail:nth-child(2) {
  background-color: goldenrod;
}

div.thumbnail:nth-child(3) {
  background-color: rebeccapurple;
}

div.thumbnail:nth-child(4) {
  background-color: powderblue;
}

div.thumbnail:nth-child(5) {
  background-color: firebrick;
}

div.thumbnail:nth-child(6) {
  background-color: sienna;
}

div.thumbnail:nth-child(7) {
  background-color: bisque;
}

div.thumbnail:nth-child(8) {
  background-color: navy;
}

div#slide_wrapper>button {
  height: fit-content;
  align-self: center;
  font-size: 24px;
  font-weight: 800;
  border: none;
  outline: none;
}

div#slide_wrapper>button:hover {
  cursor: pointer;
}

/* this CSS line applies changes with the JS script */
button.changes {
  visibility: hidden;
}
<div id="slide_wrapper">
  <button id="slide_left" >&#10094;</button>
  <div id="slider">
    <div >1</div>
    <div >2</div>
    <div >3</div>
    <div >4</div> 
    <div >5</div>    
    <div >6</div>
    <div >7</div> 
    <div >8</div>
  </div>
  <button id="slide_right" >&#10095;</button>
</div>

CodePudding user response:

While the above answer works, you might also be able to do this with the scrollWidth property.

Using the steps to determine whether the element is fully scrolled and using the widths instead of heights, you can apply CSS classes to the buttons based on the thresholds you set.

I might update the answer to include a code example when I get home, but I think the docs will help you out a lot.

Update:

As stated, I made a version which disables the buttons according to the scrolling- and clientWidth. The advantage of this is that there is no need to keep track of the amount of thumbnails, and will always work as long as you add same-sized thumbnails to your slide.

Besides changing the JS file, I added .deactivated to your css file, and assigned this class to the left button in the html file.

Hope this helps!

let buttonLeft = document.getElementById("slide_left");
let buttonRight = document.getElementById("slide_right");

let container = document.getElementById("slider");

// Initial calculation of how much their is to scroll, if none, disable
// both buttons since every thumbnail fits in the view.
let scrollingLeft =
  container.scrollWidth - container.clientWidth - container.scrollLeft;

if (scrollingLeft === 0) {
  buttonLeft.classList.add("deactivated");
  buttonRight.classList.add("deactivated");
}

buttonLeft.addEventListener("click", function() {
  container.scrollLeft -= 90;
  if (container.scrollLeft === 0) {
    buttonLeft.classList.add("deactivated");
    buttonRight.classList.remove("deactivated");
  } else {
    buttonLeft.classList.remove("deactivated");
    buttonRight.classList.remove("deactivated");
  }
});

buttonRight.addEventListener("click", function() {
  container.scrollLeft  = 90;
  let scrollingLeft =
    container.scrollWidth - container.clientWidth - container.scrollLeft;
  if (scrollingLeft === 0) {
    buttonRight.classList.add("deactivated");
    buttonLeft.classList.remove("deactivated");
  } else {
    buttonRight.classList.remove("deactivated");
    buttonLeft.classList.remove("deactivated");
  }
});
body {
  background-color: #555;
  height: 100vh;
  display: grid;
  align-items: center;
  justify-items: center;
  font-family: 'Helvetica';
}

div#slide_wrapper {
  width: 440px;
  display: flex;
  justify-content: space-between;
  height: fit-content;
}

div#slider {
  width: 350px;
  display: flex;
  height: fit-content;
  flex-wrap: nowrap;
  overflow: hidden;
}

div.thumbnail {
  min-width: 80px;
  min-height: 80px;
  cursor: pointer;
  display: grid;
  place-items: center;
  font-size: 30px;
}

div.thumbnail:not(:last-child) {
  margin-right: 10px;
}

div.thumbnail:nth-child(1) {
  background-color: darkturquoise;
}

div.thumbnail:nth-child(2) {
  background-color: goldenrod;
}

div.thumbnail:nth-child(3) {
  background-color: rebeccapurple;
}

div.thumbnail:nth-child(4) {
  background-color: powderblue;
}

div.thumbnail:nth-child(5) {
  background-color: firebrick;
}

div.thumbnail:nth-child(6) {
  background-color: sienna;
}

div.thumbnail:nth-child(7) {
  background-color: bisque;
}

div.thumbnail:nth-child(8) {
  background-color: navy;
}

div#slide_wrapper>button {
  height: fit-content;
  align-self: center;
  font-size: 24px;
  font-weight: 800;
  border: none;
  outline: none;
}

div#slide_wrapper>button:hover {
  cursor: pointer;
}

.deactivated {
  background-color: grey;
}
<div id="slide_wrapper">
  <button id="slide_left" >&#10094;</button>
  <div id="slider">
    <div >1</div>
    <div >2</div>
    <div >3</div>
    <div >4</div>
    <div >5</div>
    <div >6</div>
    <div >7</div>
    <div >8</div>
  </div>
  <button id="slide_right" >&#10095;</button>
</div>

  • Related