แถบเลื่อนช่วงที่สอดคล้องกับแบรนด์

ฟีเจอร์บนเว็บ: accent-color <input type="range"> appearance progress() attr() :dir()

ใช้อินพุตช่วงเนทีฟ

ใช้ <input type="range"> ที่ติดป้ายกำกับแทนการสร้างแถบเลื่อนขึ้นมาใหม่ด้วยองค์ประกอบ <div> หรือตัวจัดการเคอร์เซอร์ที่กำหนดเอง การควบคุมแบบเนทีฟจะคงการโต้ตอบด้วยแป้นพิมพ์และเคอร์เซอร์ ลักษณะการทำงานของการสัมผัส และการรองรับการช่วยเหลือพิเศษไว้ กำหนดค่า min, max, step และ value สำหรับกรณีการใช้งาน

<label for="range-slider">Volume</label>
<input type="range" id="range-slider" value="70"/>

หากค่าต้องใช้ป้ายกำกับหรือหน่วยที่จัดรูปแบบ ให้แสดงค่าในเนื้อหา DOM ทั่วไปและอัปเดต aria-valuetext เมื่อมีการเปลี่ยนแปลง อย่าใช้ ::before หรือ ::after ในองค์ประกอบเทียมของแถบเลื่อน เนื่องจากเนื้อหาที่สร้างขึ้นในการควบคุมแบบฟอร์มไม่สามารถทำงานร่วมกันได้ หากจำเป็นต้องใช้เคล็ดลับเครื่องมือที่ติดตามตัวเลื่อน ให้ยึดเคล็ดลับเครื่องมือไว้กับตัวเลื่อนด้วยการกำหนดตำแหน่ง Anchor ของ CSS โปรดดูเคล็ดลับเครื่องมือที่รับรู้ตำแหน่งสำหรับเคล็ดลับเครื่องมือที่ยังคงวางแนวอย่างถูกต้องเมื่อพลิก

เลือกวิธีการจัดรูปแบบ

หากต้องการปรับแต่งสีแบบง่ายๆ ให้ใช้แบบฟอร์มที่สอดคล้องกับแบรนด์และคงการแสดงผลแบบเนทีฟของเบราว์เซอร์ไว้ ดังนี้

input[type="range"] {
  accent-color: var(--brand-color);
}

accent-color ไม่ใช่ API การจัดรูปแบบแถบเลื่อนที่สมบูรณ์ ผลกระทบต่อ Thumb, Track และ Fill จะขึ้นอยู่กับ User Agent ใช้องค์ประกอบจำลองด้านล่างเมื่อต้องควบคุมแทร็ก ตัวเลื่อน ขนาด รูปร่าง หรือการเติม

จัดสไตล์แทร็กและ Thumb

รีเซ็ตการจัดรูปแบบระบบปฏิบัติการเริ่มต้นด้วย appearance: none, margin: 0 และ border: 0 หากต้องการปรับการแสดงผลข้ามเบราว์เซอร์ให้เป็นมาตรฐาน ให้ประกาศองค์ประกอบเทียม WebKit และ Firefox ในบล็อกกฎแยกต่างหาก และจัดกึ่งกลางแถบเลื่อน WebKit โดยใช้ margin-block-start: calc((var(--slider-track-size) - var(--slider-thumb-size)) / 2) (Firefox จะจัดกึ่งกลางแถบเลื่อนโดยอัตโนมัติ) เก็บค่าสำหรับผู้บริโภคเป็นคุณสมบัติที่กำหนดเองในอินพุตเพื่อให้ธีมไม่กำหนดเป้าหมายองค์ประกอบจำลองโดยตรง

input[type="range"] {
  --slider-track-size: 0.5rem;
  --slider-thumb-size: 1.25rem;
  --slider-track-radius: 999px;
  --slider-thumb-radius: 50%;
  --slider-track-color: #d9d9d9;
  --slider-fill-color: #06c;
  --slider-thumb-color: var(--slider-fill-color);
  --slider-direction: to right;

  /* reverse gradient direction for right-to-left layouts */
  &:dir(rtl) {
    --slider-direction: to left;
  }

  /* Read min and max from attributes; --control-value is synced by the script below. */
  --attr-min: attr(min type(<number>), 0);
  --attr-max: attr(max type(<number>), 100);
  --control-value: attr(value type(<number>), 50);
  --slider-progress: calc(
    progress(var(--control-value), var(--attr-min), var(--attr-max)) * 100%
  );

  appearance: none;
  inline-size: 100%;
  block-size: 2.5rem; /* Preserve a generous interaction area. */
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: pointer;
}

/* WebKit/Blink. */
input[type="range"]::-webkit-slider-runnable-track {
  block-size: var(--slider-track-size);
  border: 0;
  border-radius: var(--slider-track-radius);
  background: linear-gradient(
    var(--slider-direction),
    var(--slider-fill-color) var(--slider-progress),
    var(--slider-track-color) var(--slider-progress)
  );
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  inline-size: var(--slider-thumb-size);
  block-size: var(--slider-thumb-size);
  margin-block-start: calc(
    (var(--slider-track-size) - var(--slider-thumb-size)) / 2
  );
  border: 0;
  border-radius: var(--slider-thumb-radius);
  background: var(--slider-thumb-color);
}

/* Firefox. */
input[type="range"]::-moz-range-track {
  block-size: var(--slider-track-size);
  border: 0;
  border-radius: var(--slider-track-radius);
  background: var(--slider-track-color);
}

input[type="range"]::-moz-range-progress {
  block-size: var(--slider-track-size);
  border-radius: var(--slider-track-radius);
  background: var(--slider-fill-color);
}

input[type="range"]::-moz-range-thumb {
  inline-size: var(--slider-thumb-size);
  block-size: var(--slider-thumb-size);
  border: 0;
  border-radius: var(--slider-thumb-radius);
  background: var(--slider-thumb-color);
}

จัดให้มีตัวบ่งชี้โฟกัสของแป้นพิมพ์ที่มองเห็นได้เสมอหลังจากนำลักษณะที่ปรากฏแบบเนทีฟออก อย่าใช้สีเพียงอย่างเดียว

input[type="range"]:focus-visible {
  outline: 2px solid var(--slider-fill-color);
  outline-offset: 4px;
}

จัดรูปแบบการติดตามกิจกรรม

เมื่อส่วนที่เติมของแทร็กมีสไตล์แตกต่างจากแทร็กที่ไม่ได้เติม Firefox จะแสดงผ่าน ::-moz-range-progress WebKit/Blink ไม่มีองค์ประกอบเทียมที่เทียบเท่า ดังนั้นให้ซิงค์ค่าอินพุตแบบเรียลไทม์กับ --control-value ในเหตุการณ์ input ดังนี้

const slider = document.querySelector('#range-slider');

function syncSliderValue() {
  slider.style.setProperty('--control-value', slider.value);
}

syncSliderValue();
slider.addEventListener('input', syncSliderValue);

ข้อจำกัด

  • อย่ารวมตัวเลือกเทียมของ WebKit และ Firefox ไว้ในรายการที่คั่นด้วยคอมมารายการเดียว (เช่น ::-webkit-slider-thumb, ::-moz-range-thumb) เบราว์เซอร์จะทิ้งกฎทั้งหมดหากพบองค์ประกอบเทียมของผู้ให้บริการที่ไม่รู้จัก

สำรอง

การสำรองและการรองรับเบราว์เซอร์สำหรับ accent-color

พร็อพเพอร์ตี้ accent-color เป็นการเพิ่มประสิทธิภาพแบบต่อเนื่อง เบราว์เซอร์ที่ไม่รองรับพร็อพเพอร์ตี้นี้จะละเว้นและใช้สี UI เริ่มต้น

การสำรองและการรองรับเบราว์เซอร์สำหรับ progress() และ attr()

เมื่อไม่รองรับ progress() ให้คำนวณ --slider-progress ด้วย calc():

@supports not (opacity: progress(1, 0, 100)) {
  input[type="range"] {
    --slider-progress: calc(
      (var(--control-value) - var(--attr-min)) /
      (var(--attr-max) - var(--attr-min)) * 100%
    );
  }
}

เมื่อไม่รองรับ attr() ที่พิมพ์ ให้ซิงค์ --attr-min และ --attr-max จากแอตทริบิวต์ min และ max ของอินพุตใน JavaScript ดังนี้

function syncSliderValue() {
  slider.style.setProperty('--attr-min', slider.min || 0);
  slider.style.setProperty('--attr-max', slider.max || 100);
  slider.style.setProperty('--control-value', slider.value);
}