এক নজরে
মোডাল ও নন-মোডাল ডায়ালগের জন্য নেটিভ <dialog> এলিমেন্ট ব্যবহার করুন। এটি অ্যাক্সেসিবিলিটি সিম্যান্টিক্স, ফোকাস হ্যান্ডলিং, টপ-লেয়ার রেন্ডারিং এবং Esc হ্যান্ডলিং প্রদান করে যা কাস্টম ওভারলেকে ম্যানুয়ালি আবার তৈরি করতে হয়।
ওভারলের ধরন বেছে নিন
প্রথম যে নিয়মটি ম্যাচ করে সেটি বেছে নিন। নিশ্চিত না হলে, নিয়ম ১ ব্যবহার করুন।
নিয়ম ১: ওভারলে ব্যবহারকারীকে বাধা দেয় এবং পৃষ্ঠা ব্লক করে (ডিফল্ট)
কনফার্মেশন, ফর্ম, সাইন-ইন, ধ্বংসাত্মক অ্যাকশন এবং অন্য কোনও "মডেল", "ডায়ালগ", "লাইটবক্স" বা "পপ-আপ" অনুরোধের জন্য ব্যবহার করুন যা অন্য কিছু বলে না।
<dialog> ব্যবহার করুন যা মোডাল হিসেবে খোলা হয়েছে, command="show-modal"-এর সাথে ডিক্লারেটিভভাবে (ডিক্লারেটিভ ডায়ালগ ও পপওভার কন্ট্রোল দেখুন) অথবা showModal()-এর সাথে স্ক্রিপ্ট থেকে।
<button type="button" command="show-modal" commandfor="confirm">Delete</button>
<!-- MANDATORY: no role="dialog" or aria-modal; the native modal already provides them -->
<dialog id="confirm" aria-labelledby="confirm-title">
<h2 id="confirm-title">Delete this item?</h2>
<form method="dialog">
<button value="cancel" autofocus>Cancel</button>
<button value="delete">Delete</button>
</form>
</dialog>
ব্রাউজার এগুলি প্রদান করে: ইনার্ট পৃষ্ঠা, ফোকাস কন্টেনমেন্ট, উপরের লেয়ার, ::backdrop, Esc এবং ব্যাক-জেসচার ডিসমিসাল এবং ইনভোকারে ফোকাস রিটার্ন।
role="dialog",aria-modal, ফোকাস ট্র্যাপ,inertটগলিং বাEscহ্যান্ডলার যোগ করবেন না।show()বাopenঅ্যাট্রিবিউট দিয়ে এটি খুলবেন না।- নিচের CSS ব্যবহার করে এর পিছনে পৃষ্ঠার স্ক্রলিং বন্ধ করুন। বিস্তারিত জানতে মোডাল ডায়ালগের নিচে থাকা পৃষ্ঠা স্ক্রল করা আটকান দেখুন।
htmlবাbody-এoverflow: hiddenবাposition: fixed-এর সাহায্যে স্ক্রলিং লক করবেন না।
/* MANDATORY (both rules): without them, scrolling over the backdrop or inside the dialog scrolls the page behind it */
dialog:modal {
overscroll-behavior: contain; /* stops scroll gestures in the dialog chaining to the page */
}
dialog::backdrop {
overflow: hidden; /* ::backdrop is not a scroll container by default, so it would ignore overscroll-behavior */
overscroll-behavior: contain;
}
মেনু বা টুলটিপের জন্য নয়: নিয়ম ৩ দেখুন।
নিয়ম ২: প্যানেল খোলা থাকাকালীন ব্যবহারকারী পৃষ্ঠায় কাজ করতে থাকেন
ফাইন্ড বার, ইন্সপেক্টর, প্যালেট এবং কম্পোজ পেনের জন্য ব্যবহার করুন যা এখনও শব্দার্থগতভাবে ডায়ালগ।
পপওভার ডিসমিসাল সহ টপ-লেয়ার প্যানেলের জন্য <dialog popover> ব্যবহার করুন (auto লাইট-ডিসমিস করে, manual করে না)। প্যানেলটি অবশ্যই উপরের লেয়ারে না থাকলে তবেই dialog.show() ব্যবহার করুন।
<button type="button" popovertarget="find">Find</button>
<dialog id="find" popover="manual" aria-labelledby="find-title">
<h2 id="find-title">Find</h2>
<input type="search" aria-label="Search">
<button type="button" popovertarget="find" popovertargetaction="hide">Close</button>
</dialog>
পৃষ্ঠাটি ইন্টার্যাক্টিভ থাকে এবং নিষ্ক্রিয় করা হয় না।
- বন্ধ করার বোতামটি যেন দেখা যায় তা নিশ্চিত করুন।
showModal()ব্যবহার করবেন না, এটি পৃষ্ঠা ব্লক করে দেয়।
কনফার্মেশন ব্লক করার জন্য নয়: নিয়ম ১ দেখুন।
নিয়ম ৩: ওভারলে কোনও ডায়ালগ নয়
মেনু, ড্রপডাউন, টুলটিপ, হোভারকার্ড ও টোস্টের জন্য ব্যবহার করুন।
popover অ্যাট্রিবিউটের সাথে একটি সিম্যান্টিক এলিমেন্ট ব্যবহার করুন, <dialog> নয়।
<button type="button" popovertarget="menu">Actions</button>
<ul id="menu" popover>
<li><a href="/rename">Rename</a></li>
</ul>
এটি কীভাবে বাতিল করা যাবে তা বেছে নিন
ডায়ালগ কীভাবে খোলা হয়েছে তার উপর ডিফল্ট নির্ভর করে। closedby অনুপস্থিত বা ভুল হলে, showModal(), closerequest-এর মতো কাজ করে এবং খোলার অন্য যেকোনও উপায় none-এর মতো কাজ করে।
- শুধু Esc এবং ফিরে যাওয়ার জেসচার (মোডাল ডিফল্ট): কিছু সেট করবেন না অথবা
closedby="closerequest"। - এছাড়াও, বন্ধ করতে বাইরে ক্লিক করুন:
closedby="any"ব্যবহার করুন। - শুধুমাত্র ডেভেলপার এটি বন্ধ করেন (যেমন, সেভ না করা পরিবর্তন সহ ফর্ম):
closedby="none"ব্যবহার করুন এবং কনফার্মেশন পাথ যোগ করুন। নিচে 'বন্ধ করা' দেখুন।
নির্দেশিকা
অ্যাক্সেসযোগ্য নাম এবং প্রারম্ভিক ফোকাস
aria-labelledby-এর মাধ্যমে প্রতিটি ডায়ালগের হেডিংয়ের দিকে ইঙ্গিত করে সেটির নাম দিন করুন অথবা কোনও দৃশ্যমান টাইটেল না থাকলেaria-label-এর মাধ্যমে নাম দিন।- প্রাইমারি কন্ট্রোল বা প্রথম ফিল্ডে
autofocusরাখুন। - করুন: ধ্বংসাত্মক কনফার্মেশনে নিরাপদ অ্যাকশনে (যেমন বাতিল করুন বা রাখুন)
autofocusরাখুন। - বন্ধ করার সময় ফোকাস ফিরিয়ে আনার জন্য কোড লিখবেন না। ব্রাউজার এটি ইনভোকারকে ফেরত দেয়।
খুলছে
<button>-এcommand="show-modal"এবংcommandfor-এর সাথে ডিক্লেরেটিভভাবে খুলুন। ডিক্লারেটিভ ডায়ালগ ও পপওভার কন্ট্রোল দেখুন।- স্ক্রিপ্ট থেকে খোলার সময়
dialog.showModal()ব্যবহার করুন।
বন্ধ হচ্ছে
<form method="dialog">বোতাম বাcommand="close"ব্যবহার করে বন্ধ করুন।- অবশ্যই
closedbyবেছে নিন:any(লাইট ডিসমিস ওEsc),closerequest(শুধুEsc, মোডাল ডিফল্ট) অথবাnone(শুধু ডেভেলপার-নিয়ন্ত্রিত বন্ধ করার বিকল্প)। - বাতিল করুন বোতামের জন্য
command="request-close"বাrequestClose()ব্যবহার করুন যা অবশ্যই সেভ না করা পরিবর্তন সংক্রান্ত লজিক মেনে চলে। তারা প্রথমেcancelট্রিগার করে এবংclosedbyউপেক্ষা করে। closedby-কে প্রোগ্রেসিভ এনহ্যান্সমেন্ট হিসেবে বিবেচনা করুন।Escএবং মোবাইল ব্যাক জেসচার এটি ছাড়াই আগে থেকে মোডাল বন্ধ করে দেয়।
বন্ধ করার জন্য হুক করা হচ্ছে
- কোন বোতাম ব্যবহার করা হয়েছে তা জানতে
closeলিসেনারেdialog.returnValueপড়ুন, তারপরdialog.returnValue = ''দিয়ে এটি রিসেট করুন।Escএবং অন্যান্য ক্লোজ অনুরোধ কোনও ভ্যালু সেট করে না এবং ব্রাউজারগুলি আগেরটি মুছে ফেলবে কিনা তা নিয়ে আলাদা আলাদা সিদ্ধান্ত নেয়, তাই রিসেট না করলে পুরনো ভ্যালু ফাঁস হতে পারে।''-কে "বেছে না নিয়েই বাতিল করা হয়েছে" হিসেবে বিবেচনা করুন। Escওrequest-closeইন্টারসেপ্ট করতেcancelব্যবহার করুন, তবে ইউজার অ্যাক্টিভেশন ছাড়া বারবারEscপ্রেস করার জন্যpreventDefault()-এর উপর নির্ভর করবেন না।- অবশ্যই ডার্টি ফর্মের জন্য স্পষ্ট কনফার্মেশন স্টেপ সহ
closedby="none"ব্যবহার করুন। cancelপ্রতিরোধ করা হলে ডায়ালগ কেন খোলা থাকে তা ব্যবহারকারীকে অবশ্যই জানান: একটি দৃশ্যমান মেসেজ দেখান এবং ফোকাস পায় এমন কন্ট্রোল (যেমন, বাতিল করুন) থেকেaria-describedbyদিয়ে এটি রেফারেন্স করুন, যাতে ফোকাস সরলে স্ক্রিন রিডার এটি পড়ে। এটি ছাড়া, ফোকাস নতুন বোতামে গেলে শুধু সেই বোতামের নাম ঘোষণা করা হয়।- পয়েন্টারের নিচে কনফার্মেশন মুভ কন্ট্রোল করবেন না। মেসেজের জন্য জায়গা রিজার্ভ করুন (
visibilityদিয়ে এটি লুকান,displayবাhiddenদিয়ে নয়) এবং এমন জায়গায় ডেস্ট্রাক্টিভ বোতাম যোগ করুন যেখানে আগে থেকে থাকা বোতামগুলি সরে যায় না (যেমন, ডানদিকে অ্যালাইন করা সারির প্রথম বোতাম), যাতে একই জায়গায় দ্বিতীয়বার ক্লিক করলে ব্যবহারকারীর করা পরিবর্তন বাতিল না হয়ে যায়।
নন-মডাল ডায়ালগ
- টপ-লেয়ার প্যানেলের জন্য
<dialog popover>(autoবাmanual) ব্যবহার করুন এবং টপ-লেয়ার না চাইলেdialog.show()ব্যবহার করুন। - অবশ্যই প্রতিটি নন-মডেল ডায়ালগে একটি দৃশ্যমান বন্ধ করার বোতাম অন্তর্ভুক্ত করুন।
ব্যাকড্রপ ও স্টাইলিং
- DO স্টাইল
::backdropএবং শুধুমাত্র মোডাল স্টাইল টার্গেট করতেdialog:modalব্যবহার করুন। - টপ লেয়ারে ও সেখান থেকে এলিমেন্ট অ্যানিমেট করা-এর জন্য অ্যানিমেশন, ড্র্যাগ করা যায় এমন এলিমেন্ট তৈরি করা-এর জন্য ড্র্যাগ করা এবং পারসিস্টেন্ট টপ লেয়ার UI-এর জন্য রিপ্যারেন্টিং করুন।
dialog-এdisplay-এর জন্য কোনও শর্ত ছাড়াই সেট করবেন না। এটি বন্ধ থাকা স্ট্যাটাসকে ওভাররাইড করে।dialog[open]-এর মাধ্যমে এটি স্কোপ করুন।
অ্যাক্সেসিবিলিটি
role="dialog",aria-modal, ম্যানুয়াল ফোকাস ট্র্যাপ বা নেটিভ মডেলেinertটগল করার সুবিধা যোগ করবেন না।- বন্ধ করার কন্ট্রোলের জন্য অ্যাক্সেসযোগ্য নাম সহ নেটিভ
<button>ব্যবহার করুন। - ডায়ালগ টাইটেলের জন্য একটি সামঞ্জস্যপূর্ণ হেডিং লেভেল ব্যবহার করুন।
ফলব্যাক স্ট্র্যাটেজি
closedby (dialog-closedby)
closedby ছাড়া, একটি মডেল এখনও Esc এবং ব্যাক জেসচারের মাধ্যমে বন্ধ হয়; শুধুমাত্র ক্লিক-আউটসাইড কাজ করে না, তাই এটি একটি গ্রেসফুল ডিগ্রেডেশন। closedby="none" একইভাবে উপেক্ষা করা হয়: Esc cancel ফায়ার করে এবং তারপর ডায়ালগ বন্ধ করে। সেভ-না-করা-পরিবর্তন গার্ডকে cancel হ্যান্ডলারে রাখুন, শুধু closedby="none"-এ নয়, যাতে এটি closedby না থাকলেও সুরক্ষিত রাখে। আপনার বেসলাইন টার্গেটে লাইট ডিসমিস প্রয়োজন হলে, যেখানে closedby নেই সেখানে এটি যোগ করুন:
if (!('closedBy' in HTMLDialogElement.prototype)) {
// Test the pointer position, not event.target: the <dialog> is also the target for its own
// padding and the gaps between its children, so a target check would close on those clicks
const outside = (e, dialog) => {
const r = dialog.getBoundingClientRect();
return e.clientX < r.left || e.clientX > r.right || e.clientY < r.top || e.clientY > r.bottom;
};
for (const dialog of document.querySelectorAll('dialog[closedby="any"]')) {
let pressedOutside = false;
dialog.addEventListener('pointerdown', (e) => { pressedOutside = outside(e, dialog); });
// Require the press and the release outside, so a text-selection drag that ends on the backdrop does not dismiss
dialog.addEventListener('pointerup', (e) => { if (pressedOutside && outside(e, dialog)) dialog.close(); });
}
}
overscroll-behavior
স্ক্রল কন্টেনমেন্টকে প্রোগ্রেসিভ এনহ্যান্সমেন্ট হিসেবে বিবেচনা করুন। এটি ফিচার-ডিটেক্ট করবেন না: @supports প্রপার্টিকে কাজ করে হিসেবে রিপোর্ট করে, এমনকি যেখানে স্ক্রল করা যায় না এমন কন্টেনার এটিকে উপেক্ষা করে। যেখানে এটি এনফোর্স করা হয় না, সেখানে ডায়ালগে এখনও স্ক্রল থাকে যখনই এর নিজস্ব কন্টেন্ট ওভারফ্লো হয় এবং showModal() এখনও পৃষ্ঠাটিকে নিষ্ক্রিয় করে তোলে। html বা body-এ overflow: hidden বা position: fixed-এ ফিরে যাবেন না, যা রুট স্ক্রলবার সরিয়ে দেয় এবং লেআউট পরিবর্তন করে।
ইনভোকার কমান্ড (command / commandfor)
আপনার বেসলাইন টার্গেটে ইনভোকার কমান্ড অন্তর্ভুক্ত না থাকলে, একই মার্কআপ রাখুন এবং শর্তসাপেক্ষে পলিফিল লোড করুন (প্রোগ্রেসিভ এনহ্যান্সমেন্টের মতো একই অভিজ্ঞতা)। ইন্টারফেসে শনাক্ত করুন এবং শর্ত ছাড়া কখনই এটি লোড করবেন না:
// MANDATORY: feature detect on HTMLButtonElement.prototype and load only when native support is missing
if (!('commandForElement' in HTMLButtonElement.prototype)) {
import('invokers-polyfill'); // npm install invokers-polyfill
}
শুধুমাত্র নিয়ম ২ ও ৩-এ Popover ব্যবহার করা হয়।
পপওভারের জন্য ফলব্যাক ও ব্রাউজার সাপোর্ট
পপওভার API মূলত প্রোগ্রেসিভ এনহ্যান্সমেন্ট, তবে এর সংজ্ঞায়িত আচরণ — টপ-লেয়ার প্রোমোশন, লাইট-ডিসমিস এবং popovertarget ইনভোকেশন — শুধুমাত্র CSS-এর সমতুল্য নয়। পুরনো ব্রাউজারের ক্ষেত্রে পলিফিল বা ম্যানুয়াল ফলব্যাক প্রয়োজন হয়, যদি আপনি কোনওটিই শিপ করতে না চান।
Polyfill: পুরনো ব্রাউজারে popover অ্যাট্রিবিউট কাজ করানোর জন্য, শর্তসাপেক্ষে @oddbird/popover-polyfill লোড করুন। বাধ্যতামূলক: HTMLElement.prototype-এ popover প্রপার্টি চেক করে ফিচার শনাক্ত করুন এবং নেটিভ সাপোর্ট না থাকলে শুধুমাত্র তখনই পলিফিল লোড করুন — শর্তহীনভাবে এটি লোড করবেন না।
বান্ডলার বা ইমপোর্ট ম্যাপের মাধ্যমে:
// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
import("@oddbird/popover-polyfill");
}
বান্ডলার ছাড়া, <script type="module">-এর মধ্যে CDN থেকে ইমপোর্ট করুন:
<script type="module">
if (!("popover" in HTMLElement.prototype)) {
import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
}
</script>
স্টাইলিং সংক্রান্ত সতর্কতা: পলিফিল আসল :popover-open ছদ্ম-ক্লাসকে সংজ্ঞায়িত করতে পারে না, তাই এটি পরিবর্তে .\:popover-open ক্লাস প্রয়োগ করে। বাধ্যতামূলক: :is() বা :where()-এর সাথে দুটিকে একত্রিত করুন, অন্যথায় :popover-open নেই এমন ব্রাউজার সম্পূর্ণ নিয়মটি বাতিল করে দেয়:
[popover]:is(:popover-open, .\:popover-open) {
display: block;
}
বিকল্প হিসেবে, পলিফিল ছাড়া লিগ্যাসি ফলব্যাকের জন্য, position: fixed ব্যবহার করুন এবং getBoundingClientRect()-এর মাধ্যমে ম্যানুয়ালি কোঅর্ডিনেট হিসেব করুন অথবা ব্যবহারের ক্ষেত্রে গ্রহণযোগ্য হলে inset: auto-এর সাথে ডিফল্ট পজিশনিংয়ের উপর নির্ভর করুন।