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

ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างแถบการโหลดที่ปรับสีได้และเข้าถึงได้โดยใช้องค์ประกอบ <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;
}

ภาพหน้าจอของเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ที่แสดงองค์ประกอบที่พร้อมแสดงบนหน้าจอเท่านั้น

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

หากคุณมีการมองเห็นที่ดีอยู่แล้ว ก็สามารถเชื่อมโยงสัญญาณบอกสถานะความคืบหน้ากับองค์ประกอบและพื้นที่ของหน้าที่เกี่ยวข้องกันได้ง่ายๆ แต่ผู้ใช้ที่มีความบกพร่องทางสายตาจะเห็นได้ไม่ชัดเจนนัก ปรับปรุงได้โดยกําหนดแอตทริบิวต์ 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> โดย 1 รายการสำหรับสีแทร็ก และอีก 1 รายการสำหรับสีความคืบหน้าของแทร็ก ใน prefers-color-scheme ของ Media Query ให้ระบุค่าสีใหม่สำหรับแทร็กและความคืบหน้าของแทร็ก

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. ในส่วนหัวองค์ประกอบ ให้ค้นหาและเปิดใช้ช่องทําเครื่องหมายแสดงเงา User Agent DOM

ภาพหน้าจอของตำแหน่งในเครื่องมือสำหรับนักพัฒนาเว็บเพื่อเปิดใช้การแสดง 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 และตำแหน่งที่จะพบส่วนต่างๆ ขององค์ประกอบความคืบหน้า

ภาพหน้าจอของมุมแก้ไขข้อบกพร่องที่ 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 ใช้เพียง 1 คีย์เฟรมเท่านั้น คือคีย์เฟรมกลางที่ 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 + "%"
}

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

ค่านี้ใช้ใน DOM 3 ตําแหน่ง ได้แก่

  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()
}

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

บทสรุป

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

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

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

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

รีมิกซ์ในชุมชน