স্পিনার লোড হচ্ছে

সঠিক সময়সীমা জানা না থাকলে, কোনও প্রসেস চলছে কিনা তা ব্যবহারকারীকে জানাতে লোডিং স্পিনার (বা অ্যাক্টিভিটি ইন্ডিকেটর) ব্যবহার করা হয়। প্রোগ্রেস রিংয়ের মতো নয়, স্পিনার হল "অনির্দিষ্ট" এবং সাধারণত অ্যাক্টিভিটি সিগন্যাল করতে অ্যানিমেশন ব্যবহার করে।

এই নির্দেশিকা নিম্নলিখিত উপায়ে স্পিনার প্রয়োগ করে:

  • সিম্যান্টিক ফাউন্ডেশন হিসেবে নেটিভ <progress> এলিমেন্ট ব্যবহার করা। value অ্যাট্রিবিউট বাদ দিয়ে, ব্রাউজার এটিকে একটি অনির্দিষ্ট প্রোগ্রেস বার হিসেবে বিবেচনা করে, যা সহায়ক প্রযুক্তির মাধ্যমে সঠিক ঘোষণা নিশ্চিত করে।
  • একটি ভিজ্যুয়াল "ট্রেল" তৈরি করতে conic-gradient() দিয়ে কম্পোনেন্ট স্টাইল করা এবং কেন্দ্রটিকে একটি রিংয়ে ফাঁপা করতে background-clip: border-area।
  • CSS ট্রান্সফর্ম ব্যবহার করে স্পিনারকে দক্ষতার সাথে অ্যানিমেট করা এবং prefers-reduced-motion-কে সম্মান করা যাতে সমস্ত ব্যবহারকারীর জন্য একটি আরামদায়ক অভিজ্ঞতা নিশ্চিত করা যায়।

নির্দিষ্ট সময়সীমা সহ নির্ধারিত টাস্ক ম্যানেজ করার জন্য প্রোগ্রেস রিং দেখুন।

প্রয়োগ

১. Markup

নেটিভ <progress> এলিমেন্টকে সিম্যান্টিক সোর্স অফ ট্রুথ এবং ভিজ্যুয়াল কম্পোনেন্ট হিসেবে ব্যবহার করুন। value অ্যাট্রিবিউট ছাড়া, এটি অন্তর্নিহিতভাবে অনির্দিষ্ট।

<progress aria-label="Loading" class="loading-spinner"></progress>

২. স্টাইল

নেটিভ 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;
}

স্পিনার রিং ও ট্রেল

স্পিনার একটি ভিজ্যুয়াল ট্রেইল তৈরি করতে conic-gradient ব্যবহার করে।

@property --arc-start {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
@property --arc-end {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
/* Use a custom property to conditionally include the dash animation */
@property --progress-dash-animation {
  syntax: "*";
  inherits: false;
  initial-value: , progress-dash 3s ease-in-out infinite;
}

progress.loading-spinner:indeterminate {
  --_from: calc(90deg + var(--arc-start, 0deg));
  --_to: calc(90deg + var(--arc-end, 158deg));
  --size: 40px;
  --thickness: 2px;
  --spinner-color: #3b82f6;
  --track-color: #e2e5e7;
  --spinner-duration: 1.5s;
  --_used-spinner-duration: var(--spinner-duration);
  --spinner-timing: linear;

  position: relative;
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  appearance: none;

  /* Create the fading trail with dynamic angles */
  background: conic-gradient(
      from var(--_from),
      var(--spinner-color) calc(var(--_to) - var(--_from)),
      transparent 0
    )
    var(--track-color);

  @supports (background-clip: border-area) {
    background-clip: border-area;
    border: var(--thickness) solid transparent;
    background-origin: border-box;
  }

  /* ... fallback for background-clip: border-area ... */

  /* The dash animation is only included if @property is supported */
  animation:
    progress-spin var(--_used-spinner-duration) linear infinite
    var(--progress-dash-animation, );
}

@keyframes progress-spin {
  to {
    rotate: 1turn;
  }
}

@keyframes progress-dash {
  from {
    --arc-start: 0deg;
    --arc-end: 3deg;
  }
  50% {
    --arc-start: 100deg;
    --arc-end: 358deg;
  }
  to {
    --arc-start: 360deg;
    --arc-end: 363deg;
  }
}

মোশন সংক্রান্ত পছন্দকে সম্মান জানানো

মোশন সেনসিটিভিটি আছে এমন ব্যবহারকারীদের কাছে দ্রুত ঘুরছে এমন এলিমেন্ট বিভ্রান্তিকর মনে হতে পারে। prefers-reduced-motion মিডিয়া কোয়েরি সবসময় মেনে চলুন। ব্যবহারকারীর --spinner-duration ভ্যালু ওভাররাইড করতে ইন্টার্নাল --_used-spinner-duration প্রপার্টি সেট করুন।

@media (prefers-reduced-motion: reduce) {
  .loading-spinner {
    /* Slow down the animation significantly rather than stopping it entirely,
       so the user still knows that the process is active. */
    --_used-spinner-duration: 6s;
  }
}

ফলব্যাক স্ট্র্যাটেজি

@property কাজ করলে, ড্যাশ অ্যানিমেশন অটোমেটিক --progress-dash-animation প্রপার্টির initial-value-এর মাধ্যমে অন্তর্ভুক্ত করা হয়। @property সাপোর্ট করে না এমন ব্রাউজারে, প্রপার্টি রেজিস্ট্রেশন উপেক্ষা করা হয় এবং অ্যানিমেশনটি একটি সাধারণ রোটেশনে ফিরে আসে। এই ফলব্যাকের জন্য কোনও জাভাস্ক্রিপ্টের প্রয়োজন নেই।

যেসব ব্রাউজারে এখনও background-clip: border-area কাজ করে না, সেগুলিতে কেন্দ্র ফাঁকা করার জন্য mask-image-এ ফিরে যান।

/* Fallback: use mask-image to create the ring */
@supports not (background-clip: border-area) {
  --clip-boundary: calc(100% - var(--thickness));
  mask-image: radial-gradient(
    farthest-side,
    transparent var(--clip-boundary),
    black var(--clip-boundary)
  );
  border: 0;
}