প্রকাশিত: ২৭ মার্চ, ২০২৬
এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন একাধিক ভিউ ট্রানজিশনকে একই সাথে চালাতে দেয়, চলমান ভিউ ট্রানজিশনকে অন্যটির মধ্যে নেস্ট করার সুযোগ দেয় এবং ডকুমেন্ট-স্কোপড ভিউ ট্রানজিশনের ক্ষেত্রে সম্মুখীন হতে পারে এমন z-index সমস্যার সমাধান করে—এই সবকিছুই পৃষ্ঠার বাকি অংশকে ইন্টারেক্টিভ রেখেই করা যায়। এগুলো কীভাবে ব্যবহার করতে হয় তা জানতে এই নির্দেশিকাটি পড়ুন।
আরও সংকীর্ণ পরিসরের দৃশ্য পরিবর্তনের প্রয়োজনীয়তা
যখন আপনি document.startViewTransition() (অথবা এর ক্রস-ডকুমেন্ট প্রতিরূপের মাধ্যমে) একই-ডকুমেন্ট ভিউ ট্রানজিশন শুরু করেন, তখন ব্রাউজার ফলস্বরূপ ভিউ ট্রানজিশনটিকে সেই ডকুমেন্টের মধ্যেই সীমাবদ্ধ করে।
আপডেট কলব্যাকটি কার্যকর হওয়ার পর এবং ব্রাউজার সমস্ত প্রয়োজনীয় এলিমেন্টের স্ন্যাপশট নেওয়ার পরে, ফলস্বরূপ ::view-transition ওভারলে এবং এর সিউডো-এলিমেন্টগুলোর ট্রি নিচের উদাহরণে html মতো :root এলিমেন্টের সাথে সংযুক্ত হয়।
html
├─ ::view-transition
│ └─ ::view-transition-group(root)
│ └─ ::view-transition-image-pair(root)
│ ├─ ::view-transition-old(root)
│ └─ ::view-transition-new(root)
├─ head
└─ body
└─ …
যেহেতু ::view-transition লেয়ারটি ট্রানজিশন রুটের উপরে রেন্ডার হয়, তাই এর ফলে অপ্রত্যাশিত পরিস্থিতি তৈরি হতে পারে। উদাহরণস্বরূপ, ভিউ ট্রানজিশনে অংশগ্রহণকারী এলিমেন্টগুলো হঠাৎ করে অন্যান্য অংশগ্রহণকারী নয় এমন এলিমেন্টের উপর ওভারল্যাপ করতে পারে, অথবা ভিউ ট্রানজিশন চলাকালীন এলিমেন্টগুলো তাদের অ্যানসেস্টর র্যাপার দ্বারা আর ক্লিপড নাও থাকতে পারে।
লাইভ ডেমো
ডেমো রেকর্ডিং
::view-transition এ pointer-events পুনরায় সক্রিয় করা অথবা নেস্টেড ভিউ ট্রানজিশন গ্রুপ ব্যবহার করা, ডকুমেন্ট-স্কোপড ভিউ ট্রানজিশনের কারণে সৃষ্ট কিছু পার্শ্বপ্রতিক্রিয়া সমাধান করতে পারে। তবে, এই পদ্ধতিগুলো সব সমস্যার সমাধান করতে পারে না।
উদাহরণস্বরূপ, position: fixed যুক্ত এলিমেন্ট বা পপওভারগুলো একটি ডকুমেন্ট-স্কোপড ভিউ ট্রানজিশন সক্রিয় থাকা অবস্থায়ও তার দ্বারা আড়াল হয়ে যায় — যা z-index সমস্যা নামেও পরিচিত।
নিচের ডেমোতে পপওভারটি টগল করুন এবং তারপর একটি ডকুমেন্ট-স্কোপড ভিউ ট্রানজিশন শুরু করতে শাফেল বাটনটি সিলেক্ট করুন। নেস্টেড ভিউ ট্রানজিশন গ্রুপগুলো ক্লিপিং সমস্যার সমাধান করে, কিন্তু লেয়ারিং সমস্যাটি থেকেই যায়।
লাইভ ডেমো
ডেমো রেকর্ডিং
এর একটি সমাধান হলো, popover একটি view-transition-name দিয়ে ভিউ ট্রানজিশনের অংশ হিসেবে ক্যাপচার করা। যদিও এটি একটিমাত্র ইনস্ট্যান্সের জন্য কাজ করতে পারে, তবে এর রক্ষণাবেক্ষণ বেশ কষ্টসাধ্য এবং এটি অপ্রয়োজনীয়ভাবে স্ন্যাপশট নেওয়ার প্রক্রিয়ার উপর চাপ সৃষ্টি করে।
এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন
এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন আপনাকে DOM-এর একটি সাবট্রি থেকে ভিউ ট্রানজিশন শুরু করার সুযোগ দেয়। document.startViewTransition() কল করার পরিবর্তে, আপনি যেকোনো একটি এলিমেন্টের উপর element.startViewTransition() কল করেন, যা ভিউ ট্রানজিশনটিকে সেই এলিমেন্টের মধ্যেই সীমাবদ্ধ করে দেয়।
নিম্নলিখিত কোড অংশে, ব্রাউজারটি <ul> এলিমেন্টের উপর একটি এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন শুরু করে।
document.querySelector('ul').startViewTransition({
callback: () => {
// … code that manipulates the contents of <ul>
},
})
যে এলিমেন্টের মধ্যে আপনি element.startViewTransition() কল করেন —উদাহরণস্বরূপ <ul> —তাকে ট্রানজিশন রুট বা স্কোপ বলা হয়।
যখন ব্রাউজার কোনো এলিমেন্টে ভিউ ট্রানজিশন সীমাবদ্ধ করে, তখন সেটি DOM-এর বাকি অংশ থেকে বিচ্ছিন্ন থাকে:
- ব্রাউজারটি শুধুমাত্র স্কোপের সাবট্রির মধ্যেই স্ন্যাপশট নেওয়ার জন্য এলিমেন্টগুলো খুঁজে থাকে।
- স্ন্যাপশট নেওয়ার প্রক্রিয়া চলাকালীন—যখন
updateকলব্যাকটি কার্যকর হয়—শুধুমাত্র স্কোপের রেন্ডারিং থেমে যায়। - ফলস্বরূপ
::view-transitionসিউডো-ট্রিটি ট্রানজিশন রুটে ইনজেক্ট করা হয়।
উদাহরণস্বরূপ, <ul> এর ক্ষেত্রে, ভিউ ট্রানজিশন সক্রিয় থাকাকালীন DOM ট্রি দেখতে এইরকম হয়:
html
├─ head
└─ body
├─ ul
│ ├─ ::view-transition
│ │ └─ ::view-transition-group(root)
│ │ ├─ ::view-transition-group-children(root)
│ │ │ └─ …
│ │ └─ ::view-transition-image-pair(root)
│ │ ├─ ::view-transition-old(root)
│ │ └─ ::view-transition-new(root)
│ ├─ li
│ ├─ li
│ └─ li
├─ button#showpopover
├─ button#reorder
└─ div#popover
└─ p
::view-transition সিউডো-এর আকার ও আকৃতি ট্রানজিশন রুটের সমান এবং এটি শুধুমাত্র ট্রানজিশন রুটের উপরেই রেন্ডার হয়। এই কারণে, ট্রানজিশন রুটের বাইরের এলিমেন্টগুলোর স্তরবিন্যাস অক্ষুণ্ণ থাকে।
উদাহরণস্বরূপ, যদি আপনার <ul> এলিমেন্টের উপরে একটি পপওভার দৃশ্যমান থাকে এবং তারপর আপনি <ul> এলিমেন্টটিতে একটি এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন শুরু করেন, তাহলে পপওভারটি ভিউ ট্রানজিশনের সিউডো-ট্রি দ্বারা আবৃত হয় না।
নিচের ডেমোটিতে এটি চেষ্টা করে দেখুন। এতে দুটি বাটন আছে। প্রথম বাটনটি পপওভারটি টগল করে এবং দ্বিতীয় বাটনটি একটি এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন ব্যবহার করে তালিকার আইটেমগুলোর ক্রম পরিবর্তন করে।
লাইভ ডেমো
ডেমো রেকর্ডিং
এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন ব্যবহার করার কারণে, ট্রানজিশনটি সক্রিয় থাকা অবস্থায় পপওভারটি <ul> এলিমেন্টের উপরে দৃশ্যমান থাকে।
তাছাড়া, <ul> এলিমেন্টের বাইরের উপাদানগুলো—যেমন বাটনগুলো—ইন্টারেক্টিভ থাকে, কারণ সেই উপাদানগুলো স্কোপের অংশ নয়।
স্ব-অংশগ্রহণকারী স্কোপ এবং নেস্টেড ভিউ ট্রানজিশন গ্রুপ
যখন আপনি এমন কোনো এলিমেন্টে এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন শুরু করেন যার ওভারফ্লো ক্লিপ করা থাকে (অর্থাৎ, যখন এর overflow hidden , scroll , বা clip এ সেট করা থাকে), তখন আপনি লক্ষ্য করবেন যে ভিউ ট্রানজিশনের বিষয়বস্তু দৃশ্যত ক্লিপ হয়ে থাকে।
এর কারণ হলো, এলিমেন্ট-স্কোপড ভিউ ট্রানজিশনগুলো নিম্নলিখিত বিষয়গুলো স্বয়ংক্রিয়ভাবে পরিচালনা করে:
- স্কোপটিতে স্বয়ংক্রিয়ভাবে
view-transition-name: rootপ্রয়োগ হয়ে যায়, যা এটিকে সেলফ-পার্টিসিপেটিং করে তোলে। - নেস্টেড ভিউ ট্রানজিশন গ্রুপ সক্রিয় করতে স্কোপটিতে স্বয়ংক্রিয়ভাবে
view-transition-group: containপ্রয়োগ করা হয়। - ফলস্বরূপ
::view-transition-group-children(root)সিউডোটি স্বয়ংক্রিয়ভাবেoverflow: clipব্যবহার করে তার বিষয়বস্তু ক্লিপ করে, যদি স্কোপ রুট তার ওভারফ্লো ক্লিপ করে, যা সিউডোগুলোকে ট্রানজিশন রুটের বাইরে দৃশ্যত ছড়িয়ে পড়া থেকে বিরত রাখে।
এর ফলে, আপনি এলিমেন্ট-স্কোপড ভিউ ট্রানজিশনের সাথে ব্যবহৃত CSS-কে শুধুমাত্র সেই এলিমেন্টগুলোর উপরই কেন্দ্রীভূত রাখতে পারেন যা আপনি ক্যাপচার করতে চান। উদাহরণস্বরূপ, লিস্ট ডেমোতে, CSS শুধুমাত্র লিস্ট আইটেমগুলোতে নাম যোগ করে:
ul li {
view-transition-name: match-element;
view-transition-class: album;
}
নিচের ডেমোতে এটি পরীক্ষা করে দেখুন। এটি আপনাকে সেলফ-পার্টিসিপেশন ওভাররাইড করার সুযোগ দেয়। যখন স্কোপটি সেলফ-পার্টিসিপেটিং থাকে (যা ডিফল্ট আচরণ), তখন সবকিছু প্রত্যাশিতভাবেই কাজ করে। যখন স্কোপটি সেলফ-পার্টিসিপেটিং থাকে না, তখন এর বর্ডার সাথে সাথে পরিবর্তিত হয়ে যায় এবং ট্রানজিশনের সময় এর ভেতরের কন্টেন্ট র্যাপারের বাইরে বেরিয়ে আসে।
লাইভ ডেমো
ডেমো রেকর্ডিং
তথ্যসূত্র হিসেবে, সেলফ-পার্টিসিপেশন সহ এই ডেমোর সিউডো-ট্রি-টি দেখতে এইরকম:
html
├─ head
└─ body
├─ ul
│ ├─ ::view-transition
│ │ └─ ::view-transition-group(root)
│ │ ├─ ::view-transition-group-children(root)
│ │ │ ├─ ::view-transition-group(item1)
│ │ │ │ └─ ::view-transition-image-pair(item1)
│ │ │ │ ├─ ::view-transition-old(item1)
│ │ │ │ └─ ::view-transition-new(item1)
│ │ │ ├─ ::view-transition-group(item2)
│ │ │ │ └─ …
│ │ │ …
│ │ └─ ::view-transition-image-pair(root)
│ │ ├─ ::view-transition-old(root)
│ │ └─ ::view-transition-new(root)
│ ├─ li
│ ├─ li
│ └─ li
└─ button#reorder
যেহেতু ট্রানজিশন রুট, অর্থাৎ <ul> এলিমেন্টটি, তার ভেতরের বিষয়বস্তুকে উল্লম্বভাবে ছেঁটে ফেলে, তাই ::view-transition-group-children(root) ফাংশনটিও স্বয়ংক্রিয়ভাবে একটি ক্লিপ প্রয়োগ করে।
একই সাথে উপাদান-ভিত্তিক ভিউ পরিবর্তন
যেহেতু এলিমেন্ট-স্কোপড ভিউ ট্রানজিশনগুলো বিচ্ছিন্নভাবে চলে, তাই একাধিক এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন একই সাথে চলতে পারে, যদি তাদের স্কোপ ভিন্ন হয়।
নিম্নলিখিত ডেমোটিতে দুটি রিঅর্ডার বাটন রয়েছে, প্রতিটি লিস্টের জন্য একটি করে। প্রতিটি বাটন শুধুমাত্র তার নিজ নিজ লিস্টে একটি এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন শুরু করে। যেহেতু উভয় লিস্টের DOM ট্রি একে অপরের সাথে ওভারল্যাপ করে না, তাই দুটি এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন আলাদাভাবে এবং একই সাথে চলতে পারে।
লাইভ ডেমো
ডেমো রেকর্ডিং
এই বিচ্ছিন্ন বৈশিষ্ট্যটি আপনাকে বিভিন্ন স্কোপ জুড়ে view-transition-name ভ্যালুগুলো পুনরায় ব্যবহার করার সুযোগ দেয়। যতক্ষণ একটি নাম তার স্কোপের মধ্যে অনন্য থাকে, ততক্ষণ কোনো দ্বন্দ্ব হয় না।
নেস্টেড এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন এবং ভিউ-ট্রানজিশন-নাম ধারণ
যখন একাধিক এলিমেন্ট-স্কোপড ভিউ ট্রানজিশনের DOM ট্রি একে অপরের উপর এসে পড়ে, view-transition-name ভ্যালুর সংঘর্ষের ঝুঁকি থাকে। এই কারণে, এই ঝুঁকি প্রশমিত করার জন্য ব্রাউজার সক্রিয় এলিমেন্ট-স্কোপড ভিউ ট্রানজিশনগুলোতে স্বয়ংক্রিয়ভাবে view-transition-scope: all অ্যাসাইন করে দেয়।
যেভাবে anchor-scope , anchor-name ভ্যালুগুলোকে স্কোপ করে, ঠিক একইভাবে view-transition-scope প্রপার্টিটি নিশ্চিত করে যে view-transition-name ভ্যালুগুলো এলিমেন্টের সাবট্রি-এর মধ্যেই সীমাবদ্ধ থাকবে। এই প্রপার্টিটি none , অর্থাৎ যে নামগুলোকে স্কোপ করতে চান তার একটি তালিকা, অথবা সমস্ত ভ্যালুকে স্কোপ করার জন্য all গ্রহণ করে।
নাম বাইরে চলে যাওয়া রোধ করার পাশাপাশি, view-transition-scope একটি এলিমেন্ট এবং তার ভেতরের বিষয়বস্তুকে বাইরের, একই সময়ে চলমান কোনো ভিউ ট্রানজিশন দ্বারা ক্যাপচার হওয়া থেকেও প্রতিরোধ করে। যখন স্ন্যাপশট নেওয়ার প্রক্রিয়াটি স্ন্যাপশট করার জন্য কোনো এলিমেন্ট খুঁজতে সাবট্রি ট্র্যাভার্স করে, তখন এটি সেইসব এলিমেন্টকে (এবং তাদের সম্পূর্ণ সাবট্রিকে) উপেক্ষা করে যেগুলোতে view-transition-scope: all প্রয়োগ করা আছে। এর মাধ্যমে ধরে নেওয়া হয় যে, ওই এলিমেন্টগুলো ইতিমধ্যেই অন্য কোনো এলিমেন্ট-স্কোপড ভিউ ট্রানজিশনে অংশগ্রহণ করছে।
নিম্নলিখিত ডেমোটি পূর্ববর্তীটির একটি পরিবর্তিত রূপ। তালিকার বিষয়বস্তু এলোমেলো করার দুটি বোতাম ছাড়াও, এতে তালিকা অদলবদল করার জন্য একটি 'সোয়াপ' বোতামও রয়েছে। #lists-wrapper এ একটি .reversed ক্লাস টগল করার মাধ্যমে এই অদলবদলের কাজটি সম্পন্ন হয়।
লাইভ ডেমো
ডেমো রেকর্ডিং
যেহেতু শাফেল ট্রানজিশনের সময় view-transition-scope: all স্বয়ংক্রিয়ভাবে প্রয়োগ হয়, তাই শাফেল ট্রানজিশনটি চলমান থাকা অবস্থাতেও আপনি একটি সমান্তরাল, বাইরের সোয়াপ ট্রানজিশন শুরু করতে পারেন।
যেহেতু view-transition-scope: all বাইরের ট্রানজিশনে কোনো এলিমেন্টের স্ন্যাপশট হওয়াও প্রতিরোধ করে, তাই ডেমোটি <ul> এলিমেন্টগুলোকে ঘিরে থাকা এলিমেন্টগুলোতেও view-transition-name ভ্যালু যোগ করে।
#list1-wrapper, #list2-wrapper {
view-transition-name: attr(id type(<custom-ident>));
}
এই ডেমোর জন্য সিউডো-ট্রি-টি, দ্বিতীয় লিস্টে শাফেল শুরু করার পর এবং তারপর উভয় লিস্ট অদলবদল করার পরে, দেখতে এইরকম হয়:
html
├─ head
└─ body
└─ #lists-wrapper.reversed (SCOPE)
├─ ::view-transition
│ └─ ::view-transition-group(lists-wrapper)
│ ├─ ::view-transition-group-children(lists-wrapper)
│ │ ├─ ::view-transition-group(list1-wrapper)
│ │ │ └─ ::view-transition-image-pair(list1-wrapper)
│ │ │ ├─ ::view-transition-old(list1-wrapper)
│ │ │ └─ ::view-transition-new(list1-wrapper)
│ │ └─ ::view-transition-group(list2-wrapper)
│ │ └─ ::view-transition-image-pair(list2-wrapper)
│ │ ├─ ::view-transition-old(list2-wrapper)
│ │ └─ ::view-transition-new(list2-wrapper)
│ └─ ::view-transition-image-pair(lists-wrapper)
│ ├─ ::view-transition-old(lists-wrapper)
│ └─ ::view-transition-new(lists-wrapper)
├─ div#list1-wrapper
│ ├─ ul
│ │ ├─ li#item1
│ │ ├─ li#item2
│ │ └─ li#item3
│ └─ button.reorder
└─ div#list2-wrapper
├─ ul (SCOPE)
│ ├─ ::view-transition
│ │ └─ ::view-transition-group(list)
│ │ ├─ ::view-transition-group-children(list )
│ │ │ ├─ ::view-transition-group(item4)
│ │ │ │ └─ ::view-transition-image-pair(item4)
│ │ │ │ ├─ ::view-transition-old(item4)
│ │ │ │ └─ ::view-transition-new(item4)
│ │ │ ├─ ::view-transition-group(item5)
│ │ │ │ └─ …
│ │ │ …
│ │ └─ ::view-transition-image-pair(list)
│ │ ├─ ::view-transition-old(list)
│ │ └─ ::view-transition-new(list)
│ ├─ li#item4
│ ├─ li#item5
│ └─ li#item6
└─ button.reorder
আরও জানুন
এলিমেন্ট-স্কোপড ভিউ ট্রানজিশন সম্পর্কে আরও জানতে, এক্সপ্লেনার , css-view-transitions-2 স্পেসিফিকেশন এবং ওপেন স্পেক এডিটের তালিকা দেখুন।