সেটিংস কম্পোনেন্ট তৈরি করা

স্লাইডার ও চেকবক্সের সেটিংস কম্পোনেন্ট কীভাবে তৈরি করতে হয় তার একটি প্রাথমিক ওভারভিউ।

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

ডেমো

আপনি ভিডিও দেখতে পছন্দ করলে অথবা আমরা যা তৈরি করছি তার UI/UX প্রিভিউ দেখতে চাইলে, YouTube-এ একটি ছোট ওয়াকথ্রু এখানে দেওয়া হল:

এক নজরে

আমি এই কম্পোনেন্টের বিভিন্ন দিক নিম্নলিখিত বিভাগে ভাগ করেছি:

  1. লেআউট
  2. রঙ
  3. কাস্টম করা রেঞ্জের ইনপুট
  4. কাস্টম চেকবক্স ইনপুট
  5. অ্যাক্সেসিবিলিটি সংক্রান্ত বিবেচনা
  6. JavaScript

লেআউট

এটি হল প্রথম GUI চ্যালেঞ্জ ডেমো যা সম্পূর্ণ CSS গ্রিড! এখানে প্রতিটি গ্রিড গ্রিডের জন্য Chrome DevTools-এর মাধ্যমে হাইলাইট করা হয়েছে:

রঙিন আউটলাইন এবং ফাঁকা স্পেসিং ওভারলে যা সেটিংস লেআউট তৈরি করে এমন সব বক্স দেখাতে সাহায্য করে

Just for gap

সবচেয়ে সাধারণ লেআউট:

foo {
  display: grid;
  gap: var(--something);
}

আমি এই লেআউটকে "শুধু ফাঁকা জায়গার জন্য" বলি কারণ এটি ব্লকের মধ্যে ফাঁকা জায়গা যোগ করার জন্য শুধু গ্রিড ব্যবহার করে।

পাঁচটি লেআউট এই স্ট্র্যাটেজি ব্যবহার করে, এখানে সেগুলি সব দেখানো হয়েছে:

উল্লম্ব গ্রিড লেআউট আউটলাইন দিয়ে হাইলাইট করা এবং ফাঁকা জায়গা পূরণ করা হয়েছে

fieldset এলিমেন্ট, যার মধ্যে প্রতিটি ইনপুট গ্রুপ (.fieldset-item) থাকে, সেটি এলিমেন্টের মধ্যে হেয়ারলাইন বর্ডার তৈরি করতে gap: 1px ব্যবহার করছে। সীমানা সংক্রান্ত জটিল সমস্যার সমাধান!

পূরণ করা গ্যাপ
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
বর্ডার ট্রিক
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

ন্যাচারাল গ্রিড র‍্যাপিং

সবচেয়ে জটিল লেআউটটি শেষ পর্যন্ত ম্যাক্রো লেআউট, <main> এবং <form>-এর মধ্যে লজিক্যাল লেআউট সিস্টেম হয়ে উঠেছে।

র‍্যাপিং কন্টেন্ট মাঝখানে নিয়ে আসা

Flexbox এবং গ্রিড উভয়ই align-items বা align-content-এর ক্ষমতা প্রদান করে এবং র‍্যাপিং এলিমেন্ট নিয়ে কাজ করার সময়, content লেআউট অ্যালাইনমেন্ট চিলড্রেনের মধ্যে গ্রুপ হিসেবে স্পেস ডিস্ট্রিবিউট করবে।

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

প্রধান এলিমেন্ট place-content: center অ্যালাইনমেন্ট শর্টহ্যান্ড ব্যবহার করছে যাতে চাইল্ড এলিমেন্ট এক ও দুই কলাম লেআউটে উল্লম্ব ও অনুভূমিকভাবে কেন্দ্রে থাকে।

উপরের ভিডিওতে দেখুন কীভাবে "কন্টেন্ট" র‍্যাপ করা সত্ত্বেও সেন্টারে থাকে।

অটো-ফিট minmax রিপিট করুন

<form> প্রতিটি বিভাগের জন্য অ্যাডাপ্টিভ গ্রিড লেআউট ব্যবহার করে। উপলভ্য জায়গার উপর নির্ভর করে এই লেআউট এক থেকে দুই কলামে পরিবর্তন হয়।

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

রেসপন্সিভ লেআউটে কাস্টম টাচ যোগ করতে, এই গ্রিডে row-gap (--space-xl)-এর জন্য column-gap (--space-xxl)-এর থেকে আলাদা ভ্যালু আছে। কলামগুলি স্ট্যাক করা হলে, আমরা একটি বড় ফাঁক চাই, তবে ওয়াইড স্ক্রিনে থাকলে যতটা বড় ফাঁক থাকে ততটা বড় নয়।

grid-template-columns প্রপার্টি ৩টি CSS ফাংশন ব্যবহার করে: repeat(), minmax() এবং min(). Una Kravets-এর এই বিষয়ে একটি দুর্দান্ত লেআউট ব্লগ পোস্ট আছে, যেখানে এটিকে RAM বলা হয়েছে।

আমাদের লেআউটে ৩টি বিশেষ সংযোজন আছে, আপনি যদি এটি Una-এর সাথে তুলনা করেন:

  • আমরা একটি অতিরিক্ত min() ফাংশন পাস করি।
  • আমরা align-items: flex-start উল্লেখ করি।
  • max-width: 89vw স্টাইল আছে।

Evan Minto তার ব্লগে Intrinsically Responsive CSS Grid with minmax() and min() পোস্টে অতিরিক্ত min() ফাংশনটি খুব ভালোভাবে বর্ণনা করেছেন। আমি আপনাকে এটি পড়ার সাজেশন দিচ্ছি। flex-start অ্যালাইনমেন্ট সংশোধন করার অর্থ হল ডিফল্ট স্ট্রেচিং এফেক্ট সরিয়ে দেওয়া, যাতে এই লেআউটের চাইল্ডের সমান উচ্চতা না হলেও চলে, তাদের স্বাভাবিক, অন্তর্নিহিত উচ্চতা থাকতে পারে। এই YouTube ভিডিওতে এই অ্যালাইনমেন্ট যোগ করার বিষয়ে সংক্ষেপে আলোচনা করা হয়েছে।

এই পোস্টে max-width: 89vw-এর জন্য একটি ছোট ব্রেকডাউন দেওয়া হল। স্টাইল প্রয়োগ করা এবং না করা লেআউট আপনাকে দেখাই:

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

তাহলে, 89vw কেন? কারণ আমার লেআউটের জন্য "এটি কাজ করেছে"। আমি এবং Chrome-এর আরও কয়েকজন সহকর্মী মিলে খতিয়ে দেখছি যে কেন আরও যুক্তিযুক্ত ভ্যালু, যেমন 100vw যথেষ্ট নয় এবং এটি আসলে কোনও বাগ কিনা।

ব্যবধান

এই লেআউটের বেশিরভাগ হার্মনি স্পেসিংয়ের সীমিত প্যালেট থেকে আসে, ঠিক ৭টি।

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

গ্রিড, CSS @nest এবং @media-এর লেভেল ৫ সিনট্যাক্স-এর সাথে এই ফ্লো খুব ভালোভাবে ব্যবহার করা যায়। এখানে একটি উদাহরণ দেওয়া হল, সম্পূর্ণ <main> লেআউট সেট অফ স্টাইল।

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

মাঝখানে কন্টেন্ট সহ গ্রিড, ডিফল্ট হিসেবে মাঝারি প্যাডিং সহ (যেমন মোবাইলে)। কিন্তু আরও ভিউপোর্ট স্পেস উপলভ্য হলে, এটি প্যাডিং বাড়িয়ে ছড়িয়ে পড়ে। ২০২১ CSS বেশ ভালোই দেখাচ্ছে!

আগের লেআউট, "শুধু গ্যাপের জন্য" মনে আছে? এই কম্পোনেন্টে সেগুলি কেমন দেখায় তার আরও সম্পূর্ণ ভার্সন এখানে দেওয়া হল:

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

রঙ

রঙের নিয়ন্ত্রিত ব্যবহার এই ডিজাইনকে একই সাথে অভিব্যক্তিপূর্ণ ও মিনিমালিস্টিক করে তুলেছে। আমি এটি এইভাবে করি:

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

আমি সারফেস ও টেক্সটের রঙের নাম দেওয়ার জন্য surface-dark ও surface-darker-এর মতো নামের পরিবর্তে সংখ্যা ব্যবহার করি, কারণ মিডিয়া কোয়েরিতে আমি এগুলি ফ্লিপ করব এবং সেক্ষেত্রে লাইট ও ডার্কের কোনও অর্থ থাকবে না।

আমি সেগুলিকে এইভাবে একটি পছন্দসই মিডিয়া কোয়েরিতে ফ্লিপ করি:

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

কালার সিনট্যাক্সের বিবরণে যাওয়ার আগে সামগ্রিক ছবি ও স্ট্র্যাটেজি এক ঝলকে দেখে নেওয়া গুরুত্বপূর্ণ। তবে, আমি একটু বেশিই বলে ফেলেছি, তাই একটু পিছিয়ে যাই।

LCH?

কালার থিওরির গভীরে না গিয়ে, LCH হল মানুষের জন্য তৈরি সিনট্যাক্স, যা আমরা কীভাবে রঙ দেখি তা বোঝায়, আমরা কীভাবে গণিতের মাধ্যমে রঙ পরিমাপ করি (যেমন ২৫৫) তা নয়। এটি একটি বিশেষ সুবিধা প্রদান করে কারণ মানুষ এটি আরও সহজে লিখতে পারে এবং অন্যান্য মানুষ এই অ্যাডজাস্টমেন্টের সাথে মানিয়ে নিতে পারবে।

pod.link/csspodcast ওয়েবপেজের স্ক্রিনশট, যেখানে Color 2: Perception পর্বটি দেখানো হয়েছে
CSS পডকাস্ট থেকে পারসেপচুয়াল কালার (এবং আরও অনেক কিছু!) সম্পর্কে জানুন

আজকের জন্য, এই ডেমোতে, আসুন সিনট্যাক্স এবং আমি যে ভ্যালুগুলি ফ্লিপ করছি তার উপর ফোকাস করি লাইট এবং ডার্ক করতে। আসুন ১টি সারফেস এবং ১টি টেক্সটের রঙ দেখি:

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0)-এর অর্থ হল 10% উজ্জ্বলতা, 0 ক্রোমা এবং 0 হিউ: একটি খুব গাঢ় বর্ণহীন ধূসর। তারপর, লাইট মোডের জন্য মিডিয়া কোয়েরিতে, লাইটনেস --surface1: lch(90 0 0);-এর সাথে 90%-এ ফ্লিপ করা হয়। আর এটাই হল কৌশলের সারসংক্ষেপ। ২টি থিমের মধ্যে উজ্জ্বলতা পরিবর্তন করে শুরু করুন, ডিজাইনের জন্য প্রয়োজনীয় কন্ট্রাস্ট রেশিও বজায় রাখুন অথবা অ্যাক্সেসিবিলিটি বজায় রাখতে পারে এমন কিছু করুন।

এখানে lch()-এর সাথে বোনাস হল যে উজ্জ্বলতা মানুষের উপর নির্ভর করে এবং আমরা এতে % পরিবর্তন সম্পর্কে ভাল অনুভব করতে পারি, যে এটি ধারণাগতভাবে এবং ধারাবাহিকভাবে সেই % আলাদা হবে। যেমন, hsl() ততটা নির্ভরযোগ্য নয়।

আপনি আগ্রহী হলে, কালার স্পেস ও lch() সম্পর্কে আরও জানতে পারবেন। এটি আসছে!

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

Lea Verou

রঙের স্কিম সহ অ্যাডাপ্টিভ ফর্ম কন্ট্রোল

অনেক ব্রাউজার ডার্ক থিম কন্ট্রোল প্রদান করে, বর্তমানে Safari এবং Chromium, তবে আপনার ডিজাইন যে এগুলি ব্যবহার করে তা আপনাকে CSS বা HTML-এ উল্লেখ করতে হবে।

DevTools-এর স্টাইল প্যানেল থেকে প্রপার্টির প্রভাব উপরে দেখানো হয়েছে। ডেমোতে HTML ট্যাগ ব্যবহার করা হয়, আমার মতে সাধারণত এটিই সবচেয়ে ভাল লোকেশন:

<meta name="color-scheme" content="dark light">

Thomas Steiner-এর লেখা এই color-scheme নিবন্ধ থেকে এই বিষয়ে সব কিছু জানুন। ডার্ক চেকবক্স ইনপুট ছাড়াও আরও অনেক কিছু পাওয়ার আছে!

CSS accent-color

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

input[type="checkbox"] {
  accent-color: var(--brand);
}

Linux-এ Chromium থেকে গোলাপি চেকবক্সের একটি স্ক্রিনশট

ফিক্সড গ্রেডিয়েন্ট ও ফোকাস-উইদিন সহ কালার পপ

রঙের ব্যবহার কম হলে তা সবচেয়ে বেশি চোখে পড়ে এবং আমি রঙিন UI ইন্টার‍্যাকশনের মাধ্যমে তা করতে পছন্দ করি।

উপরের ভিডিওতে UI ফিডব্যাক ও ইন্টার‍্যাকশনের অনেক লেয়ার আছে, যা ইন্টার‍্যাকশনকে ব্যক্তিত্ব দিতে সাহায্য করে:

  • প্রসঙ্গ হাইলাইট করা।
  • রেঞ্জে ভ্যালু "কতটা সম্পূর্ণ" তা UI ফিডব্যাক প্রদান করা।
  • কোনও ফিল্ড ইনপুট গ্রহণ করছে কিনা সেই সম্পর্কে UI সংক্রান্ত মতামত প্রদান করা।

কোনও এলিমেন্টের সাথে ইন্টার‍্যাক্ট করার সময় মতামত জানাতে, CSS :focus-within সিউডো ক্লাস ব্যবহার করে বিভিন্ন এলিমেন্টের রূপ পরিবর্তন করে, আসুন .fieldset-item-কে ভেঙে দেখা যাক, এটি খুবই আকর্ষণীয়:

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

এই এলিমেন্টের কোনও একটি চাইল্ডের focus-within থাকলে:

  1. .fieldset-item ব্যাকগ্রাউন্ডে আরও বেশি কনট্রাস্ট সারফেস রঙ অ্যাসাইন করা হয়েছে।
  2. নেস্ট করা svg-এ আরও বেশি কনট্রাস্টের জন্য সাদা রঙ দিয়ে ভর্তি করা হয়েছে।
  3. নেস্ট করা <picture> clip-path সম্পূর্ণ বৃত্তে প্রসারিত হয় এবং ব্যাকগ্রাউন্ড উজ্জ্বল ফিক্সড গ্রেডিয়েন্টে ভরে যায়।

কাস্টম ব্যাপ্তি

নিচে দেওয়া HTML ইনপুট এলিমেন্টের ভিত্তিতে, আমি আপনাকে দেখাব যে আমি কীভাবে এর চেহারা কাস্টমাইজ করেছি:

<input type="range">

এই এলিমেন্টের ৩টি অংশ আছে যা আমাদের কাস্টমাইজ করতে হবে:

  1. রেঞ্জ এলিমেন্ট / কন্টেনার
  2. ট্র্যাক
  3. বৃদ্ধাঙ্গুষ্ঠ

রেঞ্জ এলিমেন্ট স্টাইল

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

CSS-এর প্রথম কয়েকটি লাইন হল স্টাইলের কাস্টম অংশ এবং আমি আশা করি যে সেগুলি স্পষ্টভাবে লেবেল করলে সুবিধা হবে। বাকি স্টাইলগুলি বেশিরভাগই রিসেট স্টাইল, যাতে কম্পোনেন্টের জটিল অংশগুলি তৈরি করার জন্য একটি সামঞ্জস্যপূর্ণ ভিত্তি প্রদান করা যায়।

ট্র্যাক স্টাইল

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

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

ট্র্যাক ফিল স্টাইল

ফিল স্টাইল বজায় রাখার জন্য আমার ডিজাইনে জাভাস্ক্রিপ্ট প্রয়োজন। শুধুমাত্র CSS স্ট্র্যাটেজি আছে, তবে সেগুলির জন্য থাম্ব এলিমেন্টের উচ্চতা ট্র্যাকের সমান হতে হবে এবং আমি সেই সীমার মধ্যে কোনও সামঞ্জস্য খুঁজে পাইনি।

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

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

CSS-Tricks-এ Ana Tudor-এর লেখা একটি দারুণ পোস্ট এখানে দেওয়া হল, যেখানে ট্র্যাক ফিল করার জন্য শুধু CSS-এর মাধ্যমে সমাধান দেখানো হয়েছে। আমি এই range এলিমেন্ট থেকেও অনেক অনুপ্রেরণা পেয়েছি।

থাম্ব স্টাইল

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

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

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  …

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

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

চেকবক্সে হাইলাইট এফেক্ট দেওয়া যদি এত সহজ হত…

ক্রস ব্রাউজার সিলেক্টর

আমি দেখেছি যে ক্রস ব্রাউজার কনসিস্টেন্সি অর্জন করতে আমার এই -webkit- এবং -moz- সিলেক্টরগুলি প্রয়োজন:

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

কাস্টম চেকবক্স

নিচে দেওয়া HTML ইনপুট এলিমেন্টের ভিত্তিতে, আমি আপনাকে দেখাব যে আমি কীভাবে এর চেহারা কাস্টমাইজ করেছি:

<input type="checkbox">

এই এলিমেন্টের ৩টি অংশ আছে যা আমাদের কাস্টমাইজ করতে হবে:

  1. চেকবক্স এলিমেন্ট
  2. সংশ্লিষ্ট লেবেল
  3. হাইলাইট এফেক্ট

চেকবক্স এলিমেন্ট

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

transform-style এবং position স্টাইলগুলি ছদ্ম-উপাদানের জন্য প্রস্তুত করে যা আমরা পরে হাইলাইট স্টাইল করার জন্য পরিচয় করিয়ে দেব। অন্যথায়, এটি বেশিরভাগই আমার মতামত ভিত্তিক স্টাইল। আমি চাই কার্সরটি পয়েন্টার হোক, আমি আউটলাইন অফসেট পছন্দ করি, ডিফল্ট চেকবক্সগুলি খুব ছোট এবং যদি accent-color সমর্থিত হয়, তাহলে এই চেকবক্সগুলিকে ব্র্যান্ডের রঙের স্কিমে নিয়ে আসুন।

চেকবক্স লেবেল

২টি কারণে চেকবক্সের জন্য লেবেল প্রদান করা গুরুত্বপূর্ণ। প্রথমটি হল চেকবক্সের মান কীসের জন্য ব্যবহার করা হয় তা উপস্থাপন করা, "কীসের জন্য চালু বা বন্ধ?" প্রশ্নের উত্তর দিতে। দ্বিতীয়ত, UX-এর জন্য, ওয়েব ব্যবহারকারীরা সংশ্লিষ্ট লেবেলের মাধ্যমে চেকবক্সের সাথে ইন্টার‍্যাক্ট করতে অভ্যস্ত হয়ে গেছেন।

ইনপুট
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
লেবেল
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

আপনার লেবেলে, একটি for অ্যাট্রিবিউট রাখুন যা আইডি অনুযায়ী চেকবক্সকে পয়েন্ট করে: <label for="text-notifications">। আপনার চেকবক্সে, নাম এবং আইডি উভয়ই ডবল আপ করুন যাতে এটি মাউস বা স্ক্রিনরিডারের মতো বিভিন্ন টুল এবং প্রযুক্তির সাহায্যে খুঁজে পাওয়া যায়: <input type="checkbox" id="text-notifications" name="text-notifications">. কানেকশনের সাথে :hover, :active এবং আরও অনেক কিছু ফ্রিতে পাওয়া যায়, যার ফলে আপনার ফর্মের সাথে ইন্টার‍্যাক্ট করার উপায় আরও বৃদ্ধি পায়।

চেকবক্স হাইলাইট

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

আমি একটি ছদ্ম এলিমেন্ট এবং জটিল CSS-এর সাহায্যে একই ভিজ্যুয়াল এফেক্ট অর্জন করতে পেরেছি:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

বৃত্তাকার ছদ্ম-এলিমেন্ট তৈরি করা সহজ কাজ, কিন্তু যে এলিমেন্টের সাথে এটি অ্যাটাচ করা আছে, তার পিছনে এটি প্লেস করা কঠিন ছিল। আমি এটি ঠিক করার আগে এবং পরে কেমন দেখতে লাগছে তা এখানে দেওয়া হল:

এটি অবশ্যই একটি মাইক্রো ইন্টারঅ্যাকশন, তবে ভিজ্যুয়াল সামঞ্জস্য বজায় রাখার জন্য আমার কাছে গুরুত্বপূর্ণ। অ্যানিমেশন স্কেলিং টেকনিকটি আমরা অন্যান্য জায়গায় যে টেকনিক ব্যবহার করেছি তারই মতো। আমরা একটি কাস্টম প্রপার্টিকে নতুন ভ্যালুতে সেট করি এবং মোশন সংক্রান্ত পছন্দের উপর ভিত্তি করে CSS-কে এটি ট্রানজিশন করতে দিই। এখানে মূল ফিচার হল translateZ(-1px)। প্যারেন্ট একটি 3D স্পেস তৈরি করেছে এবং এই ছদ্ম-এলিমেন্ট চাইল্ড z-স্পেসে নিজেকে কিছুটা পিছনে রেখে এতে ট্যাপ করেছে।

অ্যাক্সেসিবিলিটি

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

HTML এলিমেন্ট সংক্রান্ত পছন্দ

<form>
<header>
<fieldset>
<picture>
<label>
<input>

এগুলির প্রতিটিতে ব্যবহারকারীর ব্রাউজিং টুলের জন্য ইঙ্গিত এবং পরামর্শ থাকে। কিছু এলিমেন্ট ইন্টার‍্যাকশন সংক্রান্ত ইঙ্গিত প্রদান করে, কিছু ইন্টার‍্যাক্টিভিটি কানেক্ট করে এবং কিছু এলিমেন্ট অ্যাক্সেসিবিলিটি ট্রিকে আকার দিতে সাহায্য করে যা স্ক্রিনরিডার নেভিগেট করে।

HTML অ্যাট্রিবিউট

স্ক্রিনরিডারের প্রয়োজন নেই এমন এলিমেন্ট আমরা লুকাতে পারি, এই ক্ষেত্রে স্লাইডারের পাশের আইকন:

<picture aria-hidden="true">

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

SVG হল একগুচ্ছ অঙ্ক, আসুন একটি <title> এলিমেন্ট যোগ করি যাতে মাউস হোভার করলে একটি ফ্রি টাইটেল এবং অঙ্কটি কী তৈরি করছে সে সম্পর্কে মানুষের-পঠনযোগ্য মন্তব্য দেখা যায়:

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

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

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

জাভাস্ক্রিপ্ট থেকে কীভাবে ট্র্যাক ফিল কালার ম্যানেজ করা হচ্ছিল তা আমি আগেই কভার করেছি, তাই এখন <form> সম্পর্কিত জাভাস্ক্রিপ্ট দেখে নেওয়া যাক:

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

ফর্মের সাথে ইন্টার‍্যাক্ট করা এবং পরিবর্তন করার সময়, কনসোল ফর্মটিকে একটি অবজেক্ট হিসেবে টেবিলে লগ করে, যাতে সার্ভারে জমা দেওয়ার আগে সহজেই পর্যালোচনা করা যায়।

console.table() ফলাফলের স্ক্রিনশট, যেখানে ফর্ম ডেটা একটি টেবিলে দেখানো হয়েছে

উপসংহার

আমি কীভাবে করেছি তা তো জানলে, তুমি কীভাবে করবে?! এটি কিছু মজার কম্পোনেন্ট আর্কিটেকচার তৈরি করে! কে তার পছন্দের ফ্রেমওয়ার্কে স্লট সহ প্রথম ভার্সন তৈরি করতে চলেছেন? 🙂

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

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

  • চেকবক্স লেবেলের জন্য হোভার এরিয়া সম্পর্কে @tomayac-এর স্টাইল! এই ভার্সনে এলিমেন্টের মধ্যে কোনও হোভার গ্যাপ নেই: ডেমো এবং সোর্স।