วงกลมแสดงความคืบหน้า (หรือแถบความคืบหน้ารูปวงกลม) จะแสดงภาพสถานะของงาน แถบความคืบหน้าแบบวงกลมต่างจากแถบความคืบหน้าแบบเส้นตรงตรงที่มีรูปทรงกลมซึ่งเหมาะสำหรับแดชบอร์ด คอมโพเนนต์การ์ด หรือที่ใดก็ตามที่มีพื้นที่จำกัด
คู่มือนี้จะใช้แหวนแสดงความคืบหน้าโดยทำดังนี้
- การใช้องค์ประกอบ
<progress>แบบเนทีฟเป็นรากฐานเชิงความหมายเพื่อให้มั่นใจว่าคอมโพเนนต์จะเข้าถึงได้สำหรับโปรแกรมอ่านหน้าจอและผู้ใช้แป้นพิมพ์ตั้งแต่แกะกล่อง - การจัดสไตล์คอมโพเนนต์ด้วย
conic-gradient()และmask-imageช่วยให้วงแหวนตอบสนองได้อย่างเต็มที่และปรับธีมได้โดยไม่ต้องจัดการเส้นทาง SVG ที่ซับซ้อน - ใช้ประโยชน์จากพร็อพเพอร์ตี้ที่กำหนดเองของ CSS และ
@propertyเพื่อให้การเปลี่ยนผ่านของแถบความคืบหน้าเป็นไปอย่างราบรื่นและเร่งด้วย GPU
วิธีนี้เป็นที่นิยมมากกว่าโซลูชันที่ใช้ SVG เท่านั้น เนื่องจากใช้องค์ประกอบ <progress> เชิงความหมายแทน ARIA และผสานรวมกับเลย์เอาต์ ระบบการออกแบบ และการพิมพ์ที่มีอยู่ได้ง่ายกว่า
ดูไอคอนหมุนแสดงการโหลดเพื่อจัดการสถานะการโหลดที่ไม่แน่นอน
การใช้งาน
1. Markup
ใช้ Wrapper เพื่อเก็บทั้งวงแหวนภาพและเนื้อหาตรงกลางที่ไม่บังคับ องค์ประกอบ <progress> ยังคงเป็นแหล่งข้อมูลความจริงเชิงความหมาย ใช้คลาสยูทิลิตีเพื่อซ่อนแถบความคืบหน้าแบบเนทีฟในขณะที่ยังคงเข้าถึงได้
<div class="ring-wrapper">
<progress value="75" max="100" aria-label="Task progress" class="progress-ring"></progress>
<!-- Optional: Content to display in the center -->
<div class="ring-content">
75%
</div>
</div>
2. รูปแบบ
การซ่อน UI แบบเนทีฟ
หากต้องการจัดสไตล์องค์ประกอบ <progress> เป็นวงกลมแสดงความคืบหน้า ให้ซ่อนสไตล์แถบความคืบหน้าเริ่มต้นของเบราว์เซอร์ก่อน
/* Hide native bars */
progress.loading-spinner:indeterminate::-webkit-progress-bar {
display: none;
background: none;
}
progress.loading-spinner:indeterminate::-webkit-progress-value {
display: none;
background: none;
}
progress.loading-spinner:indeterminate::-moz-progress-bar {
display: none;
background: none;
}
progress.loading-spinner:indeterminate::slider-fill {
display: none;
background: none;
}
คอนเทนเนอร์และวงแหวน
Wrapper จะให้บริบทการวางตำแหน่ง องค์ประกอบ <progress> จะจัดการการไล่ระดับสีที่มองเห็นได้
.progress-ring-wrapper {
position: relative;
display: grid;
place-items: center;
}
progress.progress-ring {
--size: 150px;
--thickness: 16px;
--track-color: #f1f5f9;
--fill-color: #3b82f6;
--value: attr(value type(<number>));
width: var(--size);
height: var(--size);
transition: --value 0.4s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: 50%;
background: conic-gradient(
var(--fill-color) calc(var(--value) * 1%),
var(--track-color) 0
);
/* MANDATORY: Clip the background to the border-area. */
background-clip: border-area;
border: var(--thickness) solid transparent;
background-origin: border-box;
}
.progress-ring-content {
/* Positioned in the center of the wrapper */
position: absolute;
}
นอกจากนี้ คุณยังใช้radial-gradientเพื่อสร้างฝาปิดปลายมนได้ด้วย
เปิดใช้การเปลี่ยนผ่านที่ราบรื่นด้วย @property
หากต้องการทำให้วงกลมแสดงความคืบหน้าเคลื่อนไหวอย่างราบรื่นเมื่อค่าเปลี่ยนแปลง ให้ลงทะเบียน --value เป็นพร็อพเพอร์ตี้ที่กำหนดเองที่เป็นตัวเลข
ผู้ใช้ที่ไวต่อการเคลื่อนไหวอาจรู้สึกสับสนเมื่อมีการเปลี่ยนค่า เคารพคิวรี่สื่อ prefers-reduced-motion โดยมีระยะเวลา 0 วินาที (ทันที) โดยค่าเริ่มต้น และตั้งค่าเวลาให้นานขึ้นสำหรับผู้ใช้ที่ไม่มีค่ากำหนด
@property --value {
syntax: '<number>';
inherits: true;
initial-value: 0;
}
progress.progress-ring {
transition: --value 0s ease-in-out;
@media (prefers-reduced-motion: no-preference) {
transition-duration: 0.4s;
}
}
3. ข้อมูลอัปเดตความคืบหน้า
อัปเดตแอตทริบิวต์ value ในองค์ประกอบ <progress> และเนื้อหาข้อความของ .progress-ring-content (หากแสดงเปอร์เซ็นต์) ทุกครั้งที่ค่ามีการเปลี่ยนแปลง
4. สถานะความสำเร็จที่ไม่บังคับ
คุณสามารถใช้ตัวเลือกแอตทริบิวต์ CSS เพื่ออัปเดตลักษณะที่ปรากฏของวงแหวนโดยอัตโนมัติ (เช่น เปลี่ยนสีเป็นสีเขียว) เมื่องานเสร็จสมบูรณ์
/* Change the fill color to green when the progress reaches 100% */
progress.progress-ring[value="100"] {
--fill-color: #10b981;
}
กลยุทธ์สำรอง
อย่าเพิ่มค่าสำรองภายในองค์ประกอบ <progress> เทคโนโลยีความช่วยเหลือพิเศษไม่ได้ใช้แอตทริบิวต์นี้ และเบราว์เซอร์ที่ทันสมัยทั้งหมดจะละเว้นแอตทริบิวต์นี้
ภาพเคลื่อนไหวสำรอง
หากไม่รองรับ @property วงแหวนจะข้ามไปยังค่าใหม่ทันทีแทนที่จะเปลี่ยนอย่างราบรื่น ในกรณีส่วนใหญ่ การดำเนินการนี้เป็นเรื่องปกติและไม่ได้ทำให้ฟังก์ชันการทำงานใดๆ เสียหาย
หากจำเป็นต้องใช้การเปลี่ยนผ่านจริงๆ คุณสามารถตรวจสอบการรองรับ @property และใช้ลูป requestAnimationFrame() เพื่อแทรก --value ในเบราว์เซอร์รุ่นเก่าได้
สำหรับเบราว์เซอร์ที่ยังไม่รองรับ background-clip: border-area ให้เปลี่ยนกลับไปใช้ mask-image เพื่อทำให้ตรงกลางขององค์ประกอบ <progress> ว่างเปล่า
@supports not (background-clip: border-area) {
mask-image: radial-gradient(
transparent calc(50% - var(--thickness)),
black calc(50% - var(--thickness) + 0.5px)
);
border: 0;
}
สำหรับเบราว์เซอร์ที่ไม่รองรับฟังก์ชัน CSS attr() สำหรับพร็อพเพอร์ตี้ใดๆ ให้ใช้ MutationObserver เพื่อซิงค์แอตทริบิวต์ value กับคุณสมบัติที่กำหนดเอง --value โดยอัตโนมัติ
if (!CSS.supports("width: attr(value type(<number>))")) {
const observer = new MutationObserver(() => {
progress.style.setProperty("--value", progress.getAttribute("value"));
});
observer.observe(progress, {
attributes: true,
attributeFilter: ["value"],
});
}