কয়েক বছর আগে, আমি একটি ড্যাশবোর্ড তৈরি করার জন্য বসেছিলাম। খুব আহামরি কিছু নয়—শুধু একটি ফিক্সড সাইডবার, একটি মেইন কন্টেন্ট এরিয়া এবং একটি ফুটার। Flexbox ছিল স্পষ্টতই সঠিক পছন্দ বলে মনে হয়েছিল, এবং শুরুতে এটি ঠিকঠাক কাজ করছিল। তারপর আমি মেইন সেকশনে এক সারি কার্ড যোগ করলাম। পুরো লেআউটটি ভেঙে পড়ল। আমি পরবর্তী তিন ঘণ্টা flex-grow রেশিও এবং নেস্টেড পার্সেন্টেজ উইডথ নিয়ে লড়াই করতে করতে পারলাম না, দেখলাম যে আমি যতই প্যাডিং কমাচ্ছি না কেন, কন্টেইনারগুলো লাইনে আসতে চাইছে না। মনে হচ্ছিল পুরো পেজটি যেন যেকোনো মুহূর্তে ভেঙে পড়তে পারে এমন একটি টাওয়ার।
সেই তিক্ত অভিজ্ঞতা আমাকে আধুনিক CSS লেআউট সম্পর্কে সবচেয়ে গুরুত্বপূর্ণ একটি জিনিস শিখিয়েছে: Flexbox এবং Grid একে অপরের প্রতিদ্বন্দ্বী নয়। এগুলো ভিন্ন ভিন্ন কাজের জন্য তৈরি টুল, এবং বেশিরভাগ ব্যর্থ লেআউট তৈরি হয় ভুল টুল ব্যবহার করার কারণে।
পার্থক্যটি হলো ডাইমেনশনের
Flexbox-কে একটি করিডোর হিসেবে ভাবুন। আইটেমগুলো একটি নির্দিষ্ট দিকে প্রবাহিত হয়, হয় একটি রো (row) হিসেবে অথবা একটি কলাম (column) হিসেবে। এটি এক-মাত্রিক (one-dimensional) বিন্যাসের জন্য তৈরি। ব্রাউজার কন্টেন্টটি দেখে, তারপর সিদ্ধান্ত নেয় যে সেই একক অক্ষ বরাবর এটিকে কীভাবে স্ট্রেচ, শ্রिंक বা অ্যালাইন করতে হবে। এটি এমন পরিস্থিতির জন্য Flexbox-কে নিখুঁত করে তোলে যেখানে কন্টেন্ট নিজেই লেআউট নির্ধারণ করে। একটি নেভিগেশন বার, ফর্ম ফিল্ডের একটি স্ট্যাক, বা ট্যাগগুলোর একটি সেট যেগুলোর সমান স্পেসিং প্রয়োজন—সবই একটি flex কন্টেইনারের মধ্যে স্বাভাবিকভাবে বসে কারণ তাদের লজিক একটি লাইনে থাকে।
অন্যদিকে, Grid হলো একটি ফ্লোর প্ল্যান। এটি কঠোরভাবে দ্বি-মাত্রিক (two-dimensional), যা একই সাথে রো এবং কলাম পরিচালনা করে। আপনি প্রথমে কাঠামোটি সংজ্ঞায়িত করেন, তারপর তার ভেতরে আইটেমগুলো বসান। এটি পুরো পেজের আর্কিটেকচারের জন্য Grid-কে আদর্শ করে তোলে—যেখানে আপনার ভার্টিক্যাল এবং হরিজন্টাল পজিশনিং একসাথে নিয়ন্ত্রণ করার প্রয়োজন হয়। আপনি যখন নেস্টেড Flexbox কন্টেইনারের মাধ্যমে একটি জটিল দ্বি-মাত্রিক ডিজাইন করার চেষ্টা করেন, তখন আপনি গভীর মার্কআপ, ভঙ্গুর র্যাপার এবং জটিল গণিতের জালে আটকে যান, যা একটি অতিরিক্ত এলিমেন্ট যোগ করার সাথে সাথেই ভেঙে পড়ে।
Flexbox এখনও তার প্রয়োজনীয়তা প্রমাণ করে
প্রতিটি flex কন্টেইনারকে Grid দিয়ে প্রতিস্থাপন করার জন্য তাড়াহুড়ো করবেন না। ব্যক্তিগত কম্পোনেন্টের ক্ষেত্রে Flexbox প্রায়ই বেশি পরিষ্কার এবং সহজবোধ্য হয়। যদি আপনার একটি কার্ড ফুটার থাকে যাতে দুটি বাটন আছে এবং আপনি একটিকে বাম দিকে এবং অন্যটিকে ডান দিকে অ্যালাইন করতে চান, তবে justify-content: space-between ঠিক সেটাই করবে যা আপনি চাইছেন। যদি আপনার একটি বাটন (যার উচ্চতা অজানা) এর ভেতরে একটি আইকনকে ভার্টিক্যালি সেন্টার করতে হয়, তবে align-items: center হলো সবচেয়ে সহজ পথ। পরিবর্তনশীল কন্টেন্ট—যেমন বিভিন্ন দৈর্ঘ্যের নামযুক্ত ইউজার ব্যাজের একটি সারি—Flexbox-এর মধ্যে স্বাচ্ছন্দ্যে ফিট হয় কারণ এটি কন্টেন্ট-ফার্স্ট (content-first)। কন্টেইনারটি তার ভেতরে থাকা জিনিসের সাথে নিজেকে মানিয়ে নেয়।
Grid হলো কন্টেইনার-ফার্স্ট (container-first)। আপনি ব্রাউজারকে বলে দেন সেখানে কয়টি ট্র্যাক আছে এবং সেগুলো কতটা বড় হবে, তারপর আপনি সেই সেলগুলোতে আইটেমগুলো বসান। যদি আপনার লেআউটটি কেবল স্পেস শেয়ার করা সমান্তরাল আইটেমগুলোর একটি একক সারি হয়, তবে Grid ব্যবহার করা মানে অপ্রয়োজনীয় জটিলতা তৈরি করা।
পেজ লেআউটের জন্য Grid-ই উপযুক্ত
এখানেই Grid নিয়ন্ত্রণ নেয়। আমার ড্যাশবোর্ড তৈরির সেই দুঃস্বপ্নটির কথা মনে আছে? কাঠামোটি শুরু থেকেই দেখতে এমন হওয়া উচিত ছিল:
.page {
display: grid;
min-height: 100vh;
grid-template-rows: auto 1fr auto;
grid-template-columns: 200px 1fr;
}
.header { grid-row: 1; grid-column: 1 / -1; }
.sidebar { grid-row: 2; grid-column: 1; }
.main { grid-row: 2; grid-column: 2; }
.footer { grid-row: 3; grid-column: 1 / -1; }
দেখুন এখানে কী ঘটছে। .page কন্টেইনারটি তিনটি রো এবং দুটি কলাম তৈরি করে। প্রথম রোটি auto ব্যবহারের কারণে হেডার যা ধারণ করে তার আকার অনুযায়ী নিজেকে সেট করে নেয়। মাঝের রোটি 1fr ব্যবহার করে সমস্ত অবশিষ্ট জায়গা দখল করে নেয়। ফুটারটি শেষ রোতে বসে এবং এটি তার নিজস্ব কন্টেন্টের আকার অনুযায়ী নির্ধারিত হয়। ইতিমধ্যে, সাইডবারটি ২০০ পিক্সেল চওড়া হয়ে স্থির থাকে এবং মেইন এরিয়া বাকি অংশটুকু পূরণ করে।
প্লেসমেন্ট লজিকটিই হলো আসল স্বস্তি। হেডারটি কলাম লাইন ১ থেকে লাইন -১ পর্যন্ত বিস্তৃত, যার মানে আপনি পরে যতগুলো কলামই যোগ করুন না কেন, এটি উভয় কলাম জুড়ে বিস্তৃত থাকবে। সাইডবার এবং মেইন কন্টেন্ট রো ২ শেয়ার করে কিন্তু আলাদা আলাদা কলাম দখল করে। ফুটারটি রো ৩-এ পূর্ণ প্রস্থে ফিরে আসে। চাইল্ড এলিমেন্টগুলোর ওপর আপনার পার্সেন্টেজ গণিত করার প্রয়োজন নেই। উচ্চতা নিয়ে লড়াই করার জন্য নেস্টেড র্যাপারের প্রয়োজন নেই। এক জায়গায় সাইডবারের প্রস্থ পরিবর্তন করুন, এবং মেইন এরিয়া স্বয়ংক্রিয়ভাবে অ্যাডজাস্ট হয়ে যাবে। পুরো লেআউটটি একটি একক সিস্টেম হিসেবে কাজ করে।
grid-template-areas দিয়ে পঠনযোগ্যতা বৃদ্ধি
আরও স্পষ্টতার জন্য, আপনি আপনার সেকশনগুলোর নাম দিতে পারেন। লাইন নম্বর ম্যানেজ করার পরিবর্তে, আপনি একটি ভিজ্যুয়াল ম্যাপ লিখতে পারেন:
.page {
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.header { grid-area: header; }
.main { grid-area: main; }
এখন আপনার স্টাইলশিটটি একটি ওয়্যারফ্রেমের মতো পড়া যাবে। আপনি যদি কখনও চান যে ভিন্ন কোনো ব্রেকপয়েন্টে (breakpoint) সাইডবারটি ডান দিকে দেখা যাক, তবে আপনি টেমপ্লেট স্ট্রিংয়ের মাত্র দুটি শব্দ পরিবর্তন করবেন। নেস্টেড Flexbox কন্টেইনারের স্তূপের মধ্যে এই ধরণের স্ট্রাকচারাল পঠনযোগ্যতা অর্জন করা অসম্ভব।
দুটি কঠিন শিক্ষা
Grid কোনো জাদু নয়। এমন দুটি ভুল আছে যা খুব দ্রুত আপনার লেআউট নষ্ট করে দিতে পারে।
প্রথমটি হলো ইউনিটের অগোছালো ব্যবহার। আপনি যদি grid-template-columns: 1fr 1fr 1fr সংজ্ঞায়িত করেন কিন্তু আপনার ডিজাইনে কন্টেন্টের জন্য মাত্র দুটি কলামের প্রয়োজন হয়, তবে সেই তৃতীয় ট্র্যাকটি তখনও বিদ্যমান থাকবে। এটি হয় খালি থেকে এমন একটি গ্যাপ তৈরি করবে যা আপনি আশা করেননি, অথবা এটি আপনার আসল কন্টেন্টকে এমনভাবে চেপে বসতে বাধ্য করবে যা আপনার ডিজাইন নষ্ট করে দেবে। সুপরিকল্পিত হোন। যখন আপনি দুটি কলাম বোঝাতে চান, তখন লিখুন repeat(2, 1fr)।
