স্ক্রল করার সময় হেডার ছোট করা

স্ক্রল করার সময় হেডার ছোট হয়ে যাওয়া হল একটি সাধারণ UI প্যাটার্ন যেখানে ব্যবহারকারী নিচের দিকে স্ক্রল করলে পৃষ্ঠার উপরে থাকা একটি নির্দিষ্ট হেডার এলিমেন্ট মসৃণভাবে ছোট আকারে পরিবর্তিত হয়। এই এফেক্টটি প্রায়শই মূল কন্টেন্টের জন্য স্ক্রিন রিয়েল এস্টেটকে সর্বাধিক করতে ব্যবহৃত হয় এবং একই সাথে প্রয়োজনীয় নেভিগেশন বা ব্র্যান্ডিং এলিমেন্ট অ্যাক্সেসযোগ্য রাখে। CSS স্ক্রল-চালিত অ্যানিমেশনের মাধ্যমে, ডকুমেন্টের স্ক্রল পজিশনে অ্যানিমেশন লিঙ্ক করে, এই এফেক্টটি ডিক্লেরেটিভ এবং পারফর্ম্যান্ট উপায়ে অর্জন করা যেতে পারে।

কীভাবে প্রয়োগ করতে হয়

স্ক্রল করার সময় সঙ্কুচিত হওয়া হেডার কীভাবে তৈরি করবেন তা এখানে দেওয়া হল:

  1. ফিক্সড হেডার তৈরি করুন: পৃষ্ঠার সবচেয়ে উপরে ফিক্স করা এবং আগে থেকে নির্ধারিত উচ্চতা আছে এমন হেডার এলিমেন্ট দিয়ে শুরু করুন।

    <header>HEADER</header>
    
    header {
      position: fixed;
      height: 200px;
      top: 0;
      left: 0;
      right: 0;
    }
    
  2. সঙ্কুচিত অ্যানিমেশন নির্ধারণ করুন: একটি CSS অ্যানিমেশন তৈরি করুন যা হেডারের উচ্চতা পরিবর্তন করে।

    @keyframes shrink {
      to {
        height: 50px;
      }
    }
    
  3. অ্যানিমেশন ও স্ক্রল টাইমলাইন প্রয়োগ করুন: হেডারে অ্যানিমেশন অ্যাটাচ করুন এবং ডকুমেন্টের স্ক্রল পজিশনের সাথে এটি লিঙ্ক করতে scroll() ফাংশন ব্যবহার করুন।

    header {
      animation: shrink auto linear both;
      animation-timeline: scroll(block root);
    }
    
  4. animation-range সেট করুন: animation-range প্রপার্টি ব্যবহার করে স্ক্রল করার দূরত্ব নির্দিষ্ট করুন, যার উপর অ্যানিমেশন দেখানো হবে। যেমন, স্ক্রল করার প্রথম ১৫০ পিক্সেলের মধ্যে হেডার ছোট করতে, আপনি animation-range: 0px 150px; ব্যবহার করবেন।

    header {
      animation-range: 0px 150px;
    }
    

পরামর্শ: হেডারের পরে থাকা কন্টেন্ট যাতে হেডারের কারণে অস্পষ্ট না হয়ে যায়, তার জন্য body-এ (বা মূল কন্টেন্ট কন্টেনারে) একটি padding-top যোগ করুন যা হেডারের প্রাথমিক উচ্চতার সমান।

পরামর্শ: পৃষ্ঠার কন্টেন্ট যাতে সঙ্কুচিত হওয়া হেডারের সাথে সিঙ্ক করে স্ক্রল করে তা নিশ্চিত করতে, শুরু ও শেষের সাইজের মধ্যে পার্থক্য হিসেবে animation-range-end সেট করুন। এটি নিশ্চিত করে যে হেডারটি তার চূড়ান্ত আকারে পৌঁছালে অ্যানিমেশনটি সঠিকভাবে সম্পূর্ণ হয়। এই ডেমোতে হেডার 200px থেকে 50px-এ সঙ্কুচিত হয়, তাই animation-range-end-কে 150px-এ সেট করা হয়েছে।

কোডের উদাহরণ

@keyframes shrink {
  to {
    height: 50px;
  }
}

header {
  animation: shrink auto linear both;
  animation-timeline: scroll(block root);
  animation-range: 0px 150px;
}

পেশাদার পদ্ধতি

স্ক্রল-চালিত অ্যানিমেশন ব্যবহার করার সময়, মসৃণ ও অ্যাক্সেসযোগ্য অভিজ্ঞতা নিশ্চিত করতে কয়েকটি পেশাদার পদ্ধতি অনুসরণ করা গুরুত্বপূর্ণ:

  • ফিচার শনাক্তকরণ অন্তর্ভুক্ত করুন: সব ব্রাউজার স্ক্রল-চালিত অ্যানিমেশন সাপোর্ট করে না। সাপোর্ট চেক করতে @supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) ব্যবহার করুন এবং যেসব ব্রাউজারে এটি কাজ করে না সেগুলির জন্য একটি ফলব্যাক প্রদান করুন।
    • শুধুমাত্র আংশিক সহায়তা প্রদানকারী ব্রাউজার ফিল্টার করতে, এখানে (animation-range: 0% 100%) চেক অবশ্যই অন্তর্ভুক্ত করতে হবে।
    • ফলব্যাক স্ট্র্যাটেজির জন্য scroll-timeline-polyfill প্যাকেজ ব্যবহার করবেন না কারণ এটিতে সব ফিচার নেই এবং অনেক পরিচিত সমস্যা আছে।
    • অ্যানিমেশনটি যদি শুধুমাত্র আলংকারিক হিসেবে বিবেচিত হয়, তাহলে প্রোগ্রেসিভ এনহ্যান্সমেন্ট বেছে নিন এবং ফলব্যাক প্রদান করবেন না।
  • ব্যবহারকারীর পছন্দকে সম্মান করুন: কিছু ব্যবহারকারী ওয়েবে কম মোশন পছন্দ করেন। এইসব ব্যবহারকারীর জন্য আপনার অ্যানিমেশন বন্ধ করতে বা কমাতে prefers-reduced-motion মিডিয়া কোয়েরি ব্যবহার করুন।
  • শুধুমাত্র পারফর্ম্যান্ট CSS প্রপার্টি অ্যানিমেট করার চেষ্টা করুন: সবচেয়ে মসৃণ অ্যানিমেশনের জন্য, ব্রাউজারের কম্পোজিটর থ্রেড দ্বারা ম্যানেজ করা যায় এমন প্রপার্টি অ্যানিমেট করুন, যেমন transform এবং opacity। width বা height-এর মতো অন্যান্য প্রপার্টি অ্যানিমেট করলে পারফর্ম্যান্স সংক্রান্ত সমস্যা হতে পারে।
  • সঠিক ডিক্লারেশন অর্ডার ব্যবহার করুন: animation শর্টহ্যান্ড প্রপার্টি ব্যবহার করার সময়, শর্টহ্যান্ড যাতে টাইমলাইন রিসেট না করে দেয় তার জন্য animation-timeline এবং animation-range এর পরে ডিক্লেয়ার করুন।

স্ক্রল-চালিত অ্যানিমেশন তৈরি করতে scroll() ফাংশন ব্যবহার করার সময়:

  • ঐচ্ছিক স্ক্রলার সম্পর্কে স্পষ্ট হোন: নিকটতম অ্যানসেস্টর স্ক্রলারকে টার্গেট না করার সময়, আপনি scroll(root) বা scroll(self)-এর সাথে কোন স্ক্রলার ব্যবহার করতে চান সে সম্পর্কে স্পষ্ট হোন।
    • root, nearest বা self যথেষ্ট না হলে, নামযুক্ত স্ক্রল-টাইমলাইন ব্যবহার করুন।
  • ঐচ্ছিক ট্র্যাক করার জন্য অক্ষ সম্পর্কে স্পষ্ট হোন: ডিফল্ট block অক্ষকে টার্গেট না করার সময় (যেমন অনুভূমিক স্ক্রোলারে), scroll(block) বা scroll(inline)-এর মাধ্যমে কোন অক্ষ ট্র্যাক করতে হবে সে সম্পর্কে স্পষ্ট হোন।

বিশেষ করে এই ব্যবহারের ক্ষেত্রে:

  • animation-range-এ শতাংশ ব্যবহার করার সময় আপনি যে এলিমেন্ট অ্যানিমেট করেন সেটি position: static বা position: relative হলে চলবে না।
    • কারণ, এইসব এলিমেন্টকে "ইন-ফ্লো" হিসেবে বিবেচনা করা হয়। স্ক্রল করার সময় এইসব এলিমেন্ট ছোট করলে, মোট স্ক্রল করার দূরত্ব কমে যাবে, যার ফলে স্ক্রল করার সময় — যেমন — 10%-এর গণনা করা ভ্যালু প্রভাবিত হবে।

ব্রাউজার সাপোর্ট ও ফলব্যাক স্ট্র্যাটেজি

তাই, সাধারণত একটি ফলব্যাক স্ট্র্যাটেজি প্রয়োজন হয়।

যেসব ব্রাউজারে স্ক্রল-চালিত অ্যানিমেশন কাজ করে না, সেখানে ভিজ্যুয়াল এফেক্ট আবার তৈরি করতে আপনি ফলব্যাক ব্যবহার করতে পারেন। ফলব্যাক সাধারণত স্ক্রল লিসেনার (ScrollTimeline এফেক্টের জন্য) বা IntersectionObserver API (ViewTimeline এফেক্টের জন্য) দিয়ে তৈরি করা হয়।

স্ক্রল-চালিত অ্যানিমেশনের জন্য বিল্ট-ইন সাপোর্ট সহ ব্রাউজারে, সর্বদা নেটিভ CSS ইমপ্লিমেন্টেশন ব্যবহার করুন কারণ সেগুলি আরও বেশি পারফর্ম্যান্স দেয়।

মনে রাখবেন, ফলব্যাক অ্যাপ্রোচ ব্যবহার করে সব এফেক্ট আবার তৈরি করা যায় না।

বিশেষ করে এই ব্যবহারের ক্ষেত্রে, স্ক্রল-চালিত অ্যানিমেশন কাজ করে না এমন ব্রাউজারের জন্য নিম্নলিখিত স্ক্রিপ্ট ফলব্যাক প্রয়োগ করে। এটি 150px দূরত্বের উপর ডকুমেন্টের স্ক্রল পজিশন ট্র্যাক করতে স্ক্রল লিসেনার ব্যবহার করে এবং সেই অনুযায়ী হেডারের উচ্চতা আপডেট করে।

// Fallback for browsers that don't support scroll-driven animations
if (!CSS.supports('(animation-timeline: scroll()) and (animation-range: 0% 100%)')) {
  const header = document.querySelector('header');

  const initialHeight = 200;
  const finalHeight = 50;
  const scrollDistance = 150;

  window.addEventListener('scroll', () => {
    const scrollY = window.scrollY;
    const scrollPercent = Math.min(1, scrollY / scrollDistance);
    const newHeight = initialHeight - (initialHeight - finalHeight) * scrollPercent;

    header.style.height = `${newHeight}px`;
  });
}