Home > Mobile >  can't define a margin between the cards in my slider
can't define a margin between the cards in my slider

Time:11-04

I'm trying to create a slider but the cards inside it have no spaces at all. I've tried to add margins between them but this doesn't work.

Would you help me to discover where I messed up? Thanks in advance.

const cards = document.querySelectorAll(".card");
const btnLeft = document.querySelector(".slider__btn--left");
const btnRight = document.querySelector(".slider__btn--right");
let currentCard = 0;
const lastCard = cards.length;

const goToCard = function(currCard) {
  cards.forEach(
    (card, index) =>
    (card.style.transform = `translateX(${100 * (index - currCard)}%)`)
  );
};
goToCard(0);

const nextCard = function() {
  if (currentCard === lastCard - 1) currentCard = 0;
  else currentCard  ;
  goToCard(currentCard);
};

const previousCard = function() {
  if (currentCard === 0) currentCard = lastCard - 1;
  else currentCard--;
  goToCard(currentCard);
};

btnLeft.addEventListener("click", previousCard);

btnRight.addEventListener("click", nextCard);
.slider {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.card {
  position: absolute;
  top: 6rem;
  height: 10rem;
  width: 10rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background-color: #634133;
  transition: all 1s;
}

.slider__btn {
  font-size: 3.25rem;
  color: #fff;
  background-color: #634133;
  font-family: sans-serif;
  border: none;
  border-radius: 100%;
  box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.1);
  position: absolute;
  top: 50%;
  z-index: 10;
  height: 5.5rem;
  width: 5.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2 ease;
}

.slider__btn--left {
  left: 15%;
  transform: translate(-50%, 150%);
}

.slider__btn--right {
  right: 15%;
  transform: translate(50%, 140%);
}

.slider__btn:hover {
  background-color: rgba(216, 123, 91, 0.85);
}

.photo__photo {
  height: 23rem;
}

.photo__photo--1 {
  background-color: yellow;
}

.photo__photo--2 {
  background-color: red;
}

.photo__photo--3 {
  background-color: purple;
}

.photo__photo--4 {
  background-color: green;
}

.photo__photo--5 {
  background-color: blue;
}
<div >
  <div >
    <div >&nbsp;</div>
  </div>

  <div >
    <div >&nbsp;</div>

  </div>

  <div >
    <div >&nbsp;</div>
  </div>

  <div >
    <div >&nbsp;</div>
  </div>

  <div >
    <div >&nbsp;</div>
  </div>

  <button >&larr;</button>
  <button >&rarr;</button>
</div>

CodePudding user response:

Since you're positioning your cards manually*, simply add your gap multiplied by the index to each transform value.

const cardGap = 8; 
card.style.transform = `translateX(${100 * (index - currCard)   cardGap * index}%)`

I've also simplified your markup by using :nth-child() instead of individual classes for each slide, just as a suggestion.

const cards = document.querySelectorAll(".card");
const btnLeft = document.querySelector(".slider__btn--left");
const btnRight = document.querySelector(".slider__btn--right");
let currentCard = 0;
const lastCard = cards.length;
const cardGap = 8;

const goToCard = function(currCard) {
  cards.forEach(
    (card, index) =>
    (card.style.transform = `translateX(${100 * (index - currCard)   cardGap * index}%)`)
  );
};
goToCard(0);

const nextCard = function() {
  if (currentCard === lastCard - 1) currentCard = 0;
  else currentCard  ;
  goToCard(currentCard);
};

const previousCard = function() {
  if (currentCard === 0) currentCard = lastCard - 1;
  else currentCard--;
  goToCard(currentCard);
};

btnLeft.addEventListener("click", previousCard);

btnRight.addEventListener("click", nextCard);
.slider {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.card {
  position: absolute;
  top: 6rem;
  height: 10rem;
  width: 10rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background-color: #634133;
  transition: all 1s;
}

.slider__btn {
  font-size: 3.25rem;
  color: #fff;
  background-color: #634133;
  font-family: sans-serif;
  border: none;
  border-radius: 100%;
  box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.1);
  position: absolute;
  top: 50%;
  z-index: 10;
  height: 5.5rem;
  width: 5.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2 ease;
}

.slider__btn--left {
  left: 15%;
  transform: translate(-50%, 150%);
}

.slider__btn--right {
  right: 15%;
  transform: translate(50%, 140%);
}

.slider__btn:hover {
  background-color: rgba(216, 123, 91, 0.85);
}

.card .photo {
  min-height: 1rem;
  background-color: yellow;
}

.card:nth-child(2) .photo {
  background-color: red;
}

.card:nth-child(3) .photo {
  background-color: purple;
}

.card:nth-child(4) .photo {
  background-color: green;
}

.card:nth-child(5) .photo {
  background-color: blue;
}
<div >
  <div >
    <div ></div>
  </div>

  <div >
    <div ></div>
  </div>

  <div >
    <div ></div>
  </div>

  <div >
    <div ></div>
  </div>

  <div >
    <div ></div>
  </div>

  <button >&larr;</button>
  <button >&rarr;</button>
</div>

* Most sliders don't do this. It adds complexity that isn't usually warranted.

CodePudding user response:

A quick solution would be to add border-left: 11px solid white;on your card class. Color can be white or what ever color you background has, and it will make it look like there is a space between them

CodePudding user response:

Instead of setting the justify-content property of your .slider to center.

You can set it to:

justify-content: space-between;

Which while distribute the items evenly inside the .slider with the first item on the start and the last at the the end,

justify-content: space-around;

To distribute the items evenly with a half-size space on both ends,

justify-content: space-evenly;

To distribute the items with equal spaces arount them, or

justify-content: stretch;

Which stretches the item to fit the container.

Justify-content on MDN

CodePudding user response:

This is a bit more than the actual question but the way you where rotating the cards was a bit of the challenge here as it set widths.

Here I simplified the CSS an bit and used the actual size of the element to determine the or - scroll amount, then used the number to rotate when we hit either end. I added a wrapper simply as a base to work from - which works to your advantage if you need to put multiple in place. Note that the scroll no longer depends on the count of cards and you can add more or remove and not change the code as long as it is done before we set the lastCard value or that gets updated. Because I now scroll by the actual card size and the "scroller" may have more than one in view I added a highlight by toggle of a class just for a visual clue. You could bump the scroll when you get the last one in view or the first one if you know the number to decrement or increment at that point but I left that as it should be a simple change if that is desired.

const carousel = document.querySelector(".carousel-container");
const slider = carousel.querySelector(".slider");
const card = carousel.querySelector(".card");
const btnLeft = carousel.querySelector(".slider__btn--left");
const btnRight = carousel.querySelector(".slider__btn--right");
const firstCard = 0;
const lastCard = carousel.querySelectorAll(".card").length - 1;
let currentCard = 0;
card.classList.toggle('who-is-active', true);

function scrollCard(scrollBy) {
  slider.scrollLeft  = (card.clientWidth * scrollBy);
}

function scrollRight(cardNumber) {
  let scrollTo = cardNumber == lastCard ? -1 * lastCard : 1;
  scrollCard(scrollTo);
  return (cardNumber == lastCard) ? 0 : cardNumber   1;
}

function highlightActive(index) {
  carousel.querySelector(".who-is-active").classList.toggle('who-is-active', false);
  carousel.querySelectorAll(".card")[index].classList.toggle('who-is-active', true);
}

function scrollLeft(cardNumber) {
  let scrollTo = cardNumber == firstCard ? lastCard : -1;
  scrollCard(scrollTo);
  return (cardNumber == firstCard) ? lastCard : cardNumber - 1;
}
btnRight.addEventListener('click', function(e) {
  currentCard = scrollRight(currentCard);
  highlightActive(currentCard);
});
btnLeft.addEventListener('click', function(e) {
  currentCard = scrollLeft(currentCard);
  highlightActive(currentCard);
});
body {
  margin: 0;
}

.carousel-container {
  width: 100vw;
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  flex-direction: row;
  justify-content: space-evenly;
  margin: 0;
}

.slider {
  width: 100%;
  height: 10rem;
  display: flex;
  overflow-x: scroll;
  margin: 0;
  padding: 0;
  scrollbar-width: none;
  scroll-behavior: smooth;
  height: 10rem;
  flex-direction: row;
  align-items: center;
  justify-content: start;
  border: solid 1px red;
  background-color: #f0ffff;
}

.slider::-webkit-scrollbar {
  /* no scrollbar on chrome */
  display: none;
}

.card {
  flex-shrink: 0;
  flex-basis: 20%;
  padding: 1rem;
  order: 0;
  height: 10rem;
  width: 10rem;
  display: flex;
  flex-direction: column;
  transition: all 1s;
}

.slider__btn {
  align-self: center;
  font-size: 3.25rem;
  color: #fff;
  background-color: #634133;
  border: none;
  border-radius: 100%;
  cursor: pointer;
  transition: all 0.2 ease;
  z-index: 1;
  padding: 0.2em;
  padding-top: 0;
}

.slider__btn--left {
  order: -1;
}

.slider__btn--right {
  order: 1;
}

.slider__btn:hover {
  background-color: rgba(216, 123, 91, 0.85);
}

.photo {
  display: block;
  height: 100%;
  border: solid 3px pink;
  text-align: center;
  padding-top: 50%;
}

.photo__photo--1 {
  background-color: yellow;
}

.photo__photo--2 {
  background-color: red;
}

.photo__photo--3 {
  background-color: purple;
}

.photo__photo--4 {
  background-color: green;
}

.photo__photo--5 {
  background-color: blue;
}

.who-is-active {
  font-weight: 800;
  font-size: 2em;
  color: cyan;
}
<div >
  <div >
    <div >
      <div >&nbsp;1</div>
    </div>
    <div >
      <div >&nbsp;2</div>
    </div>
    <div >
      <div >&nbsp;3</div>
    </div>
    <div >
      <div >&nbsp;4</div>
    </div>
    <div >
      <div >&nbsp;5</div>
    </div>
    <div >
      <div >&nbsp;6</div>
    </div>
    <div >
      <div >&nbsp;7</div>
    </div>
    <div >
      <div >&nbsp;8</div>
    </div>
    <div >
      <div >&nbsp;9</div>
    </div>
    <div >
      <div >&nbsp;10</div>
    </div>
  </div>
  <button >&larr;</button>
  <button >&rarr;</button>
</div>

  • Related