স্ক্রল-স্টেট কন্টেনার কোয়েরি আপনাকে বর্তমান স্ক্রল স্টেটের উপর ভিত্তি করে এলিমেন্ট স্টাইল করার সুবিধা দেয়, যেমন কোনও এলিমেন্ট "আটকে" (স্টিকি পজিশনিংয়ের মাধ্যমে) বা "স্ন্যাপ" (স্ক্রল স্ন্যাপিংয়ের মাধ্যমে) করা আছে কিনা। এটি ক্যারোজেল বা গ্যালারির অভিজ্ঞতা প্রদান করে যেখানে জাভাস্ক্রিপ্ট ইন্টারসেকশন অবজারভার বা স্ক্রল ইভেন্ট লিসনারের উপর নির্ভর না করেই অ্যাক্টিভ আইটেমটি ভিজ্যুয়ালি আলাদা করা যায়।
কোর ইমপ্লিমেন্টেশন
স্ন্যাপ করা আইটেম হাইলাইট করতে, আপনাকে অবশ্যই একটি স্ক্রল-স্ন্যাপ কন্টেনার তৈরি করতে হবে, স্ন্যাপ টার্গেটকে স্ক্রল-স্টেট কন্টেনার হিসেবে সংজ্ঞায়িত করতে হবে এবং তারপরে ডিসেন্ডেন্ট স্টাইল করার জন্য সেই স্টেট কোয়েরি করতে হবে।
১. স্ক্রল স্ন্যাপ কন্টেনার তৈরি করুন
মূল কন্টেনারে অবশ্যই scroll-snap-type চালু থাকতে হবে।
<div class="carousel">
<div class="carousel-item">
<div class="card">Product 1 content</div>
</div>
<div class="carousel-item">
<div class="card">Product 2 content</div>
</div>
</div>
.carousel {
display: flex;
overflow-x: auto;
/* MANDATORY: Enable scroll snapping on the container */
scroll-snap-type: x mandatory;
}
২. স্ক্রল-স্টেট কন্টেনার হিসেবে স্ন্যাপ টার্গেট সংজ্ঞায়িত করুন
স্ন্যাপ করার জন্য ট্র্যাক করা উচিত এমন ক্যারোজেলের প্রতিটি আইটেমকে scroll-state কন্টেনার হিসেবে ঘোষণা করতে হবে।
.carousel-item {
/* Define where the item snaps within the container */
scroll-snap-align: center;
/* MANDATORY: Establish this element as a scroll-state query container */
container-type: scroll-state;
}
৩. snapped-এর অবস্থা সম্পর্কে কোয়েরি করুন
যেহেতু কন্টেনার কোয়েরি স্টাইল ডিসেন্ডেন্ট, তাই আপনাকে স্ন্যাপ টার্গেটের ভেতরে কোনও এলিমেন্টে হাইলাইট স্টাইল প্রয়োগ করতে হবে। স্ক্রল কন্টেনার x অ্যাক্সিসে ওভারফ্লো করার জন্য সেট করা আছে, তাই scroll-state(snapped: x) কোয়েরি ব্যবহার করুন।
বাধ্যতামূলক: @media (prefers-reduced-motion: no-preference)-এ স্টাইল র্যাপ করুন যাতে শুধুমাত্র সেইসব ব্যবহারকারীকে এফেক্ট দেখানো হয় যারা রিডিউসড মোশনের অনুরোধ করেননি। আপনার ব্যবহারের উপর নির্ভর করে, আপনি এফেক্টের কিছু অংশ রেখে দিতে পারেন, তবে এই ক্ষেত্রে, কার্ডগুলি সাদা থেকে নীল রঙে এমনভাবে ফ্ল্যাশ করে যা কিছু ব্যবহারকারীর জন্য সমস্যা সৃষ্টি করতে পারে, তাই আমরা এটি সম্পূর্ণভাবে বন্ধ করে দিই।
/* Specify transition outside of queries so that it is applied regardless of state. */
.card {
transition:
scale 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),
background-color 0.4s,
color 0.4s,
box-shadow 0.4s;
}
/*
Only show the effect for users not requesting reduced motion. Disable completely, including the color change, as it causes a flash that may be problematic.
*/
@media (prefers-reduced-motion: no-preference) {
/* Style the content when its parent .carousel-item is snapped on the x axis */
@container scroll-state(snapped: x) {
.card {
background: #007bff;
color: white;
scale: 1.15;
box-shadow: 0 10px 25px rgba(0, 123, 255, 0.3);
}
}
}
/* MANDATORY Copy-Paste Safety: Disable highlight scaling/flashing for motion sensitive users */
@media (prefers-reduced-motion: reduce) {
.card {
transition: none !important;
scale: 1 !important;
}
}
snapped ডেসক্রিপ্টর নির্দিষ্ট অক্ষ কোয়েরি করতে পারে: x, y, inline, block বা both।
অ্যাক্সেসিবিলিটি
AVOID: ইন্টার্যাক্টিভ এলিমেন্টের সাথে scroll-state ব্যবহার করা।
স্ন্যাপ করা আইটেমের জন্য ভিজ্যুয়াল হাইলাইট UX উন্নত করতে পারে, তবে স্ন্যাপ করা আইটেম অ্যাক্সেসিবিলিটি ট্রিতে দেখানো হয় না। স্ন্যাপ করা আইটেমে প্রয়োগ করা ভিজ্যুয়াল থিম থেকে যেন বোঝা না যায় যে এলিমেন্টটি অ্যাক্টিভ বা ফোকাস করা আছে এবং কীবোর্ড ফোকাস রিং যেন খুব ভালোভাবে দেখা যায় এবং snapped হাইলাইট থেকে আলাদা হয়। স্ন্যাপ করা আইটেমটি ইন্টার্যাক্টিভ হলে, এটি অ্যাক্সেসযোগ্য করার জন্য আপনাকে অবশ্যই অন্যান্য স্ট্যান্ডার্ড অ্যাক্সেসিবিলিটি পদ্ধতি ব্যবহার করতে হবে।
স্ক্রল করার কারণে স্ন্যাপিং হয়, যা কীবোর্ড ফোকাসকে সরায় না। তবে, কীবোর্ড ফোকাসের কারণে স্ক্রল কন্টেনারটি সরে যেতে পারে, যার ফলে স্ন্যাপ করা আইটেমে পরিবর্তন হতে পারে, যা ফোকাস করা আইটেম হতেও পারে আবার নাও হতে পারে। এটি ব্যবহারকারীদের বিভ্রান্ত করতে পারে এবং এটি করা থেকে বিরত থাকতে বলা হচ্ছে।
ফলব্যাক স্ট্র্যাটেজি
যেসব ব্রাউজারে স্ক্রল-স্টেট কোয়েরি কাজ করে না, সেগুলির ক্ষেত্রে আপনাকে এমন একটি ফাংশনাল বেস অভিজ্ঞতা প্রদান করতে হবে যেখানে "অ্যাক্টিভ" হাইলাইট না থাকলেও সব আইটেম পড়া যায়।
ফিচার শনাক্তকরণ
আপনি শুধুমাত্র কাজ করে এমন ব্রাউজারে উন্নত অভিজ্ঞতা প্রদান করতে @supports ব্যবহার করতে পারবেন:
@supports (container-type: scroll-state) {
/* Enhancement styles here */
}
জাভাস্ক্রিপ্ট ফলব্যাক
ব্যবহারকারীর অভিজ্ঞতার জন্য হাইলাইট করা গুরুত্বপূর্ণ হলে, স্ন্যাপ করা আইটেম নির্ধারণ করতে IntersectionObserver ব্যবহার করুন। নেগেটিভ ইনলাইন ভ্যালু সহ rootMargin প্রদান করে ক্যারোজেলের কেন্দ্রে একটি পাতলা স্লাইসে পর্যবেক্ষণ করা এলাকা অ্যাডজাস্ট করুন। যেমন, ক্যারোজেলের মাঝখানে ২% থাকলে কোনও এলিমেন্টকে ইন্টারসেক্ট করছে বলে বিবেচনা করতে, rootMargin-কে "0px -49%"-এ সেট করুন।
// Optional: detect support and apply a JS-based fallback
if (!CSS.supports('container-type', 'scroll-state')) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
// Toggle a class based on intersection
entry.target.classList.toggle('is-snapped', entry.isIntersecting);
});
}, {
root: document.querySelector(".carousel"),
// Carousel item intersects if any part of the carousel item is in the middle 2% of the carousel.
rootMargin: "0px -49%"
});
document.querySelectorAll('.carousel-item').forEach(item => {
observer.observe(item);
});
}