একটা কম্পোনেন্ট লাইব্রেরি সাধারণত একভাবেই ভাঙে — এক জায়গায় সুন্দর দেখায়, অন্য জায়গায় বসালেই ফাঁকা জায়গার হিসাব মেলে না।
কারণটা প্রায় সবসময় একই। কার্ডের নিজের CSS-এ margin-bottom: 24px লেখা আছে।
সমস্যাটা মালিকানার
একটা কম্পোনেন্টের ভেতরের ফাঁকা জায়গা — প্যাডিং, আইকন আর লেখার দূরত্ব, শিরোনাম আর বডির গ্যাপ — কম্পোনেন্টেরই সম্পত্তি। ওটা তার ডিজাইনের অংশ, সব জায়গায় এক থাকা উচিত।
কিন্তু কম্পোনেন্টের বাইরের ফাঁকা জায়গা তার নয়। ওটা লেআউটের সিদ্ধান্ত, আর লেআউট জানে কম্পোনেন্টটা কোথায় বসছে — গ্রিডে, সাইডবারে, নাকি ডায়ালগের ভেতরে একা। কম্পোনেন্ট সেটা জানে না, জানার কথাও না।
চাইল্ড যখন নিজের বাইরের মার্জিন নিজে ঠিক করে, তখন সে এমন একটা প্রশ্নের উত্তর দিয়ে ফেলে যেটা তাকে কেউ করেনি।
কোডে পার্থক্যটা
চাইল্ড মার্জিন দিচ্ছে
<!-- Card.vue -->
<template>
<article class="mb-6 rounded-xl border p-5">
<slot />
</article>
</template>
<!-- ব্যবহার -->
<Card v-for="item in items" :key="item.id" />
প্যারেন্ট গ্যাপ দিচ্ছে
<!-- Card.vue -->
<template>
<article class="rounded-xl border p-5">
<slot />
</article>
</template>
<!-- ব্যবহার -->
<div class="flex flex-col gap-6">
<Card v-for="item in items" :key="item.id" />
</div>
প্রথমটায় লিস্টের শেষ কার্ডের নিচেও ২৪ পিক্সেল ঝুলে থাকে, যেটা কেউ চায়নি। ঠিক করতে গিয়ে :last-child { margin-bottom: 0 } লেখা হয়, তারপর গ্রিডে বসালে আবার অন্য নিয়ম, তারপর ডায়ালগে আরেকটা। তিনটা ব্যতিক্রম লেখার পর কম্পোনেন্টটার স্পেসিং আর কেউ পড়ে বুঝতে পারে না।
দ্বিতীয়টায় ব্যতিক্রম নেই, কারণ নিয়মটাই নেই। প্যারেন্ট gap দিচ্ছে, শেষ আইটেমের পরে গ্যাপ বসে না — এটা gap-এর সংজ্ঞা, কারও লেখা নিয়ম নয়।
মার্জিন কলাপস আরেকটা কারণ
লম্বালম্বি মার্জিন পাশাপাশি বসলে দুটো যোগ হয় না, বড়টা টিকে থাকে। এটা CSS-এর পুরোনো আচরণ, ভুল নয় — কিন্তু কম্পোনেন্ট লেখার সময় এটাই সবচেয়ে বেশি বিভ্রান্ত করে।
উপরের কার্ডের margin-bottom: 24px আর নিচের কার্ডের margin-top: 16px মিলে ফাঁক হয় ২৪, ৪০ নয়। মানে আপনি যে সংখ্যাটা লিখেছেন, স্ক্রিনে সেটা নাও থাকতে পারে — নির্ভর করছে প্রতিবেশী কে।
gap কলাপস করে না। যা লিখবেন তাই পাবেন।
Quick check
একটা কার্ড কম্পোনেন্টে `margin-bottom: 24px` দেওয়া আছে। সেটাকে একটা `display: grid` কন্টেইনারে `gap: 16px` দিয়ে বসানো হলো। দুটো কার্ডের মাঝে ফাঁক কত হবে?
ভেতরের স্পেসিং অবশ্যই কম্পোনেন্টের
উল্টো দিকটাও সমান গুরুত্বপূর্ণ। কম্পোনেন্টের ভেতরের প্যাডিং প্যারেন্টের হাতে ছেড়ে দিলে একই বোতাম দশ জায়গায় দশ রকম হয়।
size একটা বন্ধ তালিকা হওয়া উচিত — তিনটা মান, তিনটাই কম্পোনেন্টের ভেতরে লেখা। বাইরে থেকে ক্লাস দিয়ে প্যাডিং বদলানো মানে তালিকার বাইরে একটা চতুর্থ সাইজ তৈরি করা, যেটা কোথাও লেখা নেই:
size
variant
<UiButton size="sm" variant="primary">সংরক্ষণ করুন</UiButton>উপরের প্রতিটা অবস্থার জন্য নিচে যে মার্কআপটা দেখাচ্ছে, সেটাই যথেষ্ট। কোনো class="px-6" নেই — কারণ দরকার হলে সেটা size-এর তালিকায় যোগ করার আলোচনা, ব্যবহারের জায়গায় চুপচাপ ওভাররাইড নয়।
পুরোনো কোডে কীভাবে ঢুকবেন
একবারে সব বদলানোর দরকার নেই। যে কম্পোনেন্টটা সবচেয়ে বেশি জায়গায় ব্যবহার হয়েছে, সেটা দিয়ে শুরু করলেই সবচেয়ে বেশি ব্যতিক্রম মুছে যায়।
একটা কম্পোনেন্ট থেকে মার্জিন সরানোর ধাপ
0/6 শেষ
কাজটা ছোট, কিন্তু ফলটা কোড কমার চেয়ে বড়। এরপর থেকে কেউ কম্পোনেন্টটা নতুন কোনো জায়গায় বসালে তাকে আর জিজ্ঞেস করতে হয় না, "এটার নিচে কি এমনিতেই ফাঁক আছে?"
সম্পর্কিত লেখা
setTimeout(fn, 0) সাথে সাথে চলে না কেন
ম্যাক্রোটাস্ক, মাইক্রোটাস্ক আর রেন্ডারিং — ইভেন্ট লুপের ধাপগুলো জানলে অ্যাসিঙ্ক কোডের ক্রম আর অনুমান করতে হয় না।
মানুষ কেন অচেনা কারো কাছ থেকে কিনতে দ্বিধা করে — Trust Signal যেভাবে সেল বাড়ায়
একই ল্যান্ডিং পেজ, একই দাম, একই প্রোডাক্ট — শুধু নিচে তিনটা রিভিউ যোগ করলেই কনভার্শন বদলে যায়। এটা কাকতালীয় না, মানুষ সিদ্ধান্ত নেওয়ার সময় অন্যদের আচরণ দেখেই ভরসা করে।
প্রোডাক্ট বেচবেন না, সমস্যার সমাধান বেচুন — Customer আসলে কী 'hire' করছে
একজন কাস্টমার মিল্কশেক কেনে না — সকালের বোরিং গাড়ি-চালানোর সময়টাকে সহনীয় করার একটা উপায় কেনে। প্রোডাক্টের ফিচার লিস্ট না, এই "job"-টা বুঝলেই সেল বাড়ে।
মাসে একটা কাজের ইমেইল
ডিজাইন সিস্টেম প্যাটার্ন, ফ্রন্ট-এন্ড টেকনিক আর লার্ন প্ল্যাটফর্মের নোট। কোনো প্রচার নেই, অন্যের লিংকের সংকলনও নেই।
