การสร้างคอมโพเนนต์ของแถบการโหลด

ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างแถบการโหลดที่ปรับสีได้และเข้าถึงได้ด้วยองค์ประกอบ <progress>

ในโพสต์นี้ ฉันต้องการแชร์แนวคิดเกี่ยวกับวิธีสร้างแถบการโหลดที่ปรับสีได้และเข้าถึงได้ด้วยองค์ประกอบ <progress> ลองใช้เวอร์ชันเดโมและดูแหล่งที่มา

การสาธิตแถบความคืบหน้าแบบสว่างและมืด แบบไม่แน่นอน แบบเพิ่มขึ้น และแบบเสร็จสมบูรณ์ใน Chrome

หากคุณชอบดูวิดีโอมากกว่า เรามีโพสต์นี้ในเวอร์ชัน YouTube ด้วย

ภาพรวม

องค์ประกอบ <progress> จะแสดงภาพและเสียงตอบกลับแก่ผู้ใช้เกี่ยวกับการดำเนินการเสร็จสมบูรณ์ การตอบสนองด้วยภาพนี้มีประโยชน์ในสถานการณ์ต่างๆ เช่น ความคืบหน้าในการกรอกแบบฟอร์ม การแสดงข้อมูลการดาวน์โหลดหรือการอัปโหลด หรือแม้แต่การแสดงว่าไม่ทราบปริมาณความคืบหน้าแต่ยังคงทำงานอยู่

ความท้าทายด้าน GUI นี้ทำงานร่วมกับองค์ประกอบ HTML <progress> ที่มีอยู่เพื่อประหยัดเวลาในการช่วยเหลือพิเศษ สีและเลย์เอาต์จะขยายขีดจำกัดของการปรับแต่งสำหรับองค์ประกอบในตัว เพื่อปรับปรุงคอมโพเนนต์ให้ทันสมัยและเข้ากับระบบการออกแบบได้ดียิ่งขึ้น

แท็บสว่างและมืดในแต่ละเบราว์เซอร์ที่แสดงภาพรวมของไอคอนแบบปรับอัตโนมัติจากบนลงล่าง ได้แก่ Safari, Firefox, Chrome
เดโมที่แสดงใน Firefox, Safari, iOS Safari, Chrome และ Android Chrome ในรูปแบบสว่างและมืด

Markup

ฉันเลือกที่จะรวมองค์ประกอบ <progress> ไว้ใน <label> เพื่อให้สามารถข้ามแอตทริบิวต์ความสัมพันธ์ที่ชัดเจนเพื่อสนับสนุนความสัมพันธ์โดยนัย นอกจากนี้ ฉันยังติดป้ายกำกับองค์ประกอบหลักที่ได้รับผลกระทบจากสถานะการโหลด เพื่อให้เทคโนโลยีโปรแกรมอ่านหน้าจอสามารถส่งต่อข้อมูลนั้นกลับไปยังผู้ใช้ได้

<progress></progress>

หากไม่มี value ความคืบหน้าขององค์ประกอบจะไม่แน่นอน แอตทริบิวต์ max มีค่าเริ่มต้นเป็น 1 ดังนั้นความคืบหน้าจึงอยู่ระหว่าง 0 ถึง 1 เช่น การตั้งค่า max เป็น 100 จะกำหนดช่วงเป็น 0-100 ฉันเลือกที่จะอยู่ภายในขีดจำกัด 0 และ 1 โดยแปลค่าความคืบหน้าเป็น 0.5 หรือ 50%

ความคืบหน้าของป้ายกำกับที่ตัดข้อความขึ้นบรรทัดใหม่

ในความสัมพันธ์โดยนัย องค์ประกอบความคืบหน้าจะรวมอยู่ในป้ายกำกับ ดังนี้

<label>Loading progress<progress></progress></label>

ในการสาธิตนี้ ฉันเลือกที่จะใส่ป้ายกำกับสำหรับโปรแกรมอ่านหน้าจอเท่านั้น ซึ่งทำได้โดยการรวมข้อความป้ายกำกับไว้ใน <span> และใช้รูปแบบบางอย่างกับข้อความดังกล่าวเพื่อให้ข้อความอยู่นอกหน้าจออย่างมีประสิทธิภาพ

<label>
  <span class="sr-only">Loading progress</span>
  <progress></progress>
</label>

โดยมี CSS ต่อไปนี้จาก WebAIM ประกอบด้วย

.sr-only {
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

ภาพหน้าจอของเครื่องมือสำหรับนักพัฒนาเว็บที่แสดงองค์ประกอบ screen-ready-only

พื้นที่ที่ได้รับผลกระทบจากความคืบหน้าในการโหลด

หากคุณมีสายตาปกติ คุณอาจเชื่อมโยงสัญญาณบอกสถานะความคืบหน้ากับองค์ประกอบและพื้นที่หน้าเว็บที่เกี่ยวข้องได้ง่าย แต่สำหรับผู้ใช้ที่มีความบกพร่องทางสายตา สิ่งนี้อาจไม่ชัดเจนนัก ปรับปรุงปัญหานี้โดยกำหนดแอตทริบิวต์ aria-busy ให้กับองค์ประกอบบนสุดที่จะเปลี่ยนแปลงเมื่อโหลดเสร็จสมบูรณ์ นอกจากนี้ ให้ระบุความสัมพันธ์ระหว่างความคืบหน้าและโซนการโหลดด้วย aria-describedby

<main id="loading-zone" aria-busy="true">
  …
  <progress aria-describedby="loading-zone"></progress>
</main>

จาก JavaScript ให้สลับ aria-busy เป็น true เมื่อเริ่มงาน และสลับเป็น false เมื่อเสร็จสิ้น

การเพิ่มแอตทริบิวต์ Aria

แม้ว่าบทบาทโดยนัยขององค์ประกอบ <progress> คือ progressbar แต่ฉันได้ระบุไว้อย่างชัดเจนสำหรับเบราว์เซอร์ที่ไม่มีบทบาทโดยนัยดังกล่าว ฉันยังได้เพิ่มแอตทริบิวต์ indeterminate เพื่อกำหนดองค์ประกอบให้อยู่ในสถานะไม่รู้จักอย่างชัดเจน ซึ่งชัดเจนกว่าการสังเกตว่าองค์ประกอบไม่มีการตั้งค่า value

<label>
  Loading 
  <progress 
    indeterminate 
    role="progressbar" 
    aria-describedby="loading-zone"
    tabindex="-1"
  >unknown</progress>
</label>

ใช้ tabindex="-1" เพื่อทำให้องค์ประกอบความคืบหน้าโฟกัสได้จาก JavaScript ซึ่งสำคัญสำหรับเทคโนโลยีโปรแกรมอ่านหน้าจอ เนื่องจากการให้ความสำคัญกับความคืบหน้าเมื่อความคืบหน้าเปลี่ยนแปลงจะประกาศให้ผู้ใช้ทราบว่าความคืบหน้าที่อัปเดตไปถึงจุดใดแล้ว

รูปแบบ

องค์ประกอบความคืบหน้าอาจยุ่งยากเล็กน้อยเมื่อพูดถึงการจัดรูปแบบ องค์ประกอบ HTML ในตัวมีส่วนที่ซ่อนอยู่เป็นพิเศษซึ่งอาจเลือกได้ยาก และมักจะมีชุดพร็อพเพอร์ตี้ที่จำกัดให้ตั้งค่าเท่านั้น

เลย์เอาต์

รูปแบบเลย์เอาต์มีไว้เพื่อให้มีความยืดหยุ่นในขนาดขององค์ประกอบความคืบหน้าและตำแหน่งป้ายกำกับ ระบบจะเพิ่มสถานะการดำเนินการเสร็จสมบูรณ์แบบพิเศษ ซึ่งอาจเป็นภาพบอกใบ้เพิ่มเติมที่มีประโยชน์ แต่ไม่จำเป็น

เลย์เอาต์ <progress>

ความกว้างขององค์ประกอบความคืบหน้าจะไม่มีการเปลี่ยนแปลงเพื่อให้ย่อและขยายได้ตามพื้นที่ที่จำเป็นในการออกแบบ ระบบจะตัดสไตล์ในตัวออกโดยตั้งค่า appearance และ border เป็น none ซึ่งทำเพื่อให้องค์ประกอบสามารถปรับให้เป็นมาตรฐานในเบราว์เซอร์ต่างๆ ได้ เนื่องจากแต่ละเบราว์เซอร์มีสไตล์ของตนเองสำหรับองค์ประกอบ

progress {
  --_track-size: min(10px, 1ex);
  --_radius: 1e3px;

  /*  reset  */
  appearance: none;
  border: none;

  position: relative;
  height: var(--_track-size);
  border-radius: var(--_radius);
  overflow: hidden;
}

ค่า 1e3px สำหรับ _radius ใช้สัญกรณ์วิทยาศาสตร์เพื่อแสดงจำนวนมาก ดังนั้น border-radius จึงปัดเศษเสมอ ซึ่งเทียบเท่ากับ 1000px ฉันชอบใช้ค่านี้เพราะเป้าหมายของฉันคือการใช้ค่าที่มากพอที่จะตั้งค่าแล้วลืมไปได้เลย (และเขียนสั้นกว่า 1000px) นอกจากนี้ยังทำให้ค่ามีขนาดใหญ่ขึ้นได้ง่ายหากจำเป็น เพียงเปลี่ยน 3 เป็น 4 จากนั้น 1e4px จะเทียบเท่ากับ 10000px

มีการใช้ overflow: hidden และเป็นสไตล์ที่ก่อให้เกิดข้อโต้แย้ง ซึ่งช่วยให้ทำสิ่งต่างๆ ได้ง่ายขึ้น เช่น ไม่จำเป็นต้องส่งค่า border-radius ไปยังแทร็กและองค์ประกอบการเติมแทร็ก แต่ก็หมายความว่าองค์ประกอบย่อยของความคืบหน้าจะอยู่นอกองค์ประกอบไม่ได้ การทำซ้ำอีกครั้งในองค์ประกอบความคืบหน้าที่กำหนดเองนี้สามารถทำได้โดยไม่ต้องใช้ overflow: hidden และอาจเปิดโอกาสให้มีภาพเคลื่อนไหวหรือสถานะการเสร็จสมบูรณ์ที่ดีขึ้น

ความคืบหน้าเสร็จสมบูรณ์

ตัวเลือก CSS จะทำงานที่ยากในส่วนนี้โดยการเปรียบเทียบค่าสูงสุดกับค่า และหากตรงกัน ความคืบหน้าจะเสร็จสมบูรณ์ เมื่อเสร็จสมบูรณ์ ระบบจะสร้างองค์ประกอบจำลองและต่อท้ายองค์ประกอบความคืบหน้า ซึ่งจะช่วยให้เห็นภาพเพิ่มเติมที่ชัดเจนว่าเสร็จสมบูรณ์แล้ว

progress:not([max])[value="1"]::before,
progress[max="100"][value="100"]::before {
  content: "✓";
  
  position: absolute;
  inset-block: 0;
  inset-inline: auto 0;
  display: flex;
  align-items: center;
  padding-inline-end: max(calc(var(--_track-size) / 4), 3px);

  color: white;
  font-size: calc(var(--_track-size) / 1.25);
}

ภาพหน้าจอของแถบการโหลดที่ 100% และแสดงเครื่องหมายถูกที่ส่วนท้าย

สี

เบราว์เซอร์จะใช้สีของตัวเองสำหรับองค์ประกอบความคืบหน้า และปรับให้เข้ากับโหมดสว่างและมืดได้ด้วยพร็อพเพอร์ตี้ CSS เพียงรายการเดียว ซึ่งสามารถสร้างขึ้นได้ด้วยตัวเลือกเฉพาะเบราว์เซอร์บางตัว

รูปแบบเบราว์เซอร์สว่างและมืด

หากต้องการเลือกใช้เว็บไซต์ในองค์ประกอบ <progress> ที่ปรับเปลี่ยนตามธีมมืดและสว่าง คุณต้องใช้ color-scheme เท่านั้น

progress {
  color-scheme: light dark;
}

สีเติมความคืบหน้าของที่พักเดี่ยว

หากต้องการปรับสีองค์ประกอบ <progress> ให้ใช้ accent-color

progress {
  accent-color: rebeccapurple;
}

สังเกตว่าสีพื้นหลังของแทร็กเปลี่ยนจากสว่างเป็นมืดตามaccent-color เบราว์เซอร์จะตรวจสอบว่าคอนทราสต์เหมาะสม ซึ่งถือว่าดีมาก

สีอ่อนและสีเข้มที่กำหนดเองทั้งหมด

ตั้งค่าคุณสมบัติที่กำหนดเอง 2 รายการในองค์ประกอบ <progress> โดยรายการหนึ่งสำหรับสีของแทร็กและอีกรายการหนึ่งสำหรับสีความคืบหน้าของแทร็ก ภายในคิวรี่สื่อ prefers-color-scheme ให้ระบุค่าสีใหม่สำหรับแทร็กและความคืบหน้าของแทร็ก

progress {
  --_track: hsl(228 100% 90%);
  --_progress: hsl(228 100% 50%);
}

@media (prefers-color-scheme: dark) {
  progress {
    --_track: hsl(228 20% 30%);
    --_progress: hsl(228 100% 75%);
  }
}

รูปแบบโฟกัส

ก่อนหน้านี้เราได้กำหนดดัชนีแท็บเชิงลบให้กับองค์ประกอบเพื่อให้โฟกัสแบบเป็นโปรแกรมได้ ใช้ :focus-visible เพื่อปรับแต่งโฟกัสเพื่อเลือกใช้รูปแบบกรอบโฟกัสที่ชาญฉลาดยิ่งขึ้น เมื่อใช้ตัวเลือกนี้ การคลิกเมาส์และการโฟกัสจะไม่แสดงวงแหวนโฟกัส แต่การคลิกแป้นพิมพ์จะแสดง วิดีโอ YouTube นี้จะอธิบายเรื่องนี้อย่างละเอียดและควรค่าแก่การดู

progress:focus-visible {
  outline-color: var(--_progress);
  outline-offset: 5px;
}

ภาพหน้าจอของแถบการโหลดที่มีวงแหวนโฟกัสอยู่รอบๆ สีทั้งหมดตรงกัน

รูปแบบที่กำหนดเองในเบราว์เซอร์ต่างๆ

ปรับแต่งสไตล์โดยเลือกส่วนต่างๆ ขององค์ประกอบ <progress> ที่แต่ละเบราว์เซอร์แสดง การใช้องค์ประกอบความคืบหน้าเป็นแท็กเดียว แต่ประกอบด้วยองค์ประกอบย่อย 2-3 รายการที่แสดงผ่านตัวเลือกเทียม CSS เครื่องมือสำหรับนักพัฒนาเว็บใน Chrome จะแสดงองค์ประกอบเหล่านี้ให้คุณเห็นหากเปิดใช้การตั้งค่าต่อไปนี้

  1. คลิกขวาที่หน้าเว็บ แล้วเลือกตรวจสอบองค์ประกอบเพื่อเปิดเครื่องมือสำหรับนักพัฒนาเว็บ
  2. คลิกไอคอนรูปเฟืองการตั้งค่าที่มุมขวาบนของหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บ
  3. ในส่วนหัวองค์ประกอบ ให้ค้นหาและเลือกช่องทำเครื่องหมายแสดง DOM เงาของ User Agent

ภาพหน้าจอของตำแหน่งในเครื่องมือสำหรับนักพัฒนาเว็บเพื่อเปิดใช้การแสดง Shadow DOM ของ User Agent

รูปแบบ Safari และ Chromium

เบราว์เซอร์ที่ใช้ WebKit เช่น Safari และ Chromium จะแสดง ::-webkit-progress-bar และ ::-webkit-progress-value ซึ่งอนุญาตให้ใช้ CSS ชุดย่อยได้ ตอนนี้ ให้ตั้งค่า background-color โดยใช้คุณสมบัติที่กำหนดเองซึ่งสร้างไว้ก่อนหน้านี้ ซึ่งจะปรับให้เข้ากับโหมดสว่างและมืด

/*  Safari/Chromium  */
progress[value]::-webkit-progress-bar {
  background-color: var(--_track);
}

progress[value]::-webkit-progress-value {
  background-color: var(--_progress);
}

ภาพหน้าจอแสดงองค์ประกอบภายในขององค์ประกอบความคืบหน้า

สไตล์ Firefox

Firefox จะแสดงเฉพาะตัวเลือกเทียม ::-moz-progress-bar ในองค์ประกอบ <progress> เท่านั้น ซึ่งหมายความว่าเราไม่สามารถปรับสีแทร็กได้โดยตรง

/*  Firefox  */
progress[value]::-moz-progress-bar {
  background-color: var(--_progress);
}

ภาพหน้าจอของ Firefox และตำแหน่งที่จะค้นหาองค์ประกอบความคืบหน้า

ภาพหน้าจอของ Debugging Corner ที่ Safari, iOS Safari, Firefox, Chrome และ Chrome บน Android ต่างก็มีแถบการโหลดที่แสดงการทำงานอยู่

โปรดทราบว่า Firefox มีสีแทร็กที่ตั้งค่าจาก accent-color ขณะที่ iOS Safari มีแทร็กสีฟ้าอ่อน ในโหมดมืดก็เช่นกัน Firefox มีแทร็กสีเข้ม แต่ไม่ใช่สีแบบกำหนดเองที่เราตั้งค่าไว้ และใช้งานได้ในเบราว์เซอร์ที่ใช้ Webkit

แอนิเมชัน

แม้ว่าการทำงานกับตัวเลือกเทียมในตัวของเบราว์เซอร์มักจะมีพร็อพเพอร์ตี้ CSS ที่อนุญาตจำนวนจำกัด

ภาพเคลื่อนไหวของแทร็กที่ค่อยๆ เต็ม

การเพิ่มการเปลี่ยนไปยัง inline-size ขององค์ประกอบความคืบหน้าใช้ได้กับ Chromium แต่ใช้กับ Safari ไม่ได้ นอกจากนี้ Firefox ยังไม่ใช้พร็อพเพอร์ตี้การเปลี่ยนผ่านใน ::-moz-progress-bar ด้วย

/*  Chromium Only 😢  */
progress[value]::-webkit-progress-value {
  background-color: var(--_progress);
  transition: inline-size .25s ease-out;
}

กำลังสร้างภาพเคลื่อนไหวของสถานะ:indeterminate

ในขั้นตอนนี้ ฉันจะใช้ความคิดสร้างสรรค์มากขึ้นเพื่อสร้างภาพเคลื่อนไหว ระบบจะสร้างองค์ประกอบจำลองสำหรับ Chromium และใช้การไล่ระดับสีที่เคลื่อนไหวไปมาสำหรับเบราว์เซอร์ทั้ง 3 รายการ

คุณสมบัติที่กำหนดเอง

คุณสมบัติที่กำหนดเองเหมาะสำหรับหลายๆ อย่าง แต่หนึ่งในสิ่งที่ฉันชอบที่สุดคือการตั้งชื่อให้กับค่า CSS ที่ดูน่าอัศจรรย์ ต่อไปนี้เป็นlinear-gradientที่ค่อนข้างซับซ้อน แต่มีชื่อที่น่าสนใจ ผู้ใช้สามารถเข้าใจวัตถุประสงค์และกรณีการใช้งานได้อย่างชัดเจน

progress {
  --_indeterminate-track: linear-gradient(to right,
    var(--_track) 45%,
    var(--_progress) 0%,
    var(--_progress) 55%,
    var(--_track) 0%
  );
  --_indeterminate-track-size: 225% 100%;
  --_indeterminate-track-animation: progress-loading 2s infinite ease;
}

พร็อพเพอร์ตี้ที่กำหนดเองยังช่วยให้โค้ดเป็นไปตามหลักการ DRY ด้วย เนื่องจากเราไม่สามารถจัดกลุ่มตัวเลือกเฉพาะเบราว์เซอร์เหล่านี้เข้าด้วยกันได้

คีย์เฟรม

เป้าหมายคือการสร้างภาพเคลื่อนไหวแบบวนซ้ำที่เคลื่อนไหวไปมา คีย์เฟรมเริ่มต้นและสิ้นสุดจะตั้งค่าใน CSS คุณต้องใช้คีย์เฟรมเพียงรายการเดียว ซึ่งก็คือคีย์เฟรมตรงกลางที่ 50% เพื่อสร้างภาพเคลื่อนไหวที่กลับไปยังจุดเริ่มต้นซ้ำแล้วซ้ำอีก

@keyframes progress-loading {
  50% {
    background-position: left; 
  }
}

การกำหนดเป้าหมายแต่ละเบราว์เซอร์

เบราว์เซอร์บางรายการไม่อนุญาตให้สร้างองค์ประกอบจำลองในองค์ประกอบ <progress> เองหรือไม่อนุญาตให้ทำให้แถบความคืบหน้าเคลื่อนไหว เบราว์เซอร์จำนวนมากขึ้นรองรับการเคลื่อนไหวของแทร็กมากกว่าองค์ประกอบจำลอง ดังนั้นฉันจึงอัปเกรดจากองค์ประกอบจำลองเป็นฐานและเป็นแถบเคลื่อนไหว

องค์ประกอบเทียมของ Chromium

Chromium อนุญาตให้ใช้องค์ประกอบจำลอง ::after กับตำแหน่งเพื่อครอบคลุมองค์ประกอบ ระบบจะใช้คุณสมบัติที่กำหนดเองแบบไม่แน่นอน และภาพเคลื่อนไหวไปมาจะทำงานได้ดีมาก

progress:indeterminate::after {
  content: "";
  inset: 0;
  position: absolute;
  background: var(--_indeterminate-track);
  background-size: var(--_indeterminate-track-size);
  background-position: right; 
  animation: var(--_indeterminate-track-animation);
}
แถบความคืบหน้าของ Safari

สำหรับ Safari ระบบจะใช้คุณสมบัติที่กำหนดเองและภาพเคลื่อนไหวกับแถบความคืบหน้าขององค์ประกอบจำลอง ดังนี้

progress:indeterminate::-webkit-progress-bar {
  background: var(--_indeterminate-track);
  background-size: var(--_indeterminate-track-size);
  background-position: right; 
  animation: var(--_indeterminate-track-animation);
}
แถบความคืบหน้าของ Firefox

สำหรับ Firefox คุณสมบัติที่กำหนดเองและภาพเคลื่อนไหวจะใช้กับแถบความคืบหน้าขององค์ประกอบจำลองด้วย ดังนี้

progress:indeterminate::-moz-progress-bar {
  background: var(--_indeterminate-track);
  background-size: var(--_indeterminate-track-size);
  background-position: right; 
  animation: var(--_indeterminate-track-animation);
}

JavaScript

JavaScript มีบทบาทสำคัญกับองค์ประกอบ <progress> ซึ่งจะควบคุมค่าที่ส่งไปยังองค์ประกอบและตรวจสอบว่ามีข้อมูลเพียงพอในเอกสารสำหรับโปรแกรมอ่านหน้าจอ

const state = {
  val: null
}

เดโมมีปุ่มสำหรับควบคุมความคืบหน้า ซึ่งจะอัปเดต state.val แล้วเรียกใช้ฟังก์ชันเพื่ออัปเดต DOM

document.querySelector('#complete').addEventListener('click', e => {
  state.val = 1
  setProgress()
})

setProgress()

ฟังก์ชันนี้เป็นที่ที่การประสานงาน UI/UX เกิดขึ้น เริ่มต้นใช้งานโดยสร้างฟังก์ชัน setProgress() ไม่จำเป็นต้องใช้พารามิเตอร์เนื่องจากมีสิทธิ์เข้าถึงออบเจ็กต์ state, องค์ประกอบความคืบหน้า และโซน <main>

const setProgress = () => {
  
}

กำลังตั้งค่าสถานะการโหลดในโซน <main>

องค์ประกอบ <main> ที่เกี่ยวข้องต้องอัปเดตแอตทริบิวต์ aria-busy โดยขึ้นอยู่กับว่าความคืบหน้าเสร็จสมบูรณ์หรือไม่ ดังนี้

const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)
}

ล้างแอตทริบิวต์หากไม่ทราบจำนวนเงินที่โหลด

หากไม่ทราบค่าหรือไม่ได้ตั้งค่า null ในการใช้งานนี้ ให้นำแอตทริบิวต์ value และ aria-valuenow ออก การดำเนินการนี้จะเปลี่ยน <progress> เป็นไม่แน่นอน

const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)

  if (state.val === null) {
    progress.removeAttribute('aria-valuenow')
    progress.removeAttribute('value')
    progress.focus()
    return
  }
}

แก้ไขปัญหาเกี่ยวกับคณิตศาสตร์ทศนิยมของ JavaScript

เนื่องจากฉันเลือกที่จะใช้ค่าสูงสุดเริ่มต้นของความคืบหน้าเป็น 1 ฟังก์ชันการเพิ่มและลดค่าในเดโมจึงใช้คณิตศาสตร์ทศนิยม JavaScript และภาษาอื่นๆ ไม่ได้ทำหน้าที่นี้ได้ดีเสมอไป ต่อไปนี้คือฟังก์ชัน roundDecimals() ที่จะตัดส่วนเกินออกจากผลลัพธ์ทางคณิตศาสตร์

const roundDecimals = (val, places) =>
  +(Math.round(val + "e+" + places)  + "e-" + places)

ปัดเศษค่าเพื่อให้แสดงและอ่านได้ง่าย ดังนี้

const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)

  if (state.val === null) {
    progress.removeAttribute('aria-valuenow')
    progress.removeAttribute('value')
    progress.focus()
    return
  }

  const val = roundDecimals(state.val, 2)
  const valPercent = val * 100 + "%"
}

ตั้งค่าสำหรับโปรแกรมอ่านหน้าจอและสถานะเบราว์เซอร์

ระบบจะใช้ค่านี้ใน 3 ตำแหน่งใน DOM ดังนี้

  1. แอตทริบิวต์ value ขององค์ประกอบ <progress>
  2. แอตทริบิวต์ aria-valuenow
  3. เนื้อหาข้อความภายใน <progress>
const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)

  if (state.val === null) {
    progress.removeAttribute('aria-valuenow')
    progress.removeAttribute('value')
    progress.focus()
    return
  }

  const val = roundDecimals(state.val, 2)
  const valPercent = val * 100 + "%"

  progress.value = val
  progress.setAttribute('aria-valuenow', valPercent)
  progress.innerText = valPercent
}

การให้ความสำคัญกับความคืบหน้า

เมื่ออัปเดตค่าแล้ว ผู้ใช้ที่มองเห็นจะเห็นการเปลี่ยนแปลงความคืบหน้า แต่ผู้ใช้โปรแกรมอ่านหน้าจอจะยังไม่ได้รับการประกาศการเปลี่ยนแปลง โฟกัสองค์ประกอบ <progress> แล้วเบราว์เซอร์จะประกาศการอัปเดต

const setProgress = () => {
  zone.setAttribute('aria-busy', state.val < 1)

  if (state.val === null) {
    progress.removeAttribute('aria-valuenow')
    progress.removeAttribute('value')
    progress.focus()
    return
  }

  const val = roundDecimals(state.val, 2)
  const valPercent = val * 100 + "%"

  progress.value = val
  progress.setAttribute('aria-valuenow', valPercent)
  progress.innerText = valPercent

  progress.focus()
}

ภาพหน้าจอของแอป VoiceOver ของ Mac OS ที่อ่านความคืบหน้าของแถบการโหลดให้ผู้ใช้ฟัง

บทสรุป

ตอนนี้คุณก็รู้วิธีที่เราทำแล้ว คุณจะทำอย่างไรล่ะ‽ 🙂

แน่นอนว่ามีบางอย่างที่ฉันอยากจะเปลี่ยนแปลงหากมีโอกาสอีกครั้ง เราคิดว่ายังมีโอกาสที่จะปรับปรุงคอมโพเนนต์ปัจจุบัน และยังมีโอกาสที่จะลองสร้างคอมโพเนนต์โดยไม่มีข้อจำกัดด้านสไตล์คลาสจำลองขององค์ประกอบ <progress> ซึ่งเป็นสิ่งที่น่าสนใจมาก

มาลองใช้วิธีการที่หลากหลายและเรียนรู้วิธีทั้งหมดในการสร้างบนเว็บกัน

สร้างเดโมแล้วทวีตลิงก์มาหาฉัน แล้วฉันจะเพิ่มเดโมนั้นลงในส่วนรีมิกซ์ของชุมชนด้านล่าง

รีมิกซ์ของชุมชน