일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- #솔루션
- 게시판
- 홈페이지제작
- happycgi
- #뉴스
- #cgimall
- jquery
- 해피CGI
- #홈페이지제작
- #웹솔루션
- #쇼핑몰
- #업종별
- #happycgi
- CSS
- #CSS
- 사이트제작
- #jQuery
- 해피씨지아이
- 웹솔루션
- 솔루션
- 쇼핑몰
- 홈페이지
- #해피CGI
- #동영상
- CGIMALL
- #홈페이지
- php
- #이미지
- javascript
- #image
- Today
- Total
웹솔루션개발 22년 노하우! 해피CGI의 모든것
[해피CGI][cgimall] 범위를 표현하는 인풋 슬라이드 Range With Sliding Value 본문
[해피CGI][cgimall] 범위를 표현하는 인풋 슬라이드 Range With Sliding Value
해피CGI윤실장 2023. 11. 6. 09:44
해당 인풋은 사용자에게 더욱 직관적인 인터페이스를 제공해 줄 수 있습니다.
슬라이드를 이동할 때마다 범위가 나타납니다.
웹페이지를 좀 더 역동적이고 매력적으로 만들 수 있습니다.
HTML 구조
<form class="range" action="">
<label class="range__label" for="dummy">Range</label>
<input class="range__input" id="dummy" type="range" value="25" min="0" max="50" step="1">
<div class="range__output" aria-hidden="true" data-tip>
<div class="range__output-value-track">
<div class="range__output-values" data-values></div>
</div>
</div>
</form>
CSS 소스
* {
border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--hue: 223;
--white: hsl(0,0%,100%);
--lt-gray: hsl(var(--hue),10%,95%);
--primary0: hsl(var(--hue),90%,95%);
--primary1: hsl(var(--hue),90%,90%);
--primary3: hsl(var(--hue),90%,50%);
--primary4: hsl(var(--hue),90%,30%);
--primary5: hsl(var(--hue),90%,10%);
--trans-dur: 0.3s;
font-size: calc(16px + (32 - 16) * (100vw - 320px) / (1280 - 320));
}
body,
input {
font: 1em/1.5 "DM Sans", sans-serif;
}
body {
background-color: var(--primary0);
color: var(--primary5);
height: 100vh;
display: grid;
place-items: center;
transition:
background-color var(--trans-dur),
color var(--trans-dur);
}
/* Main styles */
.range {
margin: 2.5em 0.75em 0 0.75em;
padding-top: 0.5em;
position: relative;
max-width: 12em;
width: 100%;
}
.range__label {
overflow: hidden;
position: absolute;
width: 1px;
height: 1px;
}
.range__input {
--percent: 50%;
background-color: var(--primary1);
background-image: linear-gradient(var(--primary3),var(--primary3));
background-size: var(--percent) 100%;
background-repeat: no-repeat;
border-radius: 0.25em;
display: block;
margin: 0.5em -0.75em;
width: calc(100% + 1.5em);
height: 0.5em;
transition: background-color var(--trans-dur);
-webkit-appearance: none;
appearance: none;
-webkit-tap-highlight-color: transparent;
}
.range__input:focus {
outline: transparent;
}
/* WebKit */
.range__input::-webkit-slider-thumb {
background-color: var(--white);
border: 0;
border-radius: 50%;
box-shadow: 0 0.125em 0.5em hsl(0,0%,0%,0.3);
width: 1.5em;
height: 1.5em;
transition: background-color 0.15s linear;
-webkit-appearance: none;
appearance: none;
}
.range__input:focus::-webkit-slider-thumb,
.range__input::-webkit-slider-thumb:hover {
background-color: var(--lt-gray);
}
/* Firefox */
.range__input::-moz-range-thumb {
background-color: var(--white);
border: 0;
border-radius: 50%;
box-shadow: 0 0.125em 0.5em hsl(0,0%,0%,0.3);
width: 1.5em;
height: 1.5em;
transition: background-color 0.15s linear;
}
.range__input:focus::-moz-range-thumb,
.range__input::-moz-range-thumb:hover {
background-color: var(--lt-gray);
}
/* Continue main styles */
.range__output,
.range__output:after,
.range__output-value-track,
.range__output-values {
position: absolute;
}
.range__output,
.range__output:after {
transform: translateX(-50%);
}
.range__output {
--percent: 50%;
background-color: var(--primary3);
border-radius: 0.25em;
color: var(--white);
padding: 0.25em;
bottom: calc(100% + 0.5em);
left: var(--percent);
text-align: center;
width: 2em;
height: 2em;
transition: background-color var(--trans-dur);
}
.range__output:after {
border-top: 0.5em solid var(--primary3);
border-left: 0.5em solid transparent;
border-right: 0.5em solid transparent;
content: "";
display: block;
top: calc(100% - 1px);
left: 50%;
width: 0;
height: 0;
}
.range__output-value-track {
inset: 0;
overflow: hidden;
}
.range__output-values {
--transX: 0;
display: flex;
align-items: center;
white-space: nowrap;
top: 0;
left: 0;
height: 100%;
transform: translateX(var(--transX));
transition: transform 0.15s linear;
}
.range__output-value {
width: 2em;
}
/* `:focus-visible` support */
@supports selector(:focus-visible) {
.range__input:focus::-webkit-slider-thumb {
background-color: var(--white);
}
.range__input:focus-visible::-webkit-slider-thumb,
.range__input::-webkit-slider-thumb:hover {
background-color: var(--lt-gray);
}
.range__input:focus::-moz-range-thumb {
background-color: var(--white);
}
.range__input:focus-visible::-moz-range-thumb,
.range__input::-moz-range-thumb:hover {
background-color: var(--lt-gray);
}
}
/* Dark theme */
@media (prefers-color-scheme: dark) {
body {
background-color: var(--primary5);
color: var(--primary1);
}
.range__input {
background-color: var(--primary4);
}
}
JS 소스
window.addEventListener("DOMContentLoaded",() => {
const fr = new RangeSlidingValue("dummy");
});
class RangeSlidingValue {
constructor(id) {
this.input = document.getElementById(id);
this.output = document.querySelector('[data-tip]');
this.values = this.output?.querySelector("[data-values]");
this.init();
}
init() {
this.input?.addEventListener("input",this.update.bind(this));
this.populateValues();
this.update();
}
populateValues() {
const digitSpan = document.createElement("span");
digitSpan.className = "range__output-value";
const { min, max } = this.input;
for (let v = min; v <= max; ++v) {
const newSpan = digitSpan.cloneNode();
newSpan.innerText = v;
this.values?.appendChild(newSpan);
}
}
update(e) {
let value = this.input.defaultValue;
// when manually set
if (e) value = e.target?.value;
// when initiated
else this.input.value = value;
const min = this.input.min || 0;
const max = this.input.max || 100;
const possibleValues = max - min;
const relativeValue = (value - min) / possibleValues;
const percentRaw = relativeValue * 100;
const percent = +percentRaw.toFixed(2);
const tipWidth = 2;
const transXRaw = -tipWidth * relativeValue * possibleValues;
const transX = +transXRaw.toFixed(2);
const prop1 = "--percent";
const prop2 = "--transX";
this.input?.style.setProperty(prop1,`${percent}%`);
this.output?.style.setProperty(prop1,`${percent}%`);
this.values?.style.setProperty(prop2,`${transX}em`);
}
}
'웹프로그램밍 자료실 > HTML 자료' 카테고리의 다른 글
[해피CGI][cgimall] CSS로 아이프레임 높이 자동 조절 (0) | 2023.11.16 |
---|---|
[해피CGI][cgimall] Text animation (0) | 2023.11.16 |
[해피CGI][cgimall] CSS 카드 오버 효과 애니메이션 (0) | 2023.11.03 |
[해피CGI][cgimall] Multi Range input, CSS-only 다중 범위 선택 인풋 디자인 (0) | 2023.10.25 |
[해피CGI][cgimall] Modern Button Styles - 45 CSS Only Buttons 버튼 디자인 (0) | 2023.09.20 |