একটি টুলটিপ উপাদান নির্মাণ

কীভাবে একটি রঙ-অভিযোজিত এবং অ্যাক্সেসযোগ্য টুলটিপ কাস্টম উপাদান তৈরি করা যায় তার একটি মৌলিক ওভারভিউ।

এই পোস্টে আমি কীভাবে একটি রঙ-অভিযোজিত এবং অ্যাক্সেসযোগ্য <tool-tip> কাস্টম উপাদান তৈরি করতে পারি সে সম্পর্কে আমার চিন্তাভাবনা শেয়ার করতে চাই। ডেমো চেষ্টা করুন এবং উৎস দেখুন !

একটি টুলটিপ বিভিন্ন উদাহরণ এবং রঙের স্কিম জুড়ে কাজ করে দেখানো হয়েছে

আপনি যদি ভিডিও পছন্দ করেন তবে এখানে এই পোস্টটির একটি YouTube সংস্করণ রয়েছে:

ওভারভিউ

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

করুন: সর্বদা আপনার ইনপুট লেবেল করুন।
করবেন না: লেবেলের পরিবর্তে টুলটিপের উপর নির্ভর করুন

টগলটিপ বনাম টুলটিপ

অনেক উপাদানের মতো, টুলটিপ কী তার বিভিন্ন বর্ণনা রয়েছে, উদাহরণস্বরূপ MDN , WAI ARIA , Sarah Higley , এবং Inclusive Components- এ৷ আমি টুলটিপ এবং টগলটিপগুলির মধ্যে বিচ্ছেদ পছন্দ করি। একটি টুলটিপে অ-ইন্টারেক্টিভ সম্পূরক তথ্য থাকা উচিত, যখন একটি টগলটিপে ইন্টারঅ্যাক্টিভিটি এবং গুরুত্বপূর্ণ তথ্য থাকতে পারে। বিভাজনের প্রাথমিক কারণ হল অ্যাক্সেসিবিলিটি, কীভাবে ব্যবহারকারীরা পপআপে নেভিগেট করবেন এবং তথ্য ও বোতামগুলিতে অ্যাক্সেস পাবেন বলে আশা করা হয়। টগলটিপ দ্রুত জটিল হয়ে যায়।

এখানে ডিজাইনসেম্বার সাইট থেকে একটি টগলটিপের একটি ভিডিও রয়েছে; ইন্টারঅ্যাক্টিভিটি সহ একটি ওভারলে যা একজন ব্যবহারকারী পিন করে খুলতে এবং অন্বেষণ করতে পারে, তারপর হালকা খারিজ বা এস্কেপ কী দিয়ে বন্ধ করতে পারে:

এই জিইউআই চ্যালেঞ্জটি একটি টুলটিপের রুটে চলে গেছে, সিএসএস দিয়ে প্রায় সবকিছু করতে চাইছে এবং এটি কীভাবে তৈরি করা যায় তা এখানে।

মার্কআপ

আমি একটি কাস্টম উপাদান <tool-tip> ব্যবহার করতে বেছে নিয়েছি। লেখকরা যদি না চান তবে কাস্টম উপাদানগুলিকে ওয়েব উপাদানগুলিতে তৈরি করতে হবে না। ব্রাউজারটি <foo-bar> <div> এর মতই ব্যবহার করবে। আপনি কম নির্দিষ্টতা সহ একটি ক্লাসের নাম মত একটি কাস্টম উপাদান চিন্তা করতে পারেন. কোন জাভাস্ক্রিপ্ট জড়িত নেই.

<tool-tip>A tooltip</tool-tip>

এটি ভিতরে কিছু টেক্সট সঙ্গে একটি div মত. আমরা [role="tooltip"] যোগ করে সক্ষম স্ক্রিন রিডারগুলির অ্যাক্সেসিবিলিটি ট্রিতে বাঁধতে পারি।

<tool-tip role="tooltip">A tooltip</tool-tip>

এখন, স্ক্রিন রিডারদের কাছে, এটি একটি টুলটিপ হিসাবে স্বীকৃত। নিম্নলিখিত উদাহরণে দেখুন কিভাবে প্রথম লিঙ্ক উপাদানটির গাছে একটি স্বীকৃত টুলটিপ উপাদান রয়েছে এবং দ্বিতীয়টিতে নেই? দ্বিতীয়টির ভূমিকা নেই। শৈলী বিভাগে আমরা এই ট্রি ভিউতে উন্নতি করব।

HTML-এর প্রতিনিধিত্বকারী Chrome DevTools অ্যাক্সেসিবিলিটি ট্রি-এর একটি স্ক্রিনশট৷ শীর্ষস্থানীয় পাঠ্য সহ একটি লিঙ্ক দেখায়; টুলটিপ আছে: আরে, একটি টুলটিপ!' যে ফোকাসযোগ্য. এর ভিতরে 'টপ' এর স্ট্যাটিক টেক্সট এবং একটি টুলটিপ উপাদান রয়েছে।

পরবর্তীতে আমাদের ফোকাসযোগ্য না হওয়ার জন্য টুলটিপ দরকার। যদি একজন স্ক্রিন রিডার টুলটিপের ভূমিকা বুঝতে না পারে তবে এটি ব্যবহারকারীদের বিষয়বস্তু পড়ার জন্য <tool-tip> ফোকাস করতে দেয় এবং ব্যবহারকারীর অভিজ্ঞতার এটির প্রয়োজন নেই। স্ক্রিন রিডাররা বিষয়বস্তুটিকে মূল উপাদানের সাথে যুক্ত করবে এবং যেমন, অ্যাক্সেসযোগ্য করার জন্য এটিকে ফোকাসের প্রয়োজন নেই৷ কোন ব্যবহারকারী ভুলবশত তাদের ট্যাব প্রবাহে এই টুলটিপ সামগ্রীটি খুঁজে পাবে না তা নিশ্চিত করতে এখানে আমরা inert ব্যবহার করতে পারি:

<tool-tip inert role="tooltip">A tooltip</tool-tip>

Chrome DevTools অ্যাক্সেসিবিলিটি ট্রি-এর আরেকটি স্ক্রিনশট, এবার টুলটিপ উপাদানটি নেই।

আমি তখন টুলটিপের অবস্থান নির্দিষ্ট করতে ইন্টারফেস হিসাবে বৈশিষ্ট্যগুলি ব্যবহার করা বেছে নিয়েছি। ডিফল্টরূপে সমস্ত <tool-tip> s একটি "শীর্ষ" অবস্থান ধরে নেবে, কিন্তু tip-position যোগ করে একটি উপাদানে অবস্থানটি কাস্টমাইজ করা যেতে পারে:

<tool-tip role="tooltip" tip-position="right ">A tooltip</tool-tip>

ডানদিকে একটি টুলটিপ সহ একটি লিঙ্কের একটি স্ক্রিনশট বলছে 'একটি টুলটিপ'।

আমি এই জাতীয় জিনিসগুলির জন্য ক্লাসের পরিবর্তে বৈশিষ্ট্যগুলি ব্যবহার করার প্রবণতা রাখি যাতে <tool-tip> একই সময়ে একাধিক অবস্থান বরাদ্দ করতে পারে না। শুধুমাত্র একটি বা কেউ হতে পারে.

অবশেষে, আপনি যে উপাদানটির জন্য টুলটিপ দিতে চান তার ভিতরে <tool-tip> উপাদান রাখুন। এখানে আমি একটি <picture> উপাদানের ভিতরে একটি ছবি এবং একটি <tool-tip> স্থাপন করে দৃষ্টিশক্তিসম্পন্ন ব্যবহারকারীদের সাথে alt পাঠ্য শেয়ার করছি:

<picture>
  <img alt="The GUI Challenges skull logo" width="100" src="...">
  <tool-tip role="tooltip" tip-position="bottom">
    The <b>GUI Challenges</b> skull logo
  </tool-tip>
</picture>

একটি টুলটিপ সহ একটি চিত্রের একটি স্ক্রিনশট যা বলছে 'GUI চ্যালেঞ্জেস স্কাল লোগো'৷

এখানে আমি একটি <abbr> উপাদানের ভিতরে একটি <tool-tip> রাখি:

<p>
  The <abbr>HTML <tool-tip role="tooltip" tip-position="top">Hyper Text Markup Language</tool-tip></abbr> abbr element.
</p>

সংক্ষিপ্ত এইচটিএমএল আন্ডারলাইন করা একটি অনুচ্ছেদের একটি স্ক্রিনশট এবং এটির উপরে 'হাইপার টেক্সট মার্কআপ ল্যাঙ্গুয়েজ' বলে একটি টুলটিপ।

অ্যাক্সেসযোগ্যতা

যেহেতু আমি টুলটিপ তৈরি করা বেছে নিয়েছি এবং টগলটিপ নয়, তাই এই বিভাগটি অনেক সহজ। প্রথমে, আমাকে আমাদের পছন্দসই ব্যবহারকারীর অভিজ্ঞতার রূপরেখা দিন:

  1. সীমাবদ্ধ স্থান বা বিশৃঙ্খল ইন্টারফেসে, সম্পূরক বার্তা লুকান।
  2. যখন একজন ব্যবহারকারী হোভার করে, ফোকাস করে বা একটি উপাদানের সাথে ইন্টারঅ্যাক্ট করার জন্য স্পর্শ ব্যবহার করে, তখন বার্তাটি প্রকাশ করে।
  3. হোভার, ফোকাস বা স্পর্শ শেষ হলে, আবার বার্তা লুকান।
  4. সবশেষে, নিশ্চিত করুন যে কোনো গতি কমানো হয়েছে যদি কোনো ব্যবহারকারী কম গতির জন্য একটি পছন্দ নির্দিষ্ট করে থাকে।

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

একটি টুলটিপ সহ একটি লিঙ্ক পড়ার MacOS ভয়েসওভারের স্ক্রিনশট৷

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

Chrome DevTools অ্যাক্সেসিবিলিটি ট্রির একটি স্ক্রিনশট যেখানে লিঙ্ক টেক্সট বলছে 'শীর্ষ হে, একটি টুলটিপ!'।

<tool-tip> -এ একটি স্ক্রীন রিডার শুধুমাত্র ছদ্ম-উপাদান যোগ করুন এবং আমরা অদৃষ্ট ব্যবহারকারীদের জন্য আমাদের নিজস্ব প্রম্পট পাঠ্য যোগ করতে পারি।

&::before {
  content: "; Has tooltip: ";
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

নীচে আপনি আপডেট হওয়া অ্যাক্সেসিবিলিটি ট্রি দেখতে পাবেন, যেটিতে এখন লিঙ্ক টেক্সটের পরে একটি সেমিকোলন রয়েছে এবং টুলটিপের জন্য একটি প্রম্পট রয়েছে "হ্যাস টুলটিপ:"৷

Chrome DevTools অ্যাক্সেসিবিলিটি ট্রি-এর একটি আপডেট করা স্ক্রিনশট যেখানে লিঙ্ক টেক্সট বাক্যাংশ উন্নত করেছে, 'টপ ; টুলটিপ আছে: আরে, একটি টুলটিপ!'।

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

শৈলী

<tool-tip> উপাদানটি সেই উপাদানটির একটি সন্তান হবে যেটির জন্য এটি সম্পূরক বার্তাপ্রেরণের প্রতিনিধিত্ব করছে, তাই আসুন প্রথমে ওভারলে প্রভাবের জন্য প্রয়োজনীয় বিষয়গুলি দিয়ে শুরু করি। position absolute সহ নথি প্রবাহের বাইরে নিয়ে যান:

tool-tip {
  position: absolute;
  z-index: 1;
}

যদি অভিভাবক একটি স্ট্যাকিং প্রসঙ্গ না হয়, টুলটিপটি নিজেকে সবচেয়ে কাছের একটিতে স্থাপন করবে, যা আমরা যা চাই তা নয়। ব্লকে একটি নতুন নির্বাচক রয়েছে যা সাহায্য করতে পারে, :has() :

ব্রাউজার সমর্থন

  • 105
  • 105
  • 121
  • 15.4

উৎস

:has(> tool-tip) {
  position: relative;
}

ব্রাউজার সমর্থন সম্পর্কে খুব বেশি চিন্তা করবেন না। প্রথমত, মনে রাখবেন এই টুলটিপগুলি সম্পূরক। যদি তারা কাজ না করে তবে এটি ভাল হওয়া উচিত। দ্বিতীয়ত, জাভাস্ক্রিপ্ট বিভাগে আমরা :has() সমর্থন ছাড়া ব্রাউজারগুলির জন্য আমাদের প্রয়োজনীয় কার্যকারিতা পলিফিল করার জন্য একটি স্ক্রিপ্ট স্থাপন করব।

এর পরে, আসুন টুলটিপগুলিকে অ-ইন্টারেক্টিভ করি যাতে তারা তাদের মূল উপাদান থেকে পয়েন্টার ইভেন্টগুলি চুরি না করে:

tool-tip {
  …
  pointer-events: none;
  user-select: none;
}

তারপরে, অস্বচ্ছতার সাথে টুলটিপটি লুকান যাতে আমরা একটি ক্রসফেড দিয়ে টুলটিপকে স্থানান্তর করতে পারি:

tool-tip {
  opacity: 0;
}

:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
}

:is() এবং :has() এখানে ভারী উত্তোলন করে, একটি চাইল্ড টুলটিপের দৃশ্যমানতা টগল করার জন্য ব্যবহারকারীর ইন্টারঅ্যাক্টিভিটি সম্পর্কে প্যারেন্ট উপাদানগুলি সম্বলিত tool-tip তৈরি করে। মাউস ব্যবহারকারীরা হোভার করতে পারে, কীবোর্ড এবং স্ক্রিন রিডার ব্যবহারকারীরা ফোকাস করতে পারে এবং স্পর্শ ব্যবহারকারীরা ট্যাপ করতে পারে।

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

'ব্লক-স্টার্ট' লিঙ্কের উপরে ভাসমান ডার্ক মোডে টুলটিপের একটি স্ক্রিনশট।

tool-tip {
  --_p-inline: 1.5ch;
  --_p-block: .75ch;
  --_triangle-size: 7px;
  --_bg: hsl(0 0% 20%);
  --_shadow-alpha: 50%;

  --_bottom-tip: conic-gradient(from -30deg at bottom, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) bottom / 100% 50% no-repeat;
  --_top-tip: conic-gradient(from 150deg at top, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) top / 100% 50% no-repeat;
  --_right-tip: conic-gradient(from -120deg at right, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) right / 50% 100% no-repeat;
  --_left-tip: conic-gradient(from 60deg at left, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) left / 50% 100% no-repeat;

  pointer-events: none;
  user-select: none;

  opacity: 0;
  transform: translateX(var(--_x, 0)) translateY(var(--_y, 0));
  transition: opacity .2s ease, transform .2s ease;

  position: absolute;
  z-index: 1;
  inline-size: max-content;
  max-inline-size: 25ch;
  text-align: start;
  font-size: 1rem;
  font-weight: normal;
  line-height: normal;
  line-height: initial;
  padding: var(--_p-block) var(--_p-inline);
  margin: 0;
  border-radius: 5px;
  background: var(--_bg);
  color: CanvasText;
  will-change: filter;
  filter:
    drop-shadow(0 3px 3px hsl(0 0% 0% / var(--_shadow-alpha)))
    drop-shadow(0 12px 12px hsl(0 0% 0% / var(--_shadow-alpha)));
}

/* create a stacking context for elements with > tool-tips */
:has(> tool-tip) {
  position: relative;
}

/* when those parent elements have focus, hover, etc */
:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
  transition-delay: 200ms;
}

/* prepend some prose for screen readers only */
tool-tip::before {
  content: "; Has tooltip: ";
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

/* tooltip shape is a pseudo element so we can cast a shadow */
tool-tip::after {
  content: "";
  background: var(--_bg);
  position: absolute;
  z-index: -1;
  inset: 0;
  mask: var(--_tip);
}

/* top tooltip styles */
tool-tip:is(
  [tip-position="top"],
  [tip-position="block-start"],
  :not([tip-position]),
  [tip-position="bottom"],
  [tip-position="block-end"]
) {
  text-align: center;
}

থিম সমন্বয়

টুলটিপটিতে পরিচালনা করার জন্য শুধুমাত্র কয়েকটি রঙ রয়েছে কারণ পাঠ্যের রঙটি সিস্টেম কীওয়ার্ড CanvasText মাধ্যমে পৃষ্ঠা থেকে উত্তরাধিকারসূত্রে পাওয়া যায়। এছাড়াও, যেহেতু আমরা মানগুলি সঞ্চয় করার জন্য কাস্টম বৈশিষ্ট্যগুলি তৈরি করেছি, আমরা শুধুমাত্র সেই কাস্টম বৈশিষ্ট্যগুলি আপডেট করতে পারি এবং থিমটিকে বাকিগুলি পরিচালনা করতে দিতে পারি:

@media (prefers-color-scheme: light) {
  tool-tip {
    --_bg: white;
    --_shadow-alpha: 15%;
  }
}

টুলটিপের হালকা এবং অন্ধকার সংস্করণের পাশাপাশি স্ক্রিনশট।

হালকা থিমের জন্য, আমরা ব্যাকগ্রাউন্ডটিকে সাদার সাথে মানিয়ে নিই এবং ছায়াগুলিকে তাদের অস্বচ্ছতা সামঞ্জস্য করে অনেক কম শক্তিশালী করি৷

ডান থেকে বাম

ডান থেকে বাম পঠন মোড সমর্থন করার জন্য, একটি কাস্টম সম্পত্তি নথির দিকনির্দেশের মান যথাক্রমে -1 বা 1-এর মান সংরক্ষণ করবে।

tool-tip {
  --isRTL: -1;
}

tool-tip:dir(rtl) {
  --isRTL: 1;
}

টুলটিপ অবস্থানে সহায়তা করতে এটি ব্যবহার করা যেতে পারে:

tool-tip[tip-position="top"]) {
  --_x: calc(50% * var(--isRTL));
}

পাশাপাশি ত্রিভুজটি কোথায় রয়েছে তা সহায়তা করুন:

tool-tip[tip-position="right"]::after {
  --_tip: var(--_left-tip);
}

tool-tip[tip-position="right"]:dir(rtl)::after {
  --_tip: var(--_right-tip);
}

অবশেষে, translateX() এ লজিক্যাল রূপান্তরের জন্যও ব্যবহার করা যেতে পারে:

--_x: calc(var(--isRTL) * -3px * -1);

টুলটিপ পজিশনিং

inset-block বা inset-inline বৈশিষ্ট্যগুলির সাথে লজিক্যালভাবে টুলটিপ অবস্থান করুন শারীরিক এবং লজিক্যাল টুলটিপ উভয় অবস্থানই পরিচালনা করতে। নিম্নলিখিত কোডটি দেখায় কিভাবে চারটি অবস্থানের প্রতিটি বাম-থেকে-ডান এবং ডান-থেকে-বাম উভয় দিকনির্দেশের জন্য স্টাইল করা হয়।

শীর্ষ এবং ব্লক শুরু প্রান্তিককরণ

বাম-থেকে-ডান শীর্ষ অবস্থান এবং ডান-থেকে-বাম শীর্ষ অবস্থানের মধ্যে স্থান নির্ধারণের পার্থক্য দেখানো একটি স্ক্রিনশট৷

tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position])) {
  inset-inline-start: 50%;
  inset-block-end: calc(100% + var(--_p-block) + var(--_triangle-size));
  --_x: calc(50% * var(--isRTL));
}

tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))::after {
  --_tip: var(--_bottom-tip);
  inset-block-end: calc(var(--_triangle-size) * -1);
  border-block-end: var(--_triangle-size) solid transparent;
}

ডান এবং ইনলাইন-শেষ প্রান্তিককরণ

বাম-থেকে-ডান ডান অবস্থান এবং ডান-থেকে-বাম ইনলাইন-এন্ড অবস্থানের মধ্যে স্থান নির্ধারণের পার্থক্য দেখানো একটি স্ক্রিনশট।

tool-tip:is([tip-position="right"], [tip-position="inline-end"]) {
  inset-inline-start: calc(100% + var(--_p-inline) + var(--_triangle-size));
  inset-block-end: 50%;
  --_y: 50%;
}

tool-tip:is([tip-position="right"], [tip-position="inline-end"])::after {
  --_tip: var(--_left-tip);
  inset-inline-start: calc(var(--_triangle-size) * -1);
  border-inline-start: var(--_triangle-size) solid transparent;
}

tool-tip:is([tip-position="right"], [tip-position="inline-end"]):dir(rtl)::after {
  --_tip: var(--_right-tip);
}

নীচে এবং ব্লক-এন্ড প্রান্তিককরণ

বাম-থেকে-ডান নীচে অবস্থান এবং ডান-থেকে-বাম ব্লক-এন্ড অবস্থানের মধ্যে স্থান নির্ধারণের পার্থক্য দেখানো একটি স্ক্রিনশট।

tool-tip:is([tip-position="bottom"], [tip-position="block-end"]) {
  inset-inline-start: 50%;
  inset-block-start: calc(100% + var(--_p-block) + var(--_triangle-size));
  --_x: calc(50% * var(--isRTL));
}

tool-tip:is([tip-position="bottom"], [tip-position="block-end"])::after {
  --_tip: var(--_top-tip);
  inset-block-start: calc(var(--_triangle-size) * -1);
  border-block-start: var(--_triangle-size) solid transparent;
}

বাম এবং ইনলাইন-শুরু প্রান্তিককরণ

বাম-থেকে-ডান বাম অবস্থান এবং ডান-থেকে-বাম ইনলাইন-শুরু অবস্থানের মধ্যে স্থান নির্ধারণের পার্থক্য দেখানো একটি স্ক্রিনশট৷

tool-tip:is([tip-position="left"], [tip-position="inline-start"]) {
  inset-inline-end: calc(100% + var(--_p-inline) + var(--_triangle-size));
  inset-block-end: 50%;
  --_y: 50%;
}

tool-tip:is([tip-position="left"], [tip-position="inline-start"])::after {
  --_tip: var(--_right-tip);
  inset-inline-end: calc(var(--_triangle-size) * -1);
  border-inline-end: var(--_triangle-size) solid transparent;
}

tool-tip:is([tip-position="left"], [tip-position="inline-start"]):dir(rtl)::after {
  --_tip: var(--_left-tip);
}

অ্যানিমেশন

এখন পর্যন্ত আমরা টুলটিপের দৃশ্যমানতা টগল করেছি। এই বিভাগে আমরা প্রথমে সমস্ত ব্যবহারকারীর জন্য অস্বচ্ছতা অ্যানিমেট করব, কারণ এটি একটি সাধারণভাবে নিরাপদ হ্রাসকৃত গতি পরিবর্তন। তারপর আমরা ট্রান্সফর্ম পজিশনকে অ্যানিমেট করব যাতে টুলটিপ প্যারেন্ট এলিমেন্ট থেকে স্লাইড হয়ে যায়।

একটি নিরাপদ এবং অর্থপূর্ণ ডিফল্ট রূপান্তর

টুলটিপ উপাদানটিকে অস্বচ্ছতা এবং রূপান্তর করার জন্য স্টাইল করুন, এইভাবে:

tool-tip {
  opacity: 0;
  transform: translateX(var(--_x, 0)) translateY(var(--_y, 0));
  transition: opacity .2s ease, transform .2s ease;
}

:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
  transition-delay: 200ms;
}

ট্রানজিশনে গতি যোগ করা হচ্ছে

প্রতিটি দিকের জন্য একটি টুলটিপ প্রদর্শিত হতে পারে, যদি ব্যবহারকারীর গতির সাথে ঠিক থাকে, তাহলে translateX প্রপার্টিটিকে সামান্য অবস্থান করে এটি থেকে ভ্রমণের জন্য একটি ছোট দূরত্ব প্রদান করুন:

@media (prefers-reduced-motion: no-preference) {
  :has(> tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_y: 3px;
  }

  :has(> tool-tip:is([tip-position="right"], [tip-position="inline-end"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_x: -3px;
  }

  :has(> tool-tip:is([tip-position="bottom"], [tip-position="block-end"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_y: -3px;
  }

  :has(> tool-tip:is([tip-position="left"], [tip-position="inline-start"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_x: 3px;
  }
}

লক্ষ্য করুন এটি "আউট" স্টেট সেট করছে, যেহেতু "ইন" স্টেটটি translateX(0) এ রয়েছে।

জাভাস্ক্রিপ্ট

আমার মতে, জাভাস্ক্রিপ্ট ঐচ্ছিক। কারণ এই টুলটিপগুলির কোনোটিই আপনার UI-তে কোনো কাজ সম্পন্ন করার জন্য পড়ার প্রয়োজন হবে না। সুতরাং টুলটিপ সম্পূর্ণরূপে ব্যর্থ হলে, এটা কোন বড় ব্যাপার হবে না. এর মানে আমরা টুলটিপগুলিকে ক্রমান্বয়ে উন্নত হিসাবে বিবেচনা করতে পারি। অবশেষে সমস্ত ব্রাউজার সমর্থন করবে :has() এবং এই স্ক্রিপ্ট সম্পূর্ণরূপে চলে যেতে পারে।

পলিফিল স্ক্রিপ্ট দুটি জিনিস করে এবং ব্রাউজার সমর্থন না করলেই তা করে :has() । প্রথমে, :has() সমর্থনের জন্য পরীক্ষা করুন:

if (!CSS.supports('selector(:has(*))')) {
  // do work
}

এর পরে, <tool-tip> s-এর মূল উপাদানগুলি খুঁজুন এবং তাদের সাথে কাজ করার জন্য একটি শ্রেণি নাম দিন:

if (!CSS.supports('selector(:has(*))')) {
  document.querySelectorAll('tool-tip').forEach(tooltip =>
    tooltip.parentNode.classList.add('has_tool-tip'))
}

এরপরে, ঠিক একই আচরণের জন্য :has() নির্বাচককে অনুকরণ করে সেই ক্লাসনাম ব্যবহার করে এমন শৈলীগুলির একটি সেট ইনজেক্ট করুন:

if (!CSS.supports('selector(:has(*))')) {
  document.querySelectorAll('tool-tip').forEach(tooltip =>
    tooltip.parentNode.classList.add('has_tool-tip'))

  let styles = document.createElement('style')
  styles.textContent = `
    .has_tool-tip {
      position: relative;
    }
    .has_tool-tip:is(:hover, :focus-visible, :active) > tool-tip {
      opacity: 1;
      transition-delay: 200ms;
    }
  `
  document.head.appendChild(styles)
}

এটাই, এখন সব ব্রাউজার আনন্দের সাথে টুলটিপ দেখাবে যদি :has() সমর্থিত না হয়।

উপসংহার

এখন যেহেতু আপনি জানেন যে আমি কীভাবে এটি করেছি, আপনি কীভাবে করবেন‽ 🙂 আমি টগলটিপগুলিকে আরও সহজ করার জন্য popup API, কোন z-ইনডেক্স যুদ্ধের জন্য শীর্ষ স্তর এবং উইন্ডোতে জিনিসগুলিকে আরও ভালভাবে স্থাপন করার জন্য anchor API-এর জন্য অপেক্ষা করছি৷ ততক্ষণ পর্যন্ত, আমি টুলটিপস তৈরি করব।

আসুন আমাদের পদ্ধতির বৈচিত্র্য আনুন এবং ওয়েবে তৈরি করার সমস্ত উপায় শিখি।

একটি ডেমো তৈরি করুন, আমাকে লিঙ্কগুলি টুইট করুন এবং আমি নীচের সম্প্রদায়ের রিমিক্স বিভাগে এটি যুক্ত করব!

কমিউনিটি রিমিক্স

এখানে এখনো দেখার কিছু নেই।

সম্পদ