코딩쌀롱

[HTML¦CSS] multi range slider 본문

개발공부

[HTML¦CSS] multi range slider

이브✱ 2021. 6. 1. 02:06

range slider를 유튜브 따라서 만들어봤다!  코드펜 링크🔗

javascript 코드도 들어가지만 input type="range"때문에 HTML¦CSS 카테고리에 글을 쓴다.

 

먼저 설명하자면,

1. 진짜 슬라이더인 input 2개를 만들고, 가짜 슬라이더 div를 만든다.

2. 진짜 슬라이더를 동작할 때 가짜 슬라이더도 같이 움직이도록 배치를 javascript 코드로 짠다.

3. 진짜 슬라이더를 opacity: 0 으로 투명하게 만들고, 가짜 슬라이더 위에 올린다. 

4. 이 때 진짜 슬라이더는 2개지만 겹쳐놓고, thumb 두 개가 모두 활성화되도록 한다.(pointer-event: all)

✱HTML

<div class="middle">
  <div class="multi-range-slider">
    <!-- 진짜 슬라이더 -->
    <input type="range" id="input-left" min="0" max="100" value="25" />
    <input type="range" id="input-right" min="0" max="100" value="75" />

    <!-- 커스텀 슬라이더 -->
    <div class="slider">
      <div class="track"></div>
      <div class="range"></div>
      <div class="thumb left"></div>
      <div class="thumb right"></div>
    </div>
  </div>
</div>

 

✱CSS

-webkit-, -moz-는 동작 브라우저에 관한 prefix이다.

(webkit은 크롬, 사파리 / moz는 파이어폭스 / ms는 ie)

 

appearance: none을 해줘야 기본 스타일을 숨길 수 있다.

 

opacity 속성을 이용해 요소를 숨기면 가시성은 없지만 해당 영역의 이벤트는 동작하게 된다. 이를 강제로 제어하기 위해 pointer-event 속성을 활용한다.

body {
  margin: 0;
  padding: 0;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #e5e5e5;
}

.middle {
  position: relative;
  width: 50%;
  max-width: 500px;
}

.slider {
  position: relative;
  z-index: 1;
  height: 10px;
  margin: 0 15px;
}

.slider > .track {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  border-radius: 5px;
  background-color: #c6aee7;
}

.slider > .range {
  position: absolute;
  z-index: 2;
  left: 25%;
  right: 25%;
  top: 0;
  bottom: 0;
  border-radius: 5px;
  background-color: #6200ee;
}

.slider > .thumb {
  position: absolute;
  z-index: 3;
  width: 30px;
  height: 30px;
  background-color: #6200ee;
  border-radius: 50%;
}

.slider > .thumb.left {
  left: 25%;
  transform: translate(-15px, -10px);
}
.slider > .thumb.right {
  right: 25%;
  transform: translate(15px, -10px);
}

input[type="range"] {
  position: absolute;
  /* opacity로 가린 것을 이벤트도 비활성화하기 위해 */
  pointer-events: none;
  -webkit-appearance: none;
  z-index: 2;
  height: 10px;
  width: 100%;
  opacity: 0;
}

input[type="range"]::-webkit-slider-thumb {
  /* 겹쳐진 두 thumb를 모두 활성화 */
  pointer-events: all;
  width: 30px;
  height: 30px;
  border-radius: 0;
  border: 0 none;
  background-color: red;
  cursor: pointer;
  /* appearance를 해야 위의 스타일들을 볼 수 있음 */
  -webkit-appearance: none;
}

 

✱JavaScript

const inputLeft = document.getElementById("input-left");
const inputRight = document.getElementById("input-right");

const thumbLeft = document.querySelector(".slider > .thumb.left");
const thumbRight = document.querySelector(".slider > .thumb.right");
const range = document.querySelector(".slider > .range");

const setLeftValue = () => {
  const _this = inputLeft;
  const [min, max] = [parseInt(_this.min), parseInt(_this.max)];
  
  // 교차되지 않게, 1을 빼준 건 완전히 겹치기보다는 어느 정도 간격을 남겨두기 위해.
  _this.value = Math.min(parseInt(_this.value), parseInt(inputRight.value) - 1);
  
  // input, thumb 같이 움직이도록
  const percent = ((_this.value - min) / (max - min)) * 100;
  thumbLeft.style.left = percent + "%";
  range.style.left = percent + "%";
};

const setRightValue = () => {
  const _this = inputRight;
  const [min, max] = [parseInt(_this.min), parseInt(_this.max)];
  
  // 교차되지 않게, 1을 더해준 건 완전히 겹치기보다는 어느 정도 간격을 남겨두기 위해.
  _this.value = Math.max(parseInt(_this.value), parseInt(inputLeft.value) + 1);
  
  // input, thumb 같이 움직이도록
  const percent = ((_this.value - min) / (max - min)) * 100;
  thumbRight.style.right = 100 - percent + "%";
  range.style.right = 100 - percent + "%";
};

inputLeft.addEventListener("input", setLeftValue);
inputRight.addEventListener("input", setRightValue);

 

 


참고📚

유튜브 - Multi Handle Range Slider

블로그 - CSS 이벤트 제어 pointer-events 속성

 

 

'개발공부' 카테고리의 다른 글

[Algorithm] Quick Sort  (0) 2021.06.15
[Web¦Browser] local, session, cache, cookie  (0) 2021.06.07
react와 TypeScript로 canvas 그리기  (0) 2021.05.31
[TS] 타입스크립트 메모2  (0) 2021.05.21
Comments