สร้างแถบความคืบหน้าที่จัดรูปแบบแล้ว

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

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

แถบความคืบหน้าหรือวงกลมแสดงความคืบหน้า

  • หากมีพื้นที่จำกัดหรือต้องการสัดส่วนภาพแบบสี่เหลี่ยมจัตุรัส ให้พิจารณาใช้แถบความคืบหน้าแบบวงกลม (วงกลมแสดงความคืบหน้า): วงกลมแสดงความคืบหน้า
  • ใช้ไอคอนหมุนสำหรับสถานการณ์ส่วนใหญ่ที่ความคืบหน้าไม่แน่นอน (ไอคอนหมุนแสดงการโหลด) ใช้แถบความคืบหน้าแบบไม่ระบุเวลาเมื่อสถานะไม่ระบุเวลาเป็นแบบชั่วคราว และจะถูกแทนที่ด้วยแถบความคืบหน้าแบบระบุเวลาในเร็วๆ นี้ (เช่น การรอข้อมูลเมตาเกี่ยวกับการอัปโหลดก่อนที่จะแสดง % ความคืบหน้า)

Markup

  1. ใช้องค์ประกอบ <progress> แบบเนทีฟ: ซึ่งจะให้การช่วยเหลือพิเศษในตัวและลักษณะการทำงานที่สอดคล้องกันในแพลตฟอร์ม
  2. ใช้ max หากต้องการใช้ระดับคะแนนที่แตกต่างจากระดับคะแนน 0-1 เริ่มต้น
  3. หากต้องการค่าความคืบหน้าที่เฉพาะเจาะจง ให้ตั้งค่าแอตทริบิวต์ value ละเว้น value สำหรับสถานะที่ไม่แน่นอน (เช่น ก่อนที่ความคิดเห็นที่เป็นรูปธรรมมากขึ้นจะเริ่มขึ้น)
  4. ใช้ <label for="...">, aria-labelledby หรือ aria-label เพื่อเชื่อมโยงองค์ประกอบความคืบหน้ากับป้ายกำกับ

คุณต้องการการปรับแต่งประเภทใด

พร็อพเพอร์ตี้ต่อไปนี้เพียงพอสำหรับการจัดรูปแบบที่จำกัด

  • accent-color เพื่อเปลี่ยนสีของแถบความคืบหน้า
  • width / inline-size เพื่อเปลี่ยนความกว้างของแถบความคืบหน้า
  • height/block-size มีผลไม่สอดคล้องกัน โปรดทดสอบก่อน
  • writing-mode: vertical-lr สำหรับแถบแนวตั้ง
  • เอฟเฟกต์ที่ใช้หลังจากการวาด: opacity, filter, clip-path, มาสก์, การเปลี่ยนรูปแบบ, box-shadow ฯลฯ

หากการจัดรูปแบบที่จำกัดเพียงพอแล้ว ให้ข้ามส่วนถัดไป

คำเตือน: พร็อพเพอร์ตี้บางอย่าง (เช่น border-radius, background, border) จะปิดใช้การจัดรูปแบบแถบความคืบหน้าเริ่มต้นโดยไม่มีการแจ้งเตือน หากต้องการจัดรูปแบบนอกเหนือจากพร็อพเพอร์ตี้ข้างต้น คุณต้องใช้การจัดรูปแบบที่กำหนดเองทั้งหมดตามที่อธิบายไว้ในส่วนถัดไป อย่าใช้การจัดรูปแบบที่ครอบคลุมมากขึ้น "เผื่อว่าจะได้ผล"

การจัดรูปแบบที่กำหนดเองอย่างเต็มรูปแบบ

1. การตั้งค่าพื้นฐาน

  • บังคับ: ใช้ appearance: none เพื่อเปิดใช้การจัดรูปแบบที่กำหนดเอง
  • รีเซ็ตขอบเขต UA ด้วย border: 0 solid
  • หากต้องการคลิปแถบที่ใช้งานอยู่กับรัศมีเส้นขอบขององค์ประกอบ ให้ใช้ overflow: clip หรือใช้ border-radius เดียวกันกับแถบ อย่าใช้ border-radius: inherit ในแถบ ซึ่งขึ้นอยู่กับโครงสร้างเฉพาะขององค์ประกอบใน Shadow DOM
progress {
  /* Reset default browser styles */
  appearance: none;
  border: 0 solid;
  /* Clip bar to element’s border-radius  */
  overflow: clip;
}

2. การจัดรูปแบบ

  • จัดสไตล์แทร็กในองค์ประกอบ progress เอง
  • ใช้องค์ประกอบเทียมที่กำหนดเป้าหมายเบราว์เซอร์ที่เหมาะสมเพื่อกำหนดเป้าหมายแถบความคืบหน้าเอง: ::-webkit-progress-value สำหรับ WebKit/Blink และ ::-moz-progress-bar สำหรับ Firefox
  • บังคับ: อย่าจัดกลุ่มองค์ประกอบจำลอง -webkit- และ -moz- ไว้ในกฎเดียวกัน ระบบจะถือว่ากฎไม่ถูกต้องและจะละเว้นกฎดังกล่าว :is() และ :where() ไม่ช่วยในกรณีนี้ เนื่องจากไม่รองรับองค์ประกอบจำลอง
  • องค์ประกอบเทียมที่กำหนดเป้าหมายตามเบราว์เซอร์แต่ละรายการควรปรากฏเพียงครั้งเดียว การปรับแต่งเฉพาะสถานะ (เช่น ขนาดส่วนและภาพเคลื่อนไหวที่ไม่แน่นอน) ควรได้รับการกำหนดเส้นทางผ่านคุณสมบัติที่กำหนดเองซึ่งตั้งค่าไว้ในองค์ประกอบ progress เอง
  • ไม่บังคับ: เปลี่ยน inline-size ในการเติมเพื่อให้การเปลี่ยนแปลงค่าที่กำหนดเป็นภาพเคลื่อนไหวแทนที่จะข้ามไปเลย Firefox จะปรับขนาดการเติมในเลย์เอาต์และไม่สนใจการเติม ซึ่งไม่เป็นอันตราย
progress {
  --progress-bar-radius: 1e5px;
  border-radius: var(--progress-bar-radius);
  /* Apply color for custom progress track (background) */
  background: var(--progress-bar-track, var(--color-neutral-90));
  /* Subtle depth on the empty part of the track */
  box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1);
}

/* Let <progress> styling show through */
progress::-webkit-progress-bar {
  background: transparent;
}

/* Webkit, Chrome */
progress::-webkit-progress-value {
  background: var(--progress-bar-fill, var(--accent-color));
  border-radius: var(--progress-bar-radius);
  transition: inline-size 0.3s;
}

/* Firefox */
progress::-moz-progress-bar {
  background: var(--progress-bar-fill, var(--accent-color));
  border-radius: var(--progress-bar-radius);
  transition: inline-size 0.3s;
}

3. การจัดรูปแบบสถานะไม่แน่นอน

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

  • จัดรูปแบบการเติมสีเอง อย่าสร้างใหม่เป็นพื้นหลังใน progress
  • การเติมแบบไม่แน่นอนจะเกิดขึ้นผ่านภาพเคลื่อนไหวเท่านั้น โดยคีย์เฟรมจะกำหนดความยาวด้วย inline-size จริง (ซึ่งจะแทนที่ inline-size ในบรรทัดของ UA ของ Chromium) และย้ายด้วย translate อย่าใช้ scale สำหรับความยาว เนื่องจากจะทำให้ลวดลายที่วาดบนการเติมบิดเบี้ยว
  • เปอร์เซ็นต์ translate จะเทียบกับความกว้างของเส้นเติมเอง ดังนั้นให้แสดงตำแหน่งในหน่วยแทร็กแทน โดยทำให้ progress เป็นคอนเทนเนอร์ขนาดในบรรทัดและใช้ cqi ในคีย์เฟรม รวม margin-right: auto ไว้ใน from, to เพื่อให้ Chromium วางการเติมที่ด้านซ้ายจริงใน RTL ด้วย
  • ใช้การเปลี่ยนรูปแบบ ไม่ใช่ระยะขอบ เพื่อย้ายการเติม
    • การเปลี่ยนรูปแบบจะเก็บภาพเคลื่อนไหวไว้ในคอมโพสิเตอร์ (เว้นแต่ว่า inline-size จะเคลื่อนไหวด้วย)
    • ระยะขอบจะแบ่งออกเป็น RTL ด้วยเหตุผล 2 ประการแยกกัน ดังนี้
    • Firefox จะวางตำแหน่งการเติมที่ไม่แน่นอนโดยใช้เฉพาะระยะขอบด้านซ้ายจริง ดังนั้น margin-inline-start จึงไม่มีผลใน RTL และการเติมจะไม่เคลื่อนที่
    • ใน Chromium และ WebKit ซึ่งจัดวางการเติมเป็นบล็อกปกติ เมื่อระยะขอบดันการเติมให้เลยจุดสิ้นสุดของแทร็ก ระยะขอบจะรวมกันมากกว่าแทร็ก CSS มาตรฐานจะแก้ไขปัญหานี้โดยละเว้น margin-left ใน RTL เพื่อให้ส่วนดังกล่าวข้ามไปยังขอบแทนที่จะเลื่อนออกไป
    • translate จะมีผลหลังจากเลย์เอาต์ ดังนั้นจึงไม่มีปัญหาใดๆ
  • หากต้องการมิเรอร์การเคลื่อนไหวใน RTL (เหมือนกับแถบเนทีฟของ Chrome) ให้กลับภาพเคลื่อนไหวใน :dir(rtl):
progress:dir(rtl) {
  --progress-bar-indeterminate-animation: progress-bar-indeterminate var(--progress-bar-indeterminate-animation-duration) infinite linear reverse;
}
  • กำหนดพร็อพเพอร์ตี้ --progress-bar-indeterminate-* สาธารณะใน progress (ชื่อของพร็อพเพอร์ตี้จะกำหนดขอบเขตให้อยู่ในสถานะอยู่แล้ว) เพื่อให้ผู้บริโภคสามารถลบล้างพร็อพเพอร์ตี้เหล่านั้นได้โดยไม่ต้องทราบเกี่ยวกับ :indeterminate
  • หากต้องการเปลี่ยนความยาวของส่วน (เช่น ขอบนำหน้าเคลื่อนที่ไปข้างหน้าและขอบตามหลังเคลื่อนที่ตามทัน) ให้ตั้งค่า --progress-bar-indeterminate-animation เป็นภาพเคลื่อนไหวที่เกิดขึ้นพร้อมกัน 2 รายการ โดยรายการหนึ่งมีคีย์เฟรมที่ทำให้ translate เคลื่อนไหวใน cqi (ตำแหน่ง) และอีกรายการหนึ่งมีคีย์เฟรมที่ทำให้ inline-size เคลื่อนไหว (ความยาว) เพื่อให้แต่ละรายการมีคีย์เฟรมและการค่อยๆ เปลี่ยนของตัวเอง อย่าพยายามปรับรูปร่างขอบทั้ง 2 ด้านในรายการคีย์เฟรมเดียว เนื่องจาก animation-timing-function ต่อคีย์เฟรมจะมีผลกับพร็อพเพอร์ตี้ทุกรายการในคีย์เฟรมนั้น
  • --progress-bar-animation จะมีผลในทั้ง 2 สถานะและใช้สำหรับเอฟเฟกต์ต่างๆ ได้ เช่น ชิมเมอร์แบบกำหนดได้ revert-rule ใช้เพื่อลบล้างเมื่อมีการตั้งค่าเท่านั้น เพื่อเพิ่มความสามารถในการประกอบให้สูงสุด
  • อย่าปิดใช้ภาพเคลื่อนไหวที่ไม่แน่นอน (animation: none จะปล่อยให้มีการเติมความกว้างเป็นศูนย์ใน Chromium) สำหรับการเคลื่อนไหวที่ลดลง ให้ลดความเร็วลงแทน
progress {
  /* Lets the fill position itself in track units (cqi) */
  container-type: inline-size;
  /* Segment length relative to the track */
  --progress-bar-indeterminate-size: 30%;
  --progress-bar-indeterminate-animation-duration: 1.5s;

  /* Respect prefers-reduced-motion */
  @media (prefers-reduced-motion: reduce) {
    --progress-bar-indeterminate-animation-duration: 10s;
  }
}

progress:indeterminate {
  --progress-bar-animation: var(
      --progress-bar-indeterminate-animation,
      progress-bar-indeterminate var(--progress-bar-indeterminate-animation-duration) infinite linear
    );
}

/* Add to the existing pseudo-element rules */
progress::-webkit-progress-value {
  animation: var(--progress-bar-animation, revert-rule);
}

progress::-moz-progress-bar {
  animation: var(--progress-bar-animation, revert-rule);
}

/* Physical: left to right regardless of direction (reverse under :dir(rtl) to mirror). */
@keyframes progress-bar-indeterminate {
  from, to {
    inline-size: var(--progress-bar-indeterminate-size);
    /* Pin to the physical left; Chromium would otherwise lay the fill out at the inline start */
    margin-right: auto;
  }
  from { translate: -100%; } /* Own width: fully outside the left edge */
  to { translate: 100cqi; }  /* Track width: fully outside the right edge */
}

ข้อควรพิจารณาเพิ่มเติมเกี่ยวกับการช่วยเหลือพิเศษ

นอกเหนือจากหลักเกณฑ์ที่กล่าวถึงข้างต้นแล้ว โปรดทำดังนี้

  • ประกาศว่าเสร็จสมบูรณ์โดยไม่ดึงโฟกัส: อย่าตั้งค่า tabindex หรือเรียกใช้ .focus() ใน <progress> เนื่องจากไม่มีการโต้ตอบ และการย้ายโฟกัสไปยังองค์ประกอบดังกล่าวจะรบกวนผู้ใช้แป้นพิมพ์ หากต้องการประกาศเมื่อทำงานเบื้องหลังเสร็จแล้ว ให้อัปเดตองค์ประกอบสถานะแบบสุภาพ (role="status" หรือ aria-live="polite")
  • อย่าเพิ่มข้อความสำรองภายใน <progress>: เบราว์เซอร์ที่ทันสมัยจะไม่สนใจข้อความภายใน <progress> และเทคโนโลยีความช่วยเหลือพิเศษจะไม่ใช้ข้อความดังกล่าว
  • หลีกเลี่ยงการใช้ aria-busy + aria-describedby ใน <div> ทั่วไปที่ไม่มีป้ายกำกับ aria-busy มีการรองรับโปรแกรมอ่านหน้าจอที่ไม่สอดคล้องกัน และเทคโนโลยีความช่วยเหลือพิเศษจะละเว้น aria-describedby ใน <div> ที่ไม่มีชื่อและไม่มีบทบาท หากเนื้อหาของภูมิภาคไม่พร้อมใช้งานขณะโหลด ให้ซ่อนด้วย hidden หรือ aria-hidden="true"
  • ควรตรวจสอบว่าแถบความคืบหน้าและแทร็กมีคอนทราสต์ที่เหมาะสมเมื่อเพิ่มรูปแบบที่กำหนดเอง
  • พิจารณาทางเลือกอื่นเพื่อแสดงสถานะที่ไม่แน่นอน: ภาพเคลื่อนไหวของแถบความคืบหน้าที่ไม่แน่นอนซึ่งแสดงควบคู่ไปกับเนื้อหาอื่นๆ อาจถือเป็นการรบกวนผู้ใช้บางราย

กลยุทธ์สำรอง

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

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

หากไม่รองรับ accent-color และจำเป็นต้องจัดรูปแบบแถบความคืบหน้า ให้ใช้วิธีการจัดรูปแบบที่กำหนดเองเพื่อใช้การจัดรูปแบบที่ต้องการกับแถบความคืบหน้า

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

หากไม่รองรับ revert-rule animation: var(--progress-bar-animation, revert-rule) จะเปลี่ยนกลับไปใช้ animation-name: revert-rule โดยมีระยะเวลา 0s เมื่อไม่ได้ตั้งค่า --progress-bar-animation ซึ่งเป็นการดำเนินการที่ไม่มีผลเมื่อไม่มี @keyframes revert-rule