تراز افقی و عمودی المان‌های صفحه با CSS: چطور عذاب نکشیم؟

وندا نوژن

یکی از کابوس‌های همیشگی فرانت‌اندکارها اینست که بعد از تحویل پروژه، کارفرما تازه یاد تغییرات اساسی در ساختار صفحات می‌افتد و مطلقا هم زیر بار نمی‌رود که چنین تغییراتی وقت‌گیرند، کار دوباره می‌طلبند و بنابراین هزینه مجزا دارند. بنا به تجربه در اکثر موارد کارفرما خودش هم نمی‌داند دقیقا چه می‌خواهد. بنابراین هر بار «ایده»های جدیدی از این‌ور و آن‌ور به ذهنش خطور می‌کند. زمانی که یک ایده در حال اجرا و اتمام است، ناگهان ایده مشعشع بعدی از راه می‌رسد. وقتی پروژه بسته شد و طراح می‌خواهد نفس راحت بکشد، حالا تازه نوبت به خرده‌فرمایش‌ها و اصلاحات جزئی می‌رسد: اینو بیار پایین، اونو بذار چپ، رنگ فلان قسمت رو تغییر بده، این فونت مناسب نیست و... در بین این فهرست فرمایشات، همیشه المانی در صفحه یافت می‌شود که باید وسط قرار بگیرد. خلاصه به قول توسعه‌دهنده‌ای، کاوشگر ناسا روی مریخ فرود آمد، ولی ما هنوز مشغول «وسط‌چین» کردنیم!

در CSS که به طور کلی زبان ساده‌ای است، وسط‌چین کردن جزو کارهای نسبتا دشوار محسوب می‌شود. برای این کار روش‌های مختلفی وجود دارد، منتها اینکه کدام روش را انتخاب کنیم بستگی دارد به اینکه اولا قصد تغییر کدام المان HTML را داریم و ثانیا این وسط‌چینی قرار است به طور افقی باشد یا عمودی.

تراز افقی

معمولا وسط‌چین کردن افقی المان‌ها ساده‌تر از حالت عمودی است. بنابراین ابتدا از حالت تراز افقی المان‌های p و div شروع می‌کنیم و سپس به حالت عمودی می‌رسیم.

  • تراز افقی متن (p)

وسط‌چین کردن متن (افقی) ساده‌ترین و بی‌دردسرترین حالت ممکن است. کافیست از ویژگی text-align استفاده کنیم و به آن ارزش center بدهیم. برای مثال:

<div class=&quotcontainer&quot>
  <p>سلام دنیا! (وسط چین)</p>
</div>


p {text-align: center;}
  • تراز افقی div با margin:auto

اگر بخواهیم عناصری را که حالت بلوک دارند (مثل div) به صورت افقی تراز کنیم تا وسط قرار بگیرند، می‌توانیم از ویژگی margin با مقدار 0 auto استفاده کنیم. فرضا می‌خواهیم یک div فرزند را در div والد به صورت افقی تراز کنیم:

<div class=&quotcontainer&quot>
  <div class=&quotchild&quot></div>
</div>

در این حالت دستور بالا در استایل div فرزند کفایت می‌کند:

.child {
  width: 50px;
  height: 50px;
  background-color: red;
  margin: 0 auto;
}
  • تراز افقی div با flexbox

فلکس‌باکس مدرن‌ترین راه برای وسط‌چین کردن عناصر صفحه است و ضمنا کار طراحی واکنشگرا را خیلی ساده‌تر از قبل کرده (غیر از مرورگر اینترنت اکسپلور که به رحمت ایزدی رفت، مابقی مرورگرها همگی از این قابلیت پشتیبانی می‌کنند).

به طور کلی برای تراز کردن افقی یک المان با فلکس‌باکس، صرفا باید از دستور display:flex و justify-content: center برای المان والد استفاده کرد. یعنی:

.container {
  display: flex;
  justify-content: center;
}

تراز عمودی

وسط‌چین کردن عمودی المان‌های HTML بدون استفاده از روش‌های مدرن مثل Flexbox گاهی می‌تواند خیلی طاقت‌فرسا بشود. پس ابتدا نگاهی داشته باشیم به روش‌های سنتی تا بعد به روش فلکس‌باکس برسیم.

  • تراز عمودی div با استفاده position: absolute و margin منفی

تا قبل از ظهور فلکس‌باکس، تا مدت‌های مدیدی از این روش برای تراز کردن عمودی المان‌ها استفاده می‌شد.

در این حالت باید ارتفاع المانی را که می‌خواهیم وسط قرار دهیم بدانیم. بعد باید position یا جایگاه المان والد را به صورت نسبی تعریف کنیم (position: relative). سپس به سراغ المان فرزند برویم و برخلاف المان والد برایش جایگاه مطلق درنظر بگیریم (position: absolute) و فاصله‌اش را از بالا 50 درصد تعریف کنیم (top: 50%).

اما این هنوز پایان داستان نیست! برای اینکه المان فرزند کاملاً وسط بیفتد، باید ویژگی margin-top هم تعریف و مقدارش را به اندازه منفیِ نصف ارتفاع المان فرزند تعیین کنیم. یعنی مثلا اگر ارتفاع المان فرزند 50 پیکسل باشد، آنگاه margin-top می‌بایست -25px بشود. پس:

.container {
  position: relative;
}

.child {
  width: 50px;
  height: 50px;
  background-color: red;
  position: absolute;
  top: 50%;
  margin-top: -25px;
}
  • تراز عمودی div با استفاده از ویژگی‌های Transform و Translate

اما اگر ارتفاع المانی را که می‌خواهیم به طور عمودی تراز کنیم ندانیم یا نخواهیم وابسته به آن باشیم، می‌توانیم از یک ترفند ماهرانه استفاده کنیم. این روش خیلی شبیه به استفاده از حاشیه منفی در مثال بالاست، یعنی باید همچنان Position المان والد را relative و المان فرزند را absolute تعیین کنیم و فاصله این دومی را از بالا 50 درصد درنظیر بگیریم (top: 50%). منتها به جای استفاده از حاشیه منفی، از transform: translate(0, -50%) استفاده کنیم. یعنی:

.container {
  position: relative;
}

.child {
  position: absolute;
  top: 50%;
  transform: translate(0, -50%);
}

در اینجا translate(0, -50%) شکل خلاصه‌شده‌ی دو عبارت translateX(0) و translateY(-50%) است. پس می‌توان برای تراز کردن عمودی المان فرزند در عوض از transform: translateY(-50%) هم استفاده کرد. در هر حال نتیجه کار یکسان است.

  • تراز عمودی div با استفاده از Flexbox

روش فلکس‌باکس خوشبختانه کار تراز کردن عمودی یک المان را بسیار بسیار ساده کرده و دیگر نیازی به تحمل عذاب الیم روش‌های سنتی نیست.

در این روش کافیست که برای المان والد دستورات display: flex و align-items: center به کار گرفته شود. همین و همین.

.container {
  display: flex;
  align-items: center;
}

حالا حالتی پیش می‌آید که بخواهیم یک المان را در مرکز قرار دهیم. معنی این حالت چیزی نیست جز وسط‌چین کردن یک المان به صورت افقی و عمودی به صورت همزمان. در این حالت چکار باید کرد؟

تراز افقی و عمودی به طور همزمان (قرارگیری المان در مرکز)

روش اولی که در این حالت استفاده می‌شود خیلی شبیه به حالتی است که بخواهیم یک المان را به صورت عمودی تراز کنیم. یعنی:

ابتدا برای المان والد، position: relative در نظر گرفته می‌شود. برای المان فرزند، position: absolute و top: 50%. حالا در مورد المان فرزند اینبار باید یک left: 50% هم اضافه شود. اما هنوز یک قدم دیگر هم باقی می‌ماند تا این المان کاملا در مرکز قرار بگیرد. به این ترتیب که باید فاصله حاشیه بالا را به اندازه منفیِ نصف ارتفاع المان و فاصله حاشیه چپ را به اندازه منفیِ نصف پهنای المان درنظر بگیریم. به عبارتی اگر ارتفاع المان H و پنهای آن W باشد، در آن صورت:

margin: -1/2H px 0 0 -1/2W px;

به عنوان مثال:

.container {
  position: relative;
}

.child {
  width: 50px;
  height: 50px;
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -25px 0 0 -25px; 
}
  • تراز عمودی و افقی div با استفاده از transform و translate

در این روش مشابه مثال قبل همچنان برای المان والد از position: relative و برای المان فرزند از position: absolute به همراه top: 50% و Left: 50% استفاده می‌کنیم، ولی در آخر به جای حاشیه منفی، transform: translate(-50%, -50%) را اضافه می‌کنیم. یعنی:

.container {
  position: relative;
}

.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
  • تراز عمودی و افقی div با flexbox

مجدداً فلکس‌باکس ساده‌ترین روش برای قرار دادن یک المان در مرکز (تراز عمودی و افقی) است و آنچه استفاده می‌شود در واقع ترکیبی از دستورات فلکس‌باکس است که بالاتر گفته شد. برای این کار باید برای المان والد از سه ویژگی زیر استفاده کرد:

display: flex;
justify-content: center;
align-items: center

جمع‌بندی: راهکار بهینه

با این توضیحات می‌شود نتیجه گرفت که استفاده از flexbox، در حال حاضر مدرن‌ترین و ساده‌ترین روش تراز کردن افقی و عمودی المان‌های یک صفحه وب است و روش‌های سنتی قبلی به نوعی منسوخ شده‌اند.