Elastic Slider
Thanh trượt kéo giãn được quá đầu mút, bong bóng giá trị đung đưa rồi bật về như dây cao su
.zip · HTML / CSS / JS · v1.0.0
Miễn phí — không cần tài khoản hay email. Luôn là bản mới nhất.
Đang chạy trực tiếp
Giới thiệu
Thanh trượt sinh ra để nghịch. Nắm con trượt là một bong bóng giá trị bay theo phía trên, đung đưa như con lắc mỗi khi bạn đổi hướng. Cứ kéo tiếp qua đầu thanh ray và thanh ray căng ra, mỏng đi, con trượt bẹp sang hai bên; càng kéo xa càng nặng tay. Thả ra là mọi thứ bật về và rung nhẹ một chút. Thả con trượt gần một vạch chia, nó rơi vào vạch như bị nam châm hút.
- Hợp với cài đặt và bộ lọc: âm lượng, độ sáng, giá, khoảng cách, thu phóng, nhiệt độ
- Một con trượt, hoặc hai con để chọn khoảng mà không bao giờ chồng lên nhau
- Vạch chia, nhãn và lực hút khi bạn cần số tròn; chỉ cần bước nhảy khi không
- Icon ở hai đầu phản ứng theo lực kéo, còn bong bóng thì luôn hiện, hiện khi nắm hoặc tắt hẳn
- Mọi màu sắc, kích thước và khoảng trống cho bong bóng đều là CSS custom property; sáng tối tự theo trang của bạn
- Không cần cài gì: một file CSS và một script nhỏ, hoặc một component React
Tính năng · 9
- Kéo quá hai đầu là con trượt và thanh ray căng ra như dây chun, càng kéo càng nặng tay, thả ra thì bật về và rung nhẹ
- Bong bóng giá trị treo trên con trượt, đung đưa theo tốc độ kéo rồi lắng lại bằng lò xo
- Một con trượt hoặc hai (chọn khoảng), có thể đặt khoảng cách tối thiểu giữa chúng
- Vạch chia và nhãn tuỳ chọn, kèm lực hút nam châm mềm giữ con trượt lại ở từng vạch
- Tiền tố, hậu tố, số chữ số thập phân và dấu phân cách hàng nghìn, hoặc hàm định dạng của riêng bạn
- Icon ở hai đầu nghiêng theo lực kéo, ví dụ loa tắt tiếng khi bạn kéo quá mức 0
- Sự kiện input và change, cùng trường ẩn để gửi giá trị trong form
- Bản HTML/CSS/JS thuần và bản React (dùng được với Next.js, controlled hoặc không)
- Không phụ thuộc thư viện, khoảng 9 KB sau gzip (script và style cộng lại)
Cách dùng
Gắn stylesheet và script một lần, rồi đánh dấu một phần tử rỗng bất kỳ bằng data-elastic-slider.
Thanh trượt tự dựng thanh ray, con trượt và bong bóng bên trong nó. Đặt tên cho nó bằng aria-label
hoặc aria-labelledby:
<link rel="stylesheet" href="elastic-slider.css" />
<script src="elastic-slider.js" defer></script>
<div class="elastic-slider" data-elastic-slider data-elastic-slider-value="40" data-elastic-slider-suffix="%" aria-label="Âm lượng"></div>
<!-- Hai số là một khoảng -->
<div class="elastic-slider" data-elastic-slider data-elastic-slider-max="600" data-elastic-slider-step="10"
data-elastic-slider-value="120 380" data-elastic-slider-prefix="$" aria-label="Giá"></div>
<!-- Icon ở hai đầu: phần tử bất kỳ có data-elastic-icon="start" hoặc "end" -->
<div class="elastic-slider" data-elastic-slider aria-label="Âm lượng">
<span class="elastic-slider__icon" data-elastic-icon="start"><svg viewBox="0 0 24 24">…</svg></span>
<span class="elastic-slider__icon" data-elastic-icon="end"><svg viewBox="0 0 24 24">…</svg></span>
</div>Tuỳ chọn qua data attribute, tất cả bắt đầu bằng data-elastic-slider-:
| Attribute | Mặc định | Tác dụng |
|---|---|---|
min, max, step |
0, 100, 1 |
Thang đo. max là giá trị cuối cùng mà bước nhảy chạm tới (0–10 với bước 3 dừng ở 9) |
value |
ở giữa | Giá trị, hoặc hai số ("20 80") cho một khoảng |
range |
tắt | Hai con trượt kể cả khi value chỉ có một số |
min-gap |
0 |
Khoảng cách tối thiểu giữa hai con trượt, tính theo đơn vị giá trị |
ticks |
0 |
Vạch chia: chia thanh ray thành bấy nhiêu phần bằng nhau |
tick-labels |
tắt | Ghi giá trị dưới mỗi vạch |
snap |
tắt | Lực hút nam châm mềm vào các vạch |
snap-radius |
0.04 |
Mỗi vạch hút xa bao nhiêu, tính theo tỉ lệ của thanh ray |
overdrag |
56 |
Con trượt giãn tối đa bao nhiêu px quá đầu mút; 0 cho thanh trượt thường |
bubble |
active |
active (khi đang nắm hoặc focus), always hoặc off |
prefix, suffix |
không | Ghi quanh con số: $ và % |
decimals |
theo bước | Số chữ số sau dấu thập phân |
grouping, locale |
bật, en-US |
1,200 hay 1200; chữ số và dấu phân cách theo ngôn ngữ |
name |
không | Đặt tên cho trường ẩn gửi giá trị trong <form>; khoảng gửi hai trường, thấp trước |
disabled |
tắt | Làm mờ, rời khỏi thứ tự Tab |
minimum, maximum |
Minimum, Maximum | Tên hai con trượt của khoảng, dành cho trình đọc màn hình |
Thanh trượt phát sự kiện input (mỗi lần giá trị đổi, cả khi đang kéo) và change (khi đã chốt: kéo
xong hoặc bấm phím) trên phần tử của nó. Cả hai đều nổi bọt lên và mang
event.detail = { value, values, index }:
document.querySelector("#volume").addEventListener("input", (event) => {
const { value } = event.detail; // con trượt vừa di chuyển
});ElasticSlider.get(element) trả về handle của thanh trượt đã được nối:
{ value(), values(), setValue(value), update(options), tug(edge), destroy() }. setValue đưa con trượt
tới đó một cách mượt mà và không phát sự kiện (giống gán value cho <input>); tug("start" | "end") giật
con trượt ở đầu đó của thanh ray cho nó giãn ra rồi rung về — gợi ý rằng thanh trượt này co giãn được.
Thanh trượt thêm vào sau khi trang tải: ElasticSlider.init(container) trả về hàm để gỡ ra.
Muốn truyền callback, hàm định dạng hoặc chữ đã dịch, hãy dựng bằng tay:
ElasticSlider.create(element, { min, max, value, format: (n) => ${n} km, onInput, onChange, texts }).
Chép ElasticSlider.tsx, elastic-slider.css và thư mục core vào dự án:
import { useState } from "react";
import { ElasticSlider } from "./ElasticSlider";
export function Filters() {
const [volume, setVolume] = useState(72);
const [price, setPrice] = useState([120, 380]);
return (
<>
<ElasticSlider
aria-label="Âm lượng"
value={volume}
onInput={({ value }) => setVolume(value)}
suffix="%"
bubble="always"
startIcon={<QuietIcon />}
endIcon={<LoudIcon />}
/>
<ElasticSlider aria-label="Giá" min={0} max={600} step={10} value={price} onChange={({ values }) => setPrice(values)} prefix="$" />
</>
);
}Điều khiển bằng value (một số, hoặc hai số cho khoảng) cùng onInput / onChange, hoặc không điều khiển
với defaultValue. Mọi tuỳ chọn ở trên đều là prop (min, max, step, range, minGap, ticks,
tickLabels, snap, snapRadius, overdrag, bubble, prefix, suffix, decimals, grouping,
locale, format, name, disabled, texts), thêm startIcon và endIcon, cùng mọi prop của <div>
(className, aria-*…). Ref cho { value(), values(), setValue(value), tug(edge) }. React 18 hoặc 19.
Component bắt đầu bằng "use client" nên dùng được từ trang hoặc server component bất kỳ. Với App Router
không cần làm gì thêm. Với Pages Router, hãy chuyển dòng import CSS sang pages/_app.
Đặt các biến này trên .elastic-slider (hoặc một class của bạn):
| Property | Đổi gì |
|---|---|
--elastic-track-height, --elastic-thumb-size, --elastic-gap |
Độ dày thanh ray, cỡ con trượt, khoảng cách giữa icon và thanh ray |
--elastic-bubble-room |
Chiều cao chừa trống phía trên thanh ray cho bong bóng |
--elastic-from-color, --elastic-via-color, --elastic-to-color |
Dải màu mặc định của phần đã trượt và chấm trên con trượt |
--elastic-rail, --elastic-fill |
Cả thanh ray và phần đã trượt: background nào cũng được, kể cả gradient |
--elastic-thumb, --elastic-thumb-ring, --elastic-glow |
Con trượt, vầng sáng quanh nó, và ánh sáng dưới con trượt, phần đã trượt và bong bóng |
--elastic-bubble-from, --elastic-bubble-to, --elastic-bubble-text |
Bong bóng |
--elastic-tick, --elastic-tick-lit, --elastic-label, --elastic-label-lit |
Vạch chia và nhãn, ngoài và trong vùng đã chọn |
--elastic-icon, --elastic-ring, --elastic-pop |
Icon ở hai đầu, viền focus, độ nảy khi bong bóng bật ra |
Khi chuyển động, script ghi --elastic-progress (0 đến 1, con trượt đang ở đâu), --elastic-pull-start-amount
và --elastic-pull-end-amount (0 đến 1, mỗi đầu đang bị kéo mạnh cỡ nào) lên thanh trượt: dùng chúng trong CSS
của bạn để icon hay bất cứ thứ gì khác phản ứng theo. Thanh trượt cũng có data-dragging khi đang được nắm và
data-pulling="start | end" khi đang giãn. Màu dùng light-dark(): tự theo color-scheme của trang bạn. Với
prefers-reduced-motion thì không giãn, không đung đưa, không trượt mượt; con trượt chỉ nhảy đến vị trí mới.
Hỏi về sản phẩm này
Chưa chắc có hợp dự án của bạn? Cứ hỏi — câu trả lời lấy từ chính trang này.
Lịch sử phiên bản
1.0.0First releaseMới nhất
Plain HTML/CSS/JS and React builds. Rubber-band overdrag, swinging value bubble, single and range modes, ticks with a magnetic snap, end icons, form fields, keyboard and reduced-motion support.
- Bản sửa lỗi và tính năng mới đều có ngay ở nút tải này — file tải về luôn là bản mới nhất.

