একটি ট্যাব উপাদান নির্মাণ

আইওএস এবং অ্যান্ড্রয়েড অ্যাপে পাওয়া ট্যাবগুলির অনুরূপ একটি ট্যাব উপাদান কীভাবে তৈরি করা যায় তার একটি মৌলিক ওভারভিউ।

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

ডেমো

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

ওভারভিউ

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

আজ, একটি ট্যাব ব্যবহারকারীর অভিজ্ঞতার অপরিহার্য বিষয় হল একটি বোতাম নেভিগেশন এলাকা যা একটি ডিসপ্লে ফ্রেমে বিষয়বস্তুর দৃশ্যমানতা টগল করে। অনেক ভিন্ন বিষয়বস্তু এলাকা একই স্থান ভাগ করে, কিন্তু শর্তসাপেক্ষে নেভিগেশন নির্বাচিত বোতাম উপর ভিত্তি করে উপস্থাপন করা হয়.

কম্পোনেন্ট কনসেপ্টে ওয়েব প্রয়োগ করা শৈলীর বিশাল বৈচিত্র্যের কারণে কোলাজটি বেশ বিশৃঙ্খল।
গত 10 বছর ধরে ট্যাব উপাদান ওয়েব ডিজাইন শৈলীর একটি কোলাজ

ওয়েব কৌশল

সব মিলিয়ে আমি এই উপাদানটিকে তৈরি করার জন্য বেশ সহজবোধ্য পেয়েছি, কয়েকটি সমালোচনামূলক ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্যগুলির জন্য ধন্যবাদ:

  • উপযুক্ত স্ক্রোল স্টপ অবস্থানের সাথে মার্জিত সোয়াইপ এবং কীবোর্ড ইন্টারঅ্যাকশনের জন্য scroll-snap-points
  • ব্রাউজারের জন্য ইউআরএল হ্যাশের মাধ্যমে গভীর লিঙ্কগুলি ইন-পেজ স্ক্রোল অ্যাঙ্করিং এবং শেয়ারিং সমর্থন পরিচালনা করে
  • <a> এবং id="#hash" উপাদান মার্কআপের সাথে স্ক্রিন রিডার সমর্থন
  • ক্রসফেড ট্রানজিশন এবং ইনস্ট্যান্ট ইন-পেজ স্ক্রোলিং সক্ষম করার জন্য prefers-reduced-motion
  • ইন-ড্রাফ্ট @scroll-timeline ওয়েব বৈশিষ্ট্যটি নির্বাচিত ট্যাবটিকে গতিশীলভাবে আন্ডারলাইন এবং রঙ পরিবর্তন করার জন্য

এইচটিএমএল

মৌলিকভাবে, এখানে ইউএক্স হল: একটি লিঙ্কে ক্লিক করুন, ইউআরএলটি নেস্টেড পৃষ্ঠার অবস্থার প্রতিনিধিত্ব করুন এবং তারপরে ব্রাউজার ম্যাচিং এলিমেন্টে স্ক্রোল করার সাথে সাথে বিষয়বস্তু এলাকা আপডেট দেখুন।

সেখানে কিছু স্ট্রাকচারাল কন্টেন্ট মেম্বার আছে: লিঙ্ক এবং :target এস। আমাদের লিঙ্কগুলির একটি তালিকা প্রয়োজন, যেগুলির জন্য একটি <nav> দুর্দান্ত, এবং <article> উপাদানগুলির একটি তালিকা, যার জন্য একটি <section> দুর্দান্ত। প্রতিটি লিঙ্ক হ্যাশ একটি বিভাগের সাথে মিলবে, ব্রাউজারকে অ্যাঙ্করিংয়ের মাধ্যমে জিনিসগুলি স্ক্রোল করতে দেয়।

একটি লিঙ্ক বোতাম ক্লিক করা হয়, ফোকাস করা বিষয়বস্তু স্লাইডিং

উদাহরণস্বরূপ, একটি লিঙ্কে ক্লিক করলে তা স্বয়ংক্রিয়ভাবে ক্রোম 89-এ :target নিবন্ধে ফোকাস করে, কোন JS প্রয়োজন হয় না। ব্যবহারকারী তারপর বরাবরের মতো তাদের ইনপুট ডিভাইস দিয়ে নিবন্ধের বিষয়বস্তু স্ক্রোল করতে পারেন। এটি প্রশংসাসূচক বিষয়বস্তু, যা মার্কআপে নির্দেশিত।

আমি ট্যাবগুলি সংগঠিত করতে নিম্নলিখিত মার্কআপ ব্যবহার করেছি:

<snap-tabs>
  <header>
    <nav>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
    </nav>
  </header>
  <section>
    <article></article>
    <article></article>
    <article></article>
    <article></article>
  </section>
</snap-tabs>

আমি এই মত href এবং id বৈশিষ্ট্য সহ <a> এবং <article> উপাদানগুলির মধ্যে সংযোগ স্থাপন করতে পারি:

<snap-tabs>
  <header>
    <nav>
      <a href="#responsive"></a>
      <a href="#accessible"></a>
      <a href="#overscroll"></a>
      <a href="#more"></a>
    </nav>
  </header>
  <section>
    <article id="responsive"></article>
    <article id="accessible"></article>
    <article id="overscroll"></article>
    <article id="more"></article>
  </section>
</snap-tabs>

আমি পরবর্তীতে নিবন্ধগুলিকে মিশ্র পরিমাণে লরেমের সাথে এবং লিঙ্কগুলিকে একটি মিশ্র দৈর্ঘ্য এবং শিরোনামগুলির সেট দিয়ে পূরণ করেছি। বিষয়বস্তুর সাথে কাজ করার জন্য, আমরা লেআউট শুরু করতে পারি।

স্ক্রলিং লেআউট

এই উপাদানটিতে 3টি বিভিন্ন ধরণের স্ক্রোল এলাকা রয়েছে:

  • নেভিগেশন (গোলাপী) অনুভূমিকভাবে স্ক্রোলযোগ্য
  • বিষয়বস্তু এলাকা (নীল) অনুভূমিকভাবে স্ক্রোলযোগ্য
  • প্রতিটি নিবন্ধ আইটেম (সবুজ) উল্লম্বভাবে স্ক্রোলযোগ্য।
3টি রঙিন বাক্সে রঙের সাথে মিলিত দিকনির্দেশক তীরগুলি যা স্ক্রোল এলাকার রূপরেখা দেয় এবং তারা যে দিকটি স্ক্রোল করবে তা দেখায়।

স্ক্রোলিং এর সাথে জড়িত 2টি বিভিন্ন ধরণের উপাদান রয়েছে:

  1. একটা জানালা
    সংজ্ঞায়িত মাত্রা সহ একটি বাক্স যাতে overflow সম্পত্তি শৈলী রয়েছে।
  2. একটি oversized পৃষ্ঠ
    এই লেআউটে, এটি তালিকার ধারক: নেভি লিঙ্ক, বিভাগ নিবন্ধ এবং নিবন্ধের বিষয়বস্তু।

<snap-tabs> ট্যাব> লেআউট

আমি যে শীর্ষ স্তরের বিন্যাসটি বেছে নিয়েছি তা হল ফ্লেক্স (ফ্লেক্সবক্স)। আমি column দিকনির্দেশ সেট করেছি, তাই শিরোনাম এবং বিভাগ উল্লম্বভাবে অর্ডার করা হয়েছে। এটি আমাদের প্রথম স্ক্রোল উইন্ডো, এবং এটি ওভারফ্লো লুকিয়ে সবকিছু লুকিয়ে রাখে। শিরোনাম এবং বিভাগ শীঘ্রই ওভারস্ক্রোল নিয়োগ করবে, পৃথক অঞ্চল হিসাবে।

এইচটিএমএল
<snap-tabs>
  <header></header>
  <section></section>
</snap-tabs>
সিএসএস
  snap-tabs {
  display: flex;
  flex-direction: column;

  /* establish primary containing box */
  overflow: hidden;
  position: relative;

  & > section {
    /* be pushy about consuming all space */
    block-size: 100%;
  }

  & > header {
    /* defend against 
needing 100% */ flex-shrink: 0; /* fixes cross browser quarks */ min-block-size: fit-content; } }

রঙিন 3-স্ক্রোল ডায়াগ্রামে ফিরে ইঙ্গিত করা:

  • <header> এখন (গোলাপী) স্ক্রোল কন্টেইনার হতে প্রস্তুত।
  • <section> (নীল) স্ক্রোল কন্টেইনার হতে প্রস্তুত।

VisBug-এর সাহায্যে আমি নীচে যে ফ্রেমগুলি হাইলাইট করেছি সেগুলি আমাদের স্ক্রোল কন্টেনারগুলি তৈরি করা উইন্ডোগুলি দেখতে সাহায্য করে৷

শিরোনাম এবং বিভাগ উপাদানগুলিতে হটপিঙ্ক ওভারলে রয়েছে, যা তারা উপাদানটিতে যে স্থান নেয় তার রূপরেখা দেয়

ট্যাব <header> লেআউট

পরবর্তী লেআউট প্রায় একই: আমি উল্লম্ব ক্রম তৈরি করতে ফ্লেক্স ব্যবহার করি।

এইচটিএমএল
<snap-tabs>
  <header>
    <nav></nav>
    <span class="snap-indicator"></span>
  </header>
  <section></section>
</snap-tabs>
সিএসএস
header {
  display: flex;
  flex-direction: column;
}

.snap-indicator লিঙ্কগুলির গ্রুপের সাথে অনুভূমিকভাবে ভ্রমণ করা উচিত এবং এই হেডার লেআউটটি সেই পর্যায়টি সেট করতে সহায়তা করে। এখানে কোন পরম অবস্থান উপাদান!

nav এবং span.indicator উপাদানগুলির উপর হটপিঙ্ক ওভারলে রয়েছে, যা তারা কম্পোনেন্টে যে স্থান নেয় তার রূপরেখা দেয়

পরবর্তী, স্ক্রোল শৈলী. দেখা যাচ্ছে যে আমরা আমাদের 2টি অনুভূমিক স্ক্রোল এলাকার (শিরোনাম এবং বিভাগ) মধ্যে স্ক্রোল শৈলী ভাগ করতে পারি, তাই আমি একটি ইউটিলিটি ক্লাস তৈরি করেছি, .scroll-snap-x

.scroll-snap-x {
  /* browser decide if x is ok to scroll and show bars on, y hidden */
  overflow: auto hidden;
  /* prevent scroll chaining on x scroll */
  overscroll-behavior-x: contain;
  /* scrolling should snap children on x */
  scroll-snap-type: x mandatory;

  @media (hover: none) {
    scrollbar-width: none;

    &::-webkit-scrollbar {
      width: 0;
      height: 0;
    }
  }
}

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

ট্যাব হেডার <nav> লেআউট

নেভি লিঙ্কগুলিকে একটি লাইনে বিছিয়ে দিতে হবে, কোন লাইন বিরতি ছাড়াই, উল্লম্বভাবে কেন্দ্রীভূত, এবং প্রতিটি লিঙ্ক আইটেম স্ক্রোল-স্ন্যাপ কন্টেইনারে স্ন্যাপ করা উচিত। 2021 CSS-এর জন্য দ্রুত কাজ!

এইচটিএমএল
<nav>
  <a></a>
  <a></a>
  <a></a>
  <a></a>
</nav>
সিএসএস
  nav {
  display: flex;

  & a {
    scroll-snap-align: start;

    display: inline-flex;
    align-items: center;
    white-space: nowrap;
  }
}

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

এনএভির একটি উপাদানের উপর হটপিঙ্ক ওভারলে থাকে, যেখানে তারা কম্পোনেন্টে যে স্থানটি গ্রহণ করে সেই সাথে তারা কোথায় ওভারফ্লো করে তার রূপরেখা দেয়

ট্যাব <section> বিভাগ> লেআউট

এই বিভাগটি একটি ফ্লেক্স আইটেম এবং স্থানের প্রভাবশালী ভোক্তা হতে হবে। এটিতে নিবন্ধগুলি স্থাপন করার জন্য কলাম তৈরি করতে হবে। আবার, CSS 2021 এর জন্য দ্রুত কাজ! block-size: 100% এই উপাদানটিকে যতটা সম্ভব প্যারেন্ট পূরণ করতে প্রসারিত করে, তারপর তার নিজস্ব লেআউটের জন্য, এটি অভিভাবকের প্রস্থের 100% কলামের একটি সিরিজ তৈরি করে। শতাংশ এখানে দুর্দান্ত কাজ করে কারণ আমরা অভিভাবকদের উপর শক্তিশালী সীমাবদ্ধতা লিখেছি।

এইচটিএমএল
<section>
  <article></article>
  <article></article>
  <article></article>
  <article></article>
</section>
সিএসএস
  section {
  block-size: 100%;

  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
}

এটা যেন আমরা বলছি "যতটা সম্ভব উল্লম্বভাবে প্রসারিত করুন, একটি চাপের উপায়ে" (হেডারটি মনে রাখবেন যেটি আমরা flex-shrink: 0 : এটি এই সম্প্রসারণ পুশের বিরুদ্ধে একটি প্রতিরক্ষা), যা একটি সারির উচ্চতা নির্ধারণ করে সম্পূর্ণ উচ্চতার কলামের সেট। auto-flow শৈলী গ্রিডকে সবসময় একটি অনুভূমিক রেখায় বাচ্চাদের বাইরে রাখতে বলে, কোন মোড়ক নেই, ঠিক আমরা যা চাই; অভিভাবক জানালা উপচে পড়া.

নিবন্ধের উপাদানগুলিতে হটপিঙ্ক ওভারলে রয়েছে, তারা উপাদানটিতে যে স্থান গ্রহণ করে এবং কোথায় তারা উপচে পড়ে তার রূপরেখা দেয়

আমার মাঝে মাঝে মাথা গুটিয়ে রাখা কঠিন লাগে! এই বিভাগের উপাদানটি একটি বাক্সে ফিট করা হয়েছে, তবে বাক্সের একটি সেটও তৈরি করেছে৷ আমি আশা করি ভিজ্যুয়াল এবং ব্যাখ্যা সাহায্য করছে.

ট্যাব <article> লেআউট

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

এইচটিএমএল
<article>
  <h2></h2>
  <p></p>
  <p></p>
  <h2></h2>
  <p></p>
  <p></p>
  ...
</article>
সিএসএস
article {
  scroll-snap-align: start;

  overflow-y: auto;
  overscroll-behavior-y: contain;
}

আমি নিবন্ধগুলি তাদের পিতামাতার স্ক্রলারের মধ্যে স্ন্যাপ করা বেছে নিয়েছি। আমি সত্যিই পছন্দ করি যে কীভাবে নেভিগেশন লিঙ্ক আইটেম এবং নিবন্ধ উপাদানগুলি তাদের নিজ নিজ স্ক্রোল কন্টেইনারগুলির ইনলাইন-শুরুতে স্ন্যাপ করে। এটি একটি সুরেলা সম্পর্কের মতো দেখায় এবং অনুভব করে।

নিবন্ধের উপাদান এবং এটির শিশু উপাদানগুলির উপর হটপিঙ্ক ওভারলে রয়েছে, তারা উপাদানটিতে যে স্থানটি গ্রহণ করে এবং তারা যে দিকে প্রবাহিত হয় তার রূপরেখা দেয়

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

3টি স্ক্রোল এলাকা সংকলন

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

3টি স্ক্রলবার দেখানোর জন্য সেট করা হয়েছে, এখন লেআউট স্পেস গ্রাস করছে, এবং আমাদের কম্পোনেন্ট এখনও দুর্দান্ত দেখাচ্ছে

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

DevTools আমাদের এটি কল্পনা করতে সাহায্য করতে পারে:

স্ক্রোল অঞ্চলগুলিতে গ্রিড এবং ফ্লেক্সবক্স টুল ওভারলে রয়েছে, যা তারা উপাদানটিতে যে স্থান নেয় এবং তারা যে দিকে প্রবাহিত হয় তার রূপরেখা দেয়
Chromium Devtools, অ্যাঙ্কর উপাদানে পূর্ণ ফ্লেক্সবক্স নেভি এলিমেন্ট লেআউট, আর্টিকেল এলিমেন্টে পূর্ণ গ্রিড সেকশন লেআউট এবং অনুচ্ছেদ এবং একটি শিরোনাম এলিমেন্টে পূর্ণ আর্টিকেল এলিমেন্ট দেখাচ্ছে।

স্ক্রোল লেআউট সম্পূর্ণ: স্ন্যাপিং, গভীর লিঙ্কযোগ্য, এবং কীবোর্ড অ্যাক্সেসযোগ্য। UX বর্ধন, শৈলী এবং আনন্দের জন্য শক্তিশালী ভিত্তি।

বৈশিষ্ট্য হাইলাইট

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

অ্যানিমেশন

এখানে অ্যানিমেশন কাজের লক্ষ্য হল স্পষ্টভাবে UI প্রতিক্রিয়ার সাথে মিথস্ক্রিয়া লিঙ্ক করা। এটি ব্যবহারকারীকে তাদের (আশা করি) সমস্ত বিষয়বস্তুর নিরবচ্ছিন্ন আবিষ্কারের মাধ্যমে গাইড বা সহায়তা করে। আমি উদ্দেশ্য এবং শর্তসাপেক্ষে গতি যোগ করা হবে. ব্যবহারকারীরা এখন তাদের অপারেটিং সিস্টেমে তাদের গতি পছন্দগুলি নির্দিষ্ট করতে পারে, এবং আমি আমার ইন্টারফেসে তাদের পছন্দগুলির প্রতিক্রিয়া জানাতে পুরোপুরি উপভোগ করি।

আমি নিবন্ধ স্ক্রোল অবস্থানের সাথে একটি ট্যাব আন্ডারলাইন লিঙ্ক করা হবে. স্ন্যাপিং শুধুমাত্র সুন্দর সারিবদ্ধতা নয়, এটি একটি অ্যানিমেশনের শুরু এবং শেষকেও নোঙ্গর করে। এটি <nav> কে রাখে, যা একটি মিনি-ম্যাপের মত কাজ করে, বিষয়বস্তুর সাথে সংযুক্ত থাকে। আমরা CSS এবং JS উভয় থেকে ব্যবহারকারীর গতি পছন্দ পরীক্ষা করব। বিবেচনা করা কয়েক মহান জায়গা আছে!

স্ক্রোল আচরণ

:target এবং element.scrollIntoView() উভয়ের গতি আচরণ উন্নত করার সুযোগ রয়েছে। ডিফল্টরূপে, এটা তাত্ক্ষণিক. ব্রাউজার শুধু স্ক্রোল অবস্থান সেট করে। আচ্ছা, যদি আমরা সেই স্ক্রোল পজিশনে ট্রানজিশন করতে চাই, সেখানে পলক ফেলার পরিবর্তে?

@media (prefers-reduced-motion: no-preference) {
  .scroll-snap-x {
    scroll-behavior: smooth;
  }
}

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

ট্যাব সূচক

এই অ্যানিমেশনের উদ্দেশ্য হল বিষয়বস্তুর অবস্থার সাথে সূচককে যুক্ত করতে সাহায্য করা। আমি সিদ্ধান্ত নিয়েছি যে ব্যবহারকারীরা কম গতি পছন্দ করেন তাদের জন্য ক্রসফেড border-bottom শৈলী এবং একটি স্ক্রোল লিঙ্কযুক্ত স্লাইডিং + কালার ফেইড অ্যানিমেশন ব্যবহারকারীদের জন্য যারা গতির সাথে ঠিক আছে।

Chromium Devtools-এ, আমি পছন্দ টগল করতে পারি এবং 2টি ভিন্ন রূপান্তর শৈলী প্রদর্শন করতে পারি। আমি এটি নির্মাণ মজা একটি টন ছিল.

@media (prefers-reduced-motion: reduce) {
  snap-tabs > header a {
    border-block-end: var(--indicator-size) solid hsl(var(--accent) / 0%);
    transition: color .7s ease, border-color .5s ease;

    &:is(:target,:active,[active]) {
      color: var(--text-active-color);
      border-block-end-color: hsl(var(--accent));
    }
  }

  snap-tabs .snap-indicator {
    visibility: hidden;
  }
}

আমি .snap-indicator লুকিয়ে রাখি যখন ব্যবহারকারী কম গতি পছন্দ করে যেহেতু আমার আর এটির প্রয়োজন নেই। তারপর আমি এটিকে border-block-end শৈলী এবং একটি transition দিয়ে প্রতিস্থাপন করি। এছাড়াও ট্যাব মিথস্ক্রিয়ায় লক্ষ্য করুন যে সক্রিয় নেভি আইটেমটিতে শুধুমাত্র একটি ব্র্যান্ড আন্ডারলাইন হাইলাইট নেই, তবে এটির পাঠ্যের রঙও গাঢ়। সক্রিয় উপাদানটিতে উচ্চতর পাঠ্য রঙের বৈসাদৃশ্য এবং একটি উজ্জ্বল আন্ডারলাইট অ্যাকসেন্ট রয়েছে।

CSS-এর মাত্র কয়েকটি অতিরিক্ত লাইন কাউকে দেখা অনুভব করবে (এই অর্থে যে আমরা চিন্তাভাবনা করে তাদের গতি পছন্দকে সম্মান করছি)। আমি এটা ভালোবাসি.

@scroll-timeline

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

const { matches:motionOK } = window.matchMedia(
  '(prefers-reduced-motion: no-preference)'
);

আমি প্রথমে জাভাস্ক্রিপ্ট থেকে ব্যবহারকারীর গতি পছন্দ চেক করি। যদি এর ফলাফল false হয়, যার অর্থ ব্যবহারকারী হ্রাস গতি পছন্দ করে, তাহলে আমরা স্ক্রোল লিঙ্কিং মোশন প্রভাবগুলির কোনোটি চালাব না।

if (motionOK) {
  // motion based animation code
}

এটি লেখার সময়, @scroll-timeline এর জন্য ব্রাউজার সমর্থন কোনটিই নয়। এটি শুধুমাত্র পরীক্ষামূলক বাস্তবায়ন সহ একটি খসড়া বৈশিষ্ট্য । যদিও এটিতে একটি পলিফিল রয়েছে, যা আমি এই ডেমোতে ব্যবহার করি।

ScrollTimeline

যদিও CSS এবং JavaScript উভয়ই স্ক্রোল টাইমলাইন তৈরি করতে পারে, আমি জাভাস্ক্রিপ্টে নির্বাচন করেছি যাতে আমি অ্যানিমেশনে লাইভ উপাদান পরিমাপ ব্যবহার করতে পারি।

const sectionScrollTimeline = new ScrollTimeline({
  scrollSource: tabsection,  // snap-tabs > section
  orientation: 'inline',     // scroll in the direction letters flow
  fill: 'both',              // bi-directional linking
});

আমি চাই 1টি জিনিস অন্যের স্ক্রোল পজিশন অনুসরণ করুক, এবং একটি ScrollTimeline তৈরি করে আমি স্ক্রোল লিঙ্কের ড্রাইভারকে সংজ্ঞায়িত করি, scrollSource । সাধারণত ওয়েবে একটি অ্যানিমেশন একটি গ্লোবাল টাইম ফ্রেম টিক এর বিপরীতে চলে, কিন্তু মেমরিতে একটি কাস্টম sectionScrollTimeline সহ, আমি সেগুলি পরিবর্তন করতে পারি।

tabindicator.animate({
    transform: ...,
    width: ...,
  }, {
    duration: 1000,
    fill: 'both',
    timeline: sectionScrollTimeline,
  }
);

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

ডায়নামিক কীফ্রেম

@scroll-timeline এর সাথে অ্যানিমেট করার জন্য সত্যিই একটি শক্তিশালী বিশুদ্ধ ঘোষণামূলক CSS উপায় আছে, কিন্তু আমি যে অ্যানিমেশনটি বেছে নিয়েছি তা খুব গতিশীল ছিল। auto প্রস্থের মধ্যে স্থানান্তর করার কোন উপায় নেই, এবং শিশুদের দৈর্ঘ্যের উপর ভিত্তি করে গতিশীলভাবে বেশ কয়েকটি কীফ্রেম তৈরি করার কোন উপায় নেই।

জাভাস্ক্রিপ্ট জানে কিভাবে সেই তথ্যটি পেতে হয়, তাই আমরা নিজেরাই শিশুদের উপর পুনরাবৃত্তি করব এবং রানটাইমে গণনা করা মানগুলি ধরব:

tabindicator.animate({
    transform: [...tabnavitems].map(({offsetLeft}) =>
      `translateX(${offsetLeft}px)`),
    width: [...tabnavitems].map(({offsetWidth}) =>
      `${offsetWidth}px`)
  }, {
    duration: 1000,
    fill: 'both',
    timeline: sectionScrollTimeline,
  }
);

প্রতিটি tabnavitem জন্য, offsetLeft অবস্থানটি ধ্বংস করুন এবং একটি স্ট্রিং প্রদান করুন যা এটিকে একটি translateX মান হিসাবে ব্যবহার করে। এটি অ্যানিমেশনের জন্য 4টি রূপান্তর কীফ্রেম তৈরি করে। প্রস্থের জন্যও একই কাজ করা হয়, প্রত্যেককে জিজ্ঞাসা করা হয় এর গতিশীল প্রস্থ কত এবং তারপর এটি একটি কীফ্রেম মান হিসাবে ব্যবহৃত হয়।

আমার ফন্ট এবং ব্রাউজার পছন্দের উপর ভিত্তি করে এখানে উদাহরণ আউটপুট:

TranslateX কীফ্রেম:

[...tabnavitems].map(({offsetLeft}) =>
  `translateX(${offsetLeft}px)`)

// results in 4 array items, which represent 4 keyframe states
// ["translateX(0px)", "translateX(121px)", "translateX(238px)", "translateX(464px)"]

প্রস্থ কীফ্রেম:

[...tabnavitems].map(({offsetWidth}) =>
  `${offsetWidth}px`)

// results in 4 array items, which represent 4 keyframe states
// ["121px", "117px", "226px", "67px"]

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

সক্রিয় ট্যাব এবং নিষ্ক্রিয় ট্যাব VisBug ওভারলেগুলির সাথে দেখানো হয় যা উভয়ের জন্য পাসিং কনট্রাস্ট স্কোর দেখায়

ব্যবহারকারী তাদের ইন্টারঅ্যাকশনের মাধ্যমে অ্যানিমেশনটি চালায়, সূচকের প্রস্থ এবং অবস্থান এক বিভাগ থেকে অন্য বিভাগে পরিবর্তিত হয়, স্ক্রোল দিয়ে পুরোপুরি ট্র্যাক করে।

আপনি হয়তো লক্ষ্য করেননি, কিন্তু হাইলাইট করা নেভিগেশন আইটেমটি নির্বাচিত হওয়ার কারণে আমি রঙের পরিবর্তনের জন্য খুব গর্বিত।

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

আমি এটি কিভাবে করেছি তা এখানে:

tabnavitems.forEach(navitem => {
  navitem.animate({
      color: [...tabnavitems].map(item =>
        item === navitem
          ? `var(--text-active-color)`
          : `var(--text-color)`)
    }, {
      duration: 1000,
      fill: 'both',
      timeline: sectionScrollTimeline,
    }
  );
});

প্রতিটি ট্যাব নেভি লিঙ্কের জন্য এই নতুন রঙের অ্যানিমেশন প্রয়োজন, আন্ডারলাইন নির্দেশকের মতো একই স্ক্রোল টাইমলাইন ট্র্যাক করা। আমি আগের মতো একই টাইমলাইন ব্যবহার করি: যেহেতু এটির ভূমিকা হল স্ক্রলে একটি টিক নির্গত করা, তাই আমরা যেকোন ধরনের অ্যানিমেশনে সেই টিকটি ব্যবহার করতে পারি। আমি আগে যেমন করেছিলাম, আমি লুপে 4টি কীফ্রেম তৈরি করি এবং রঙ ফেরত দিই।

[...tabnavitems].map(item =>
  item === navitem
    ? `var(--text-active-color)`
    : `var(--text-color)`)

// results in 4 array items, which represent 4 keyframe states
// [
  "var(--text-active-color)",
  "var(--text-color)",
  "var(--text-color)",
  "var(--text-color)",
]

কালার var(--text-active-color) সহ কীফ্রেম লিঙ্কটিকে হাইলাইট করে, এবং অন্যথায় এটি একটি আদর্শ পাঠ্য রঙ। সেখানে নেস্টেড লুপ এটিকে তুলনামূলকভাবে সহজ করে তোলে, কারণ বাইরের লুপটি প্রতিটি নেভিটি আইটেম এবং ভিতরের লুপটি প্রতিটি নেভিটেমের ব্যক্তিগত কীফ্রেম। বাইরের লুপ উপাদানটি ভিতরের লুপের মতো একই কিনা তা আমি পরীক্ষা করি এবং কখন এটি নির্বাচন করা হয় তা জানতে এটি ব্যবহার করুন।

এইটা লিখে অনেক মজা পেলাম। অনেক.

এমনকি আরও জাভাস্ক্রিপ্ট বর্ধন

এটি একটি অনুস্মারক মূল্য যে আমি আপনাকে এখানে যা দেখাচ্ছি তার মূলটি জাভাস্ক্রিপ্ট ছাড়াই কাজ করে। যে বলেছে, আসুন দেখি কিভাবে আমরা এটিকে উন্নত করতে পারি যখন জেএস পাওয়া যায়।

ডিপ লিঙ্ক একটি মোবাইল শব্দ, কিন্তু আমি মনে করি ডিপ লিঙ্কের উদ্দেশ্য এখানে ট্যাবগুলির সাথে পূরণ করা হয়েছে যাতে আপনি সরাসরি একটি ট্যাবের বিষয়বস্তুতে একটি URL শেয়ার করতে পারেন৷ ব্রাউজারটি ইন-পেজ আইডিতে নেভিগেট করবে যা URL হ্যাশের সাথে মেলে। আমি খুঁজে পেয়েছি যে এই onload হ্যান্ডলারটি প্ল্যাটফর্ম জুড়ে প্রভাব তৈরি করেছে।

window.onload = () => {
  if (location.hash) {
    tabsection.scrollLeft = document
      .querySelector(location.hash)
      .offsetLeft;
  }
}

স্ক্রোল শেষ সিঙ্ক্রোনাইজেশন

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

স্ক্রোল শেষের জন্য আমি কীভাবে অপেক্ষা করি তা এখানে: js tabsection.addEventListener('scroll', () => { clearTimeout(tabsection.scrollEndTimer); tabsection.scrollEndTimer = setTimeout(determineActiveTabSection, 100); });

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

const determineActiveTabSection = () => {
  const i = tabsection.scrollLeft / tabsection.clientWidth;
  const matchingNavItem = tabnavitems[i];

  matchingNavItem && setActiveTab(matchingNavItem);
};

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

const setActiveTab = tabbtn => {
  tabnav
    .querySelector(':scope a[active]')
    .removeAttribute('active');

  tabbtn.setAttribute('active', '');
  tabbtn.scrollIntoView();
};

সক্রিয় ট্যাব সেট করা যে কোনো বর্তমানে সক্রিয় ট্যাব সাফ করে শুরু হয়, তারপর আগত নেভি আইটেমটিকে সক্রিয় অবস্থা বৈশিষ্ট্য প্রদান করে। scrollIntoView() এর কলে CSS-এর সাথে একটি মজার মিথস্ক্রিয়া রয়েছে যা লক্ষ্য করার মতো।

.scroll-snap-x {
  overflow: auto hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;

  @media (prefers-reduced-motion: no-preference) {
    scroll-behavior: smooth;
  }
}

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

উপসংহার

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

আসুন আমাদের পদ্ধতির বৈচিত্র্য আনুন এবং ওয়েবে তৈরি করার সমস্ত উপায় শিখি। একটি ত্রুটি তৈরি করুন, আমাকে আপনার সংস্করণ টুইট করুন , এবং আমি এটিকে নীচের সম্প্রদায়ের রিমিক্স বিভাগে যোগ করব৷

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