x

التصميم المتمحور حول المستخدم User-Centered Design

ما هي أفضل الممارسات للإشارة إلى التقدم Progress Indication في النماذج Forms والتسجيل Registration والإعداد Setup ؟

نظري

ملاحظة: قد تستخدم بعض الأمثلة التفاعلية أكواد CSS و JavaScript لم تتعلمها بعد. لا تقلق بشأن محاولة فهم الكود بالكامل؛ فالهدف من هذه الأمثلة هو عرض نماذج لمفاهيم التصميم هذه، لتتمكن من فهم آلية عملها بشكل أفضل.

الإشارة إلى التقدم هي طريقة لعرض مدى تقدم المستخدم في عملية ما. يمكن استخدامها في النماذج، والتسجيل، وعمليات الإعداد. الهدف هو مساعدة المستخدم على فهم موقعه في العملية وكم تبقى عليه من خطوات.

على سبيل المثال، يمكنك استخدام شريط إشارة التقدم لتوضيح ما تبقى للمستخدم عند ملء النماذج. لا تريد أن تضع المستخدم في موقف يحتاج فيه لملء نموذج طويل ولا يعرف كم خطوة متبقية. الشفافية مهمة ليعرف المستخدم إذا كان لديه وقت كافٍ للجلوس وإكمال النموذج أو إذا كان عليه العودة لاحقًا.

index.html


<link rel="stylesheet" href="styles.css">

<form id="multiStepForm">
  <div class="form-progress">
    <label class="progress-label">تقدم النموذج</label>
    <div class="progress-container">
      <div class="progress-bar"></div>
      <div class="progress-text">الخطوة 1 من 3</div>
    </div>
  </div>

  <!-- Step 1 -->
  <fieldset class="form-step active">
    <legend>معلومات شخصية</legend>
    <label for="name">الاسم الكامل:</label>
    <input type="text" id="name" name="name" required>

    <label for="email">البريد الإلكتروني:</label>
    <input type="email" id="email" name="email" required>

    <button type="button" class="next-btn">التالي</button>
  </fieldset>

  <!-- Step 2 -->
  <fieldset class="form-step">
    <legend>العنوان</legend>
    <label for="address">عنوان الشارع:</label>
    <input type="text" id="address" name="address" required>

    <label for="city">المدينة:</label>
    <input type="text" id="city" name="city" required>

    <button type="button" class="prev-btn">السابق</button>
    <button type="button" class="next-btn">التالي</button>
  </fieldset>

  <!-- Step 3 -->
  <fieldset class="form-step">
    <legend>مراجعة & إرسال</legend>
    <p>يُرجى مراجعة بياناتك قبل الإرسال.</p>

    <button type="button" class="prev-btn">السابق</button>
    <button type="submit">تسليم</button>
  </fieldset>
</form>

<script src="index.js"></script>
            

styles.css


.form-progress {
max-width: 500px;
margin: 20px auto 30px;
font-family: Arial, sans-serif;
}

.progress-label {
display: block;
margin-bottom: 8px;
font-size: 16px;
font-weight: 600;
color: #333;
}

.progress-container {
position: relative;
background-color: #555;
border-radius: 8px;
height: 30px;
overflow: hidden;
box-shadow: inset 0 1px 3px rgba(0,0,0,0.3);
}

.progress-bar {
background-color: #4caf50;
height: 100%;
width: 0;
border-radius: 8px 0 0 8px;
transition: width 0.3s ease;
}

.progress-text {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 30px;
line-height: 30px;
text-align: center;
font-weight: bold;
color: #fff;
pointer-events: none;
user-select: none;
}

form {
max-width: 500px;
margin: 0 auto;
font-family: Arial, sans-serif;
}

fieldset {
border: none;
padding: 0;
margin: 0 0 20px;
}

legend {
font-size: 1.2em;
font-weight: 700;
margin-bottom: 10px;
color: #222;
}

label {
display: block;
margin-bottom: 6px;
font-weight: 600;
color: #333;
}

input[type="text"],
input[type="email"] {
width: 100%;
padding: 8px 10px;
font-size: 1em;
border: 1px solid #ccc;
border-radius: 4px;
margin-bottom: 15px;
box-sizing: border-box;
transition: border-color 0.2s ease;
}

input[type="text"]:focus,
input[type="email"]:focus {
outline: none;
border-color: #4caf50;
box-shadow: 0 0 5px rgba(76, 175, 80, 0.5);
}

.form-step {
display: none;
}

.form-step.active {
display: block;
}

button {
background-color: #4caf50;
border: none;
color: white;
padding: 10px 18px;
font-size: 1em;
border-radius: 5px;
cursor: pointer;
margin-right: 10px;
transition: background-color 0.2s ease;
}

button:hover:not(:disabled) {
background-color: #45a049;
}

button:disabled {
background-color: #9e9e9e;
cursor: not-allowed;
}

@media (max-width: 600px) {
.form-progress, form {
max-width: 90%;
margin: 20px auto;
}
}
    

index.js


const form = document.getElementById('multiStepForm');
const steps = form.querySelectorAll('.form-step');
const progressBar = form.querySelector('.progress-bar');
const progressText = form.querySelector('.progress-text');
const totalSteps = steps.length;

let currentStep = 0;

function updateProgress() {
  const percent = ((currentStep + 1) / totalSteps) * 100;
  progressBar.style.width = percent + '%';
  progressText.textContent = `الخطوة ${currentStep + 1} من ${totalSteps}`;
}

function showStep(index) {
  steps.forEach((step, i) => {
    step.classList.toggle('active', i === index);
  });
  updateProgress();
}

form.querySelectorAll('.next-btn').forEach(btn => btn.addEventListener('click', () => {
  if (currentStep < totalSteps - 1) {
    currentStep++;
    showStep(currentStep);
  }
}));

form.querySelectorAll('.prev-btn').forEach(btn => btn.addEventListener('click', () => {
  if (currentStep > 0) {
    currentStep--;
    showStep(currentStep);
  }
}));

showStep(currentStep);

form.addEventListener('submit', e => {
  e.preventDefault();
  alert('تم إرسال النموذج!');
});
            

معاينة:

عند تصميم قسم إشارة التقدم، هناك بعض أفضل الممارسات التي يجب مراعاتها. الاعتبار الأول هو الحفاظ على البساطة. لا تريد إرباك المستخدم بمعلومات كثيرة تجعله يشعر بالإحباط ويغادر الموقع.

الاعتبار الثاني هو جعل العودة إلى الخطوات السابقة ممكنة. هذا مهم لأن المستخدمين قد يرغبون في مراجعة إجاباتهم السابقة أو تعديلها.

اعتبار آخر هو جعل قسم إشارة التقدم سهل العثور عليه. إذا لم يجد المستخدم القسم، فلن يعرف مدى تقدمه في العملية.

الاعتبار الأخير هو وجود عناوين أقسام واضحة، أو نسب مئوية، أو خطوات. إذا كان لديك فقط شريط تقدم بدون سياق، فلن يعرف المستخدم ما يعنيه.

index.html


<link rel="stylesheet" href="styles.css">

<form id="progressForm">
  <div class="form-progress" aria-label="Form progress">
    <label class="progress-label">الخطوة <span id="currentStep">1</span> من <span id="totalSteps">4</span> (<span id="percentage">25%</span>)</label>
    <div class="progress-container" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="25">
      <div class="progress-bar"></div>
    </div>
  </div>

  <!-- Step 1 -->
  <fieldset class="form-step active">
    <legend>معلومات أساسية</legend>
    <p>يُرجى إدخال معلوماتك الأساسية.</p>
    <label for="name">الاسم:</label>
    <input type="text" id="name" name="name" required>

    <button type="button" class="next-btn">التالي</button>
  </fieldset>

  <!-- Step 2 -->
  <fieldset class="form-step">
    <legend>بيانات الاتصال</legend>
    <p>كيف يمكننا التواصل معك؟</p>
    <label for="email">البريد الإلكتروني:</label>
    <input type="email" id="email" name="email" required>

    <button type="button" class="prev-btn">السابق</button>
    <button type="button" class="next-btn">التالي</button>
  </fieldset>

  <!-- Step 3 -->
  <fieldset class="form-step">
    <legend>العنوان</legend>
    <p>أين تعيش؟</p>
    <label for="address">الشارع:</label>
    <input type="text" id="address" name="address" required>

    <button type="button" class="prev-btn">السابق</button>
    <button type="button" class="next-btn">التالي</button>
  </fieldset>

  <!-- Step 4 -->
  <fieldset class="form-step">
    <legend>مراجعة</legend>
    <p>راجع إجاباتك قبل الإرسال.</p>

    <button type="button" class="prev-btn">السابق</button>
    <button type="submit">تسليم</button>
  </fieldset>
</form>

<script src="index.js"></script>
            

styles.css


.form-progress {
max-width: 500px;
margin: 20px auto 30px;
font-family: Arial, sans-serif;
}

.progress-label {
display: block;
margin-bottom: 8px;
font-size: 16px;
font-weight: 600;
color: #333;
}

.progress-container {
position: relative;
background-color: #555;
border-radius: 8px;
height: 30px;
overflow: hidden;
box-shadow: inset 0 1px 3px rgba(0,0,0,0.3);
}

.progress-bar {
background-color: #4caf50;
height: 100%;
width: 0;
border-radius: 8px 0 0 8px;
transition: width 0.3s ease;
}

.progress-text {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 30px;
line-height: 30px;
text-align: center;
font-weight: bold;
color: #fff;
pointer-events: none;
user-select: none;
}

form {
max-width: 500px;
margin: 0 auto;
font-family: Arial, sans-serif;
}

fieldset {
border: none;
padding: 0;
margin: 0 0 20px;
}

legend {
font-size: 1.2em;
font-weight: 700;
margin-bottom: 10px;
color: #222;
}

label {
display: block;
margin-bottom: 6px;
font-weight: 600;
color: #333;
}

input[type="text"],
input[type="email"] {
width: 100%;
padding: 8px 10px;
font-size: 1em;
border: 1px solid #ccc;
border-radius: 4px;
margin-bottom: 15px;
box-sizing: border-box;
transition: border-color 0.2s ease;
}

input[type="text"]:focus,
input[type="email"]:focus {
outline: none;
border-color: #4caf50;
box-shadow: 0 0 5px rgba(76, 175, 80, 0.5);
}

.form-step {
display: none;
}

.form-step.active {
display: block;
}

button {
background-color: #4caf50;
border: none;
color: white;
padding: 10px 18px;
font-size: 1em;
border-radius: 5px;
cursor: pointer;
margin-right: 10px;
transition: background-color 0.2s ease;
}

button:hover:not(:disabled) {
background-color: #45a049;
}

button:disabled {
background-color: #9e9e9e;
cursor: not-allowed;
}

@media (max-width: 600px) {
.form-progress, form {
max-width: 90%;
margin: 20px auto;
}
}
            

index.js


const form = document.getElementById('progressForm');
const steps = form.querySelectorAll('.form-step');
const progressBar = form.querySelector('.progress-bar');
const currentStepSpan = document.getElementById('currentStep');
const totalStepsSpan = document.getElementById('totalSteps');
const percentageSpan = document.getElementById('percentage');

const totalSteps = steps.length;
let currentStep = 0;

totalStepsSpan.textContent = totalSteps;

function updateProgress() {
  const percent = Math.round(((currentStep + 1) / totalSteps) * 100);
  progressBar.style.width = percent + '%';
  currentStepSpan.textContent = currentStep + 1;
  percentageSpan.textContent = percent + '%';

  // Update ARIA attribute
  form.querySelector('.progress-container').setAttribute('aria-valuenow', percent);
}

function showStep(index) {
  steps.forEach((step, i) => {
    step.classList.toggle('active', i === index);
  });
  updateProgress();
}

form.querySelectorAll('.next-btn').forEach(btn => btn.addEventListener('click', () => {
  if (currentStep < totalSteps - 1) {
    currentStep++;
    showStep(currentStep);
  }
}));

form.querySelectorAll('.prev-btn').forEach(btn => btn.addEventListener('click', () => {
  if (currentStep > 0) {
    currentStep--;
    showStep(currentStep);
  }
}));

form.addEventListener('submit', e => {
  e.preventDefault();
  alert('تم إرسال النموذج! شكرًا لك!');
});

showStep(currentStep);
            

معاينة:

هذه بعض أفضل الممارسات التي يجب مراعاتها عند تصميم إشارة التقدم في النماذج، والتسجيل، وعمليات الإعداد. ادرس بعض الأمثلة في المواقع الكبيرة لترى كيف ينفذون إشارة التقدم. ثم اختبر تصميمك مع مستخدمين حقيقيين لترى مدى فعاليته.

أسئلة :

ما هو الهدف الأساسي من استخدام إشارة التقدم في النماذج أو عمليات التسجيل؟

1. لترفيه المستخدمين أثناء إكمال النموذج. ❌

2. لإعلام المستخدمين بمدى تقدمهم في العملية وما تبقى عليهم فعله. ✅

3. لتقليل عدد الخطوات في العملية. ❌

4. لتسريع عملية إرسال النموذج. ❌


لماذا من المهم السماح للمستخدمين بالعودة إلى الخطوات السابقة في نموذج أو عملية تسجيل؟

1. للسماح للمستخدمين بتغيير إجاباتهم أو مراجعة المدخلات السابقة. ✅

2. لجعل النموذج أكثر تعقيدًا. ❌

3. لتقليل عدد الخطوات في العملية. ❌

4. لزيادة الوقت الذي يقضيه المستخدمون في الموقع. ❌


ما الذي يجب مراعاته عند وضع قسم إشارة التقدم في صفحة ويب؟

1. يجب أن يكون صغيرًا قدر الإمكان لتجنب تشتيت المستخدم. ❌

2. يجب أن يكون سهل العثور عليه وموسومًا بوضوح مع سياق مثل عناوين الأقسام أو النسب المئوية. ✅

3. يجب أن يكون مخفيًا حتى يصل المستخدم إلى الخطوة النهائية. ❌

4. يجب أن يتضمن فقط شريط تقدم بصري بدون نص. ❌