কন্টেইনার কোয়েরি পলিফিলের ভিতরে

জেরাল্ড মোনাকো
Gerald Monaco

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

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

ফণা অধীনে

ট্রান্সপিলেশন

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

ট্রান্সপিলেশনের প্রথম ধাপ হল টপ-লেভেল @container নিয়মকে @media ক্যোয়ারীতে রূপান্তর করা। এটি বেশিরভাগই নিশ্চিত করে যে বিষয়বস্তু একসাথে গোষ্ঠীবদ্ধ থাকে। যেমন, CSSOM API ব্যবহার করার সময় এবং CSS সোর্স দেখার সময়।

আগে
@container (width > 300px) {
  /* content */
}
পরে
@media all {
  /* content */
}

কন্টেইনার ক্যোয়ারী করার আগে, CSS-এর কাছে কোনো লেখকের জন্য নিয়মের গ্রুপগুলিকে ইচ্ছামত সক্ষম বা অক্ষম করার উপায় ছিল না। এই আচরণটি পলিফিল করার জন্য, একটি কন্টেইনার কোয়েরির ভিতরের নিয়মগুলিকেও পরিবর্তন করতে হবে। প্রতিটি @container তার নিজস্ব অনন্য আইডি দেওয়া হয় (উদাহরণস্বরূপ, 123 ), যা প্রতিটি নির্বাচককে এমনভাবে রূপান্তর করতে ব্যবহৃত হয় যে এটি শুধুমাত্র তখনই প্রযোজ্য হবে যখন এই আইডি সহ উপাদানটির একটি cq-XYZ বৈশিষ্ট্য থাকে। রানটাইমে পলিফিল দ্বারা এই বৈশিষ্ট্যটি সেট করা হবে।

আগে
@container (width > 300px) {
  .card {
    /* ... */
  }
}
পরে
@media all {
  .card:where([cq-XYZ~="123"]) {
    /* ... */
  }
}

:where(...) ছদ্ম-শ্রেণীর ব্যবহার লক্ষ্য করুন। সাধারণত, একটি অতিরিক্ত বৈশিষ্ট্য নির্বাচক সহ নির্বাচকের নির্দিষ্টতা বৃদ্ধি করবে। ছদ্ম-শ্রেণীর সাথে, মূল নির্দিষ্টতা সংরক্ষণের সময় অতিরিক্ত শর্ত প্রয়োগ করা যেতে পারে। কেন এটি গুরুত্বপূর্ণ তা দেখতে, নিম্নলিখিত উদাহরণটি বিবেচনা করুন:

@container (width > 300px) {
  .card {
    color: blue;
  }
}

.card {
  color: red;
}

এই CSS প্রদত্ত, .card ক্লাসের একটি উপাদানের সর্বদা color: red , কারণ পরবর্তী নিয়মটি সর্বদা একই নির্বাচক এবং নির্দিষ্টতার সাথে পূর্ববর্তী নিয়মটিকে ওভাররাইড করবে। প্রথম নিয়মটি স্থানান্তরিত করা এবং একটি অতিরিক্ত অ্যাট্রিবিউট সিলেক্টর ছাড়া :where(...) এর ফলে নির্দিষ্টতা বৃদ্ধি পাবে এবং color: blue ভুলভাবে প্রয়োগ করা হবে।

যাইহোক, :where(...) ছদ্ম-শ্রেণী মোটামুটি নতুন । যে ব্রাউজারগুলি এটি সমর্থন করে না তাদের জন্য, পলিফিল একটি নিরাপদ এবং সহজ সমাধান প্রদান করে: আপনি ইচ্ছাকৃতভাবে আপনার @container নিয়মগুলিতে একটি ডামি :not(.container-query-polyfill) নির্বাচক যুক্ত করে আপনার নিয়মের নির্দিষ্টতা বৃদ্ধি করতে পারেন:

আগে
@container (width > 300px) {
  .card {
    color: blue;
  }
}

.card {
  color: red;
}
পরে
@container (width > 300px) {
  .card:not(.container-query-polyfill) {
    color: blue;
  }
}

.card {
  color: red;
}

এটির বেশ কয়েকটি সুবিধা রয়েছে:

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

ট্রান্সপিলেশনের সময়, পলিফিল এই ডামিটিকে একই নির্দিষ্টতার সাথে অ্যাট্রিবিউট সিলেক্টর দিয়ে প্রতিস্থাপন করবে। কোনো বিস্ময় এড়াতে, পলিফিল উভয় নির্বাচক ব্যবহার করে: উপাদানটি পলিফিল বৈশিষ্ট্য গ্রহণ করবে কিনা তা নির্ধারণ করতে মূল উৎস নির্বাচক ব্যবহার করা হয় এবং স্টাইলিংয়ের জন্য ট্রান্সপিলড নির্বাচক ব্যবহার করা হয়।

ছদ্ম-উপাদান

একটি প্রশ্ন আপনি নিজেকে জিজ্ঞাসা করতে পারেন: পলিফিল যদি অনন্য ধারক আইডি 123 অন্তর্ভুক্ত করার জন্য একটি উপাদানে কিছু cq-XYZ বৈশিষ্ট্য সেট করে, তাহলে কীভাবে ছদ্ম-উপাদানগুলি, যেগুলিতে বৈশিষ্ট্যগুলি সেট করা যায় না, সমর্থন করা যায়?

ছদ্ম-উপাদানগুলি সর্বদা DOM-এ একটি বাস্তব উপাদানের সাথে আবদ্ধ থাকে, যাকে বলা হয় উদ্ভূত উপাদান । ট্রান্সপিলেশনের সময়, শর্তসাপেক্ষ নির্বাচকটি পরিবর্তে এই আসল উপাদানটিতে প্রয়োগ করা হয়:

আগে
@container (width > 300px) {
  #foo::before {
    /* ... */
  }
}
পরে
@media all {
  #foo:where([cq-XYZ~="123"])::before {
    /* ... */
  }
}

#foo::before:where([cq-XYZ~="123"]) (যা অবৈধ হবে) তে রূপান্তরিত হওয়ার পরিবর্তে, শর্তসাপেক্ষ নির্বাচককে মূল উপাদানের শেষে সরানো হয়, #foo

যাইহোক, যে সব প্রয়োজন হয় না. একটি ধারককে এটির মধ্যে নেই এমন কিছু পরিবর্তন করার অনুমতি দেওয়া হয় না (এবং একটি ধারক নিজের ভিতরে থাকতে পারে না), তবে বিবেচনা করুন যে #foo নিজেই কন্টেইনার উপাদানটি জিজ্ঞাসা করা হলে ঠিক কী হবে। #foo[cq-XYZ] অ্যাট্রিবিউট ভুলভাবে পরিবর্তিত হবে এবং যেকোনো #foo নিয়ম ভুলভাবে প্রয়োগ করা হবে।

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

আগে
@container (width > 300px) {
  #foo,
  #foo::before {
    /* ... */
  }
}
পরে
@media all {
  #foo:where([cq-XYZ-A~="123"]),
  #foo:where([cq-XYZ-B~="123"])::before {
    /* ... */
  }
}

যেহেতু একটি কন্টেইনার কখনই প্রথম অ্যাট্রিবিউট ( cq-XYZ-A ) প্রয়োগ করবে না, তাই প্রথম নির্বাচক তখনই মিলবে যদি একটি ভিন্ন প্যারেন্ট কন্টেইনার কন্টেইনার শর্ত পূরণ করে এবং এটি প্রয়োগ করে।

ধারক আপেক্ষিক ইউনিট

কন্টেইনার প্রশ্নগুলি কয়েকটি নতুন ইউনিটের সাথেও আসে যা আপনি আপনার CSS-এ ব্যবহার করতে পারেন, যেমন cqw এবং cqh নিকটতম উপযুক্ত প্যারেন্ট কন্টেইনারের প্রস্থ এবং উচ্চতার 1% (যথাক্রমে) জন্য। এগুলিকে সমর্থন করার জন্য, ইউনিটটি CSS কাস্টম বৈশিষ্ট্য ব্যবহার করে একটি calc(...) অভিব্যক্তিতে রূপান্তরিত হয়। পলিফিল কন্টেইনার এলিমেন্টে ইনলাইন শৈলীর মাধ্যমে এই বৈশিষ্ট্যগুলির জন্য মান সেট করবে।

আগে
.card {
  width: 10cqw;
  height: 10cqh;
}
পরে
.card {
  width: calc(10 * --cq-XYZ-cqw);
  height: calc(10 * --cq-XYZ-cqh);
}

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

/* Element with a horizontal writing mode */
--cq-XYZ-cqi: var(--cq-XYZ-cqw);
--cq-XYZ-cqb: var(--cq-XYZ-cqh);

/* Element with a vertical writing mode */
--cq-XYZ-cqi: var(--cq-XYZ-cqh);
--cq-XYZ-cqb: var(--cq-XYZ-cqw);

এখন, ইউনিটগুলিকে আগের মতোই উপযুক্ত CSS কাস্টম প্রপার্টিতে রূপান্তরিত করা যেতে পারে।

বৈশিষ্ট্য

কন্টেইনার কোয়েরিগুলি container-type এবং container-name মতো কয়েকটি নতুন CSS বৈশিষ্ট্য যোগ করে। যেহেতু getComputedStyle(...) এর মতো APIগুলি অজানা বা অবৈধ বৈশিষ্ট্যগুলির সাথে ব্যবহার করা যায় না, তাই পার্স করার পরে এগুলিও CSS কাস্টম বৈশিষ্ট্যে রূপান্তরিত হয়। যদি একটি প্রপার্টি পার্স করা না যায় (উদাহরণস্বরূপ, কারণ এতে একটি অবৈধ বা অজানা মান রয়েছে), ব্রাউজার পরিচালনা করার জন্য এটিকে একা রেখে দেওয়া হয়।

আগে
.card {
  container-name: card-container;
  container-type: inline-size;
}
পরে
.card {
  --cq-XYZ-container-name: card-container;
  --cq-XYZ-container-type: inline-size;
}

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

আগে
@supports (container-type: inline-size) {
  /* ... */
}
পরে
@supports (--cq-XYZ-container-type: inline-size) {
  /* ... */
}

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

* {
  --cq-XYZ-container-name: none;
  --cq-XYZ-container-type: normal;
}

সর্বোত্তম অনুশীলন

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

প্রাথমিক লোডের সময়, পলিফিল পৃষ্ঠাটি লেআউট করার আগে অনেক কিছু ঘটতে হবে:

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

যদি এই উদ্বেগগুলি পলিফিল দ্বারা সাবধানে সমাধান না করা হয়, তাহলে এটি সম্ভাব্যভাবে আপনার মূল ওয়েব ভাইটালগুলিকে প্রত্যাহার করতে পারে৷

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

@supports not (container-type: inline-size) {
  #content {
    visibility: hidden;
  }
}

এটা বাঞ্ছনীয় যে আপনি এটিকে একটি বিশুদ্ধ CSS লোডিং অ্যানিমেশনের সাথে একত্রিত করুন, যা আপনার (লুকানো) বিষয়বস্তুর উপর সম্পূর্ণরূপে অবস্থান করে, দর্শককে কিছু ঘটছে তা জানাতে। আপনি এখানে এই পদ্ধতির একটি সম্পূর্ণ ডেমো খুঁজে পেতে পারেন।

এই পদ্ধতিটি বেশ কয়েকটি কারণে সুপারিশ করা হয়:

  • একটি বিশুদ্ধ CSS লোডার নতুন ব্রাউজার সহ ব্যবহারকারীদের জন্য ওভারহেড কমিয়ে দেয়, যখন পুরানো ব্রাউজার এবং ধীর নেটওয়ার্কে তাদের হালকা প্রতিক্রিয়া প্রদান করে।
  • visibility: hidden , আপনি লেআউট শিফট এড়ান।
  • পলিফিল লোড হওয়ার পরে, এই @supports শর্তটি পাস হওয়া বন্ধ হয়ে যাবে এবং আপনার সামগ্রী প্রকাশ করা হবে।
  • কনটেইনার প্রশ্নের জন্য অন্তর্নির্মিত সমর্থন সহ ব্রাউজারগুলিতে, শর্তটি কখনই পাস হবে না, এবং তাই পৃষ্ঠাটি প্রথম-পেইন্টে প্রত্যাশিত হিসাবে প্রদর্শিত হবে।

উপসংহার

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

আপনি এটি দিয়ে যে আশ্চর্যজনক জিনিসগুলি তৈরি করবেন তা দেখতে এবং অভিজ্ঞতার জন্য আমরা অপেক্ষা করতে পারি না।