نظرة عامة أساسية حول طريقة تصميم شريط تحميل قابل للتكيّف مع الألوان باستخدام العنصر <progress>
في هذه المشاركة، أودّ أن أشارك معك أفكارًا حول كيفية إنشاء شريط تحميل قابل للتكيّف مع الألوان باستخدام العنصر <progress>
. جرِّب العرض التوضيحي واطّلع على
المصدر.
في ما يلي إصدار YouTube من هذه المشاركة إذا كنت تفضّل الفيديوهات:
نظرة عامة
يقدّم عنصر
<progress>
ملاحظات مرئية ومسموعة للمستخدمين بشأن إكمال الإجراء. هذه الملاحظات المرئية مفيدة في حالات مثل: التقدّم في نموذج، أو عرض عملية تنزيل أو تحميل المعلومات، أو حتى إظهار أنّ مقدار التقدّم غير معروف، لكنّ العمل لا يزال جاريًا.
تعاون تحدي واجهة المستخدم الرسومية (GUI) مع عنصر HTML الحالي <progress>
لتوفير بعض الجهد في تسهيل الاستخدام. تدفع الألوان والتخطيطات حدود التخصيص للعنصر المضمن، لتحديث المكون وجعله مناسبًا بشكل أفضل داخل أنظمة التصميم.
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);
}
اللون
يجلب المتصفّح ألوانه الخاصة لعنصر التقدّم، ويتكيّف مع اللون الفاتح والداكن باستخدام خاصية CSS واحدة فقط. ويمكن زيادة هذا الشرط باستخدام بعض أدوات الاختيار الخاصة بالمتصفّح.
أنماط المتصفّح الفاتح والداكن
لتفعيل عناصر <progress>
التكيُّفية الداكنة والفاتحة على موقعك الإلكتروني، ما عليك سوى استخدام
color-scheme
.
progress {
color-scheme: light dark;
}
لون معبأ لمستوى التقدّم في موقع واحد
لتلوين عنصر <progress>
، استخدِم accent-color
.
progress {
accent-color: rebeccapurple;
}
لاحِظ أنّ لون خلفية المسار يتغيّر من الفاتح إلى الداكن استنادًا إلى accent-color
. يضمن المتصفّح ظهور تباين مناسب: أنيق جدًا.
ألوان فاتحة وداكنة مخصصة بالكامل
اضبط سمتَين مخصّصتَين للعنصر <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>
التي يعرضها كل متصفّح. يكون استخدام عنصر التقدم علامة واحدة، ولكنه يتكوّن من عدد قليل من العناصر الثانوية التي تظهر من خلال أدوات اختيار CSS الزائفة. ستعرض "أدوات مطوري البرامج في Chrome"
هذه العناصر لك إذا فعّلت الإعداد:
- انقر بزر الماوس الأيمن على صفحتك واختَر فحص العنصر لإظهار "أدوات مطوري البرامج".
- النقر على رمز ترس "الإعدادات" في أعلى يسار نافذة "أدوات مطوري البرامج".
- ضمن العنوان العناصر، ابحث عن مربّع الاختيار عرض ظل وكيل المستخدم DOM وفعِّله.
أنماط 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 تم ضبط لونه من accent-color
، فيما يتضمّن iOS Safari
مسارًا باللون الأزرق الفاتح. وهو الأمر نفسه في الوضع الداكن، فمتصفّح Firefox يحتوي على مسار داكن اللون
ولكنه ليس باللون المخصّص الذي حدّدناه، ويعمل في المتصفّحات المستندة إلى Webkit.
Animation
أثناء العمل باستخدام أدوات الاختيار الزائفة المضمّنة في المتصفح، غالبًا ما تتم إضافة مجموعة محدودة من سمات 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 وتطبيق تدرج يتم تحريكه ذهابًا وإيابًا لجميع المتصفحات الثلاثة.
الخصائص المخصّصة
وتعدّ الخصائص المخصصة مفيدة للعديد من العناصر، ولكن من أفضلها اختيار اسم لقيمة 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;
}
ستساعد الخصائص المخصّصة أيضًا في بقاء الرمز في حالة جفاف لأنّه لا يمكننا تجميع أدوات الاختيار هذه الخاصة بكل متصفّح معًا.
الإطارات الرئيسية
الهدف هو رسوم متحركة لامتناهية تتنقل ذهابًا وإيابًا. سيتم تعيين الإطارات الرئيسية
للبداية والنهاية في 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()
هذه الوظيفة هي المكان الذي يحدث فيه تنسيق واجهة المستخدم/تجربة المستخدم. يمكنك البدء بإنشاء دالة 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:
- السمة
value
للعنصر<progress>
- السمة
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
}
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()
}
الخلاصة
الآن بعد أن عرفت كيف فعلت ذلك، كيف يمكنك‽ 🙂
وهناك بالتأكيد بعض التغييرات التي أود إجراؤها إذا أُتيحت فرصة أخرى. أعتقد أنّ هناك مجالاً لحذف المكوِّن الحالي، ويمكن محاولة إنشاء مكوِّن بدون قيود نمط الفئة الزائفة في العنصر <progress>
. الأمر يستحق الاستكشاف!
دعونا ننويع أساليبنا ونتعلم جميع طرق الإنشاء على الويب.
يمكنك إنشاء عرض توضيحي وروابط تغريدات لي وسنضيفها إلى قسم الريمكسات في المنتدى أدناه.