$ticks-height: 5px; $ticks-thickness: 1px; $max-ticks-allowed: 30; $thumb-size: 20px; $track-height: #{calc($thumb-size / 2)}; .slider { // Define css variables --ticks-count: calc(var(--max) - var(--min)) / var(--step); --too-many-ticks: min(1, Max(var(--ticks-count) - #{$max-ticks-allowed}, 0)); --x-step: max(var(--step), var(--too-many-ticks) * (var(--max) - var(--min))); // Define properties position: relative; // Draw the steps background: linear-gradient(to right, var(--text-muted-color) $ticks-thickness, transparent 1px) repeat-x; background-size: calc((100% - #{$thumb-size}) / ((var(--max) - var(--min)) / var(--x-step))) #{$ticks-height}; background-position-x: #{calc($track-height - $ticks-thickness / 2)}; background-position-y: bottom; font-weight: 700; color: var(--text-muted-color); font-size: 0.8125rem; height: 22px; margin-top: 2.5ch; margin-bottom: 2.5ch; // mix/max texts &::before, &::after { content: counter(x); position: absolute; bottom: calc(-2.5ch - 2px); top: calc(2.5ch + 2px); opacity: .5; transform: translateX(calc(50% * var(--before, -1) * -1)); pointer-events: none; } &::before { --before: 1; counter-reset: x var(--min); left: #{$track-height}; } &::after { counter-reset: x var(--max); right: #{$track-height}; } } .outputContainer { position: absolute; top: 0; left: #{$track-height}; right: #{$track-height}; height: #{$track-height}; pointer-events: none; } .output { pointer-events: none; position: absolute; z-index: 5; width: #{$thumb-size}; height: #{$thumb-size}; left: calc((((var(--value) - var(--min)) / (var(--max) - var(--min))) * 100%) - #{calc($thumb-size / 2)}); bottom: #{calc($thumb-size / 2 + 6px)}; text-align: center; } .progress { --completed-a: calc((clamp(var(--min), var(--value, 0), var(--max)) - var(--min)) / (var(--max) - var(--min)) * 100); --completed-b: calc((var(--value) - var(--min)) / (var(--max) - var(--min)) * 100); --cb: max(var(--completed-a), var(--completed-b)); --start-end: #{$track-height}; --clip-end: calc(100% - (var(--cb)) * 1%); --clip: inset(-20px var(--clip-end) -20px 0); position: absolute; width: 100%; height: #{$track-height}; background: var(--text-color); border-radius: #{$track-height}; z-index: -1; // fill area &::before { content: ""; position: absolute; left: 0; right: 0; clip-path: var(--clip); top: 0; bottom: 0; background: var(--text-secondary); z-index: 1; border-radius: inherit; } } .input { --thumb-shadow: 0 0 3px rgba(0, 0, 0, 0.4), 0 0 1px rgba(0, 0, 0, 0.5) inset, 0 0 0 99px var(--text-color) inset; -webkit-appearance: none; width: 100%; height: #{$thumb-size}; margin: 0; position: absolute; left: 0; cursor: grab; outline: none; background: none; @mixin thumb { appearance: none; height: #{$thumb-size}; width: #{$thumb-size}; transform: translateY(-5px); border-radius: 50%; background: var(--text-color); box-shadow: var(--thumb-shadow); border: none; pointer-events: auto; } &::-webkit-slider-thumb { @include thumb; } &::-moz-range-thumb { @include thumb; } &::-ms-thumb { @include thumb; } &:active { --thumb-shadow: 0 0 0 #{calc($thumb-size / 4)} inset var(--text-color), 0 0 0 99px var(--text-secondary) inset, 0 0 3px rgba(0, 0, 0, 0.4); cursor: grabbing; } }