خط دور جداگانه و سایه جعبه: Outline و Box Shadow

در درس‌های قبل با Border و Border Image آشنا شدیم. حالا وقتشه دو ابزار دیگه رو ببینیم که هرکدوم، به روش خودشون، دور یک عنصر یه جلوه بصری اضافه می‌کنن؛ یکی Outline که شبیه بوردره ولی رفتار متفاوتی داره، و دیگری Box Shadow که سایه‌ای دور کل جعبه می‌سازه.

outline چیست؟

.box {
  outline: 3px solid dodgerblue;
}

Property به اسم outline یک خط دور عنصر می‌کشه؛ از نظر Syntax، دقیقاً شبیه border است (ضخامت، سبک، رنگ)، ولی از نظر رفتار در Box Model، کاملاً متفاوت عمل می‌کنه.

تفاوت اصلی outline با border: بدون تأثیر بر اندازه جعبه

مهم‌ترین تفاوت اینه: border بخشی از Box Model محسوبه (همون‌طور که در فصل ۴ دیدیم) و روی اندازه نهایی جعبه اثر می‌ذاره؛ اما outline اصلاً بخشی از Box Model نیست. Outline، بیرون از Border رسم می‌شه، بدون اینکه هیچ فضایی از Layout رو اشغال کنه یا اندازه جعبه رو تغییر بده.

.with-border {
  width: 200px;
  border: 5px solid black;
  /* عرض واقعی جعبه (در content-box) بزرگ‌تر از 200px می‌شود */
}

.with-outline {
  width: 200px;
  outline: 5px solid black;
  /* عرض جعبه دقیقاً همان 200px باقی می‌ماند */
}

در مثال اول، همون‌طور که در فصل ۴ دیدیم، بوردر به عرض تعریف‌شده اضافه می‌شه. در مثال دوم، چون Outline اصلاً بخشی از محاسبات Box Model نیست، عرض جعبه دقیقاً همون 200px باقی می‌مونه؛ Outline فقط روی بیرون از این جعبه، به‌صورت یک لایه اضافه و مستقل، کشیده می‌شه.

outline-offset: فاصله بین Outline و لبه جعبه

.box {
  border: 2px solid navy;
  outline: 2px solid coral;
  outline-offset: 5px;
}

Property به اسم outline-offset یک فاصله بین Outline و لبه بیرونی Border ایجاد می‌کنه؛ یعنی به‌جای چسبیدن مستقیم به لبه جعبه، Outline کمی از اون فاصله می‌گیره. این قابلیت، چیزی‌ست که border اصلاً نداره.

کاربرد اصلی و مهم Outline: نشانگر Focus

button:focus-visible {
  outline: 3px solid royalblue;
  outline-offset: 2px;
}

همون‌طور که در فصل ۳ با :focus و :focus-visible اشاره کردیم، outline نقش حیاتی‌ای در دسترسی‌پذیری داره؛ چون مرورگرها به‌طور پیش‌فرض، وقتی کاربر با کلید Tab بین عناصر قابل‌فوکوس (مثل دکمه‌ها و لینک‌ها) حرکت می‌کنه، از همین outline برای نشون دادن عنصر فعلی استفاده می‌کنن.

چرا نباید outline: none بدون جایگزین استفاده شود؟

/* اشتباه رایج و مضر برای دسترسی‌پذیری */
button:focus {
  outline: none;
}

خیلی از توسعه‌دهنده‌ها، چون Outline پیش‌فرض مرورگر رو زیبا نمی‌دونن، اون رو کاملاً حذف می‌کنن؛ بدون جایگزین کردن هیچ نشانه بصری دیگه‌ای. این کار، برای کاربرانی که با صفحه‌کلید ناوبری می‌کنن، به‌شدت مضره؛ چون دیگه هیچ راهی برای فهمیدن اینکه الان کدوم عنصر فعاله وجود نداره. روش درست، جایگزین کردن Outline پیش‌فرض با یک استایل سفارشی‌تر (مثل مثال قبلی)، نه حذف کامل اون.

box-shadow: سایه دور کل جعبه

.card {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

Property به اسم box-shadow، دقیقاً مشابه text-shadow که در فصل ۸ دیدیم، یک سایه اضافه می‌کنه؛ ولی به‌جای دور شکل حروف، دور کل جعبه مستطیلی (یا گرد‌شده، در صورت داشتن border-radius) یک عنصر.

Syntax پایه box-shadow

box-shadow: افست‌افقی افست‌عمودی شعاع‌محو شعاع‌گسترش رنگ;

این Syntax، پنج مقدار می‌پذیره که دو مقدار آخرش نسبت به text-shadow جدیدن:

مقدار نقش
افست افقی و عمودی جابه‌جایی سایه (دقیقاً مثل text-shadow)
شعاع محو (Blur Radius) میزان نرمی و پخش‌شدگی لبه‌های سایه
شعاع گسترش (Spread Radius) بزرگ یا کوچک کردن کل سایه نسبت به اندازه جعبه اصلی (اختیاری)
رنگ رنگ خود سایه

تفاوت Blur Radius و Spread Radius

.blur-only {
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.with-spread {
  box-shadow: 0 4px 20px 10px rgba(0, 0, 0, 0.3);
}

Blur Radius فقط لبه‌های سایه رو محو و نرم می‌کنه؛ Spread Radius (که مقدار چهارم و اختیاریه)، کل سایه رو، مثل بزرگ یا کوچک کردن خود جعبه سایه، در همه جهات گسترش یا جمع می‌کنه. مقدار مثبت Spread، سایه رو بزرگ‌تر از جعبه اصلی می‌کنه؛ مقدار منفی، اون رو کوچک‌تر می‌کنه.

inset: سایه داخل جعبه

.inner-shadow {
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3);
}

به‌طور پیش‌فرض، box-shadow بیرون از جعبه رسم می‌شه (دقیقاً مثل یه سایه واقعی که پشت یک جسم روی زمین می‌افته). با اضافه کردن کلیدواژه inset در ابتدای مقدار، سایه به‌جای بیرون، داخل جعبه رسم می‌شه؛ که جلوه‌ای شبیه یک گودی یا فرورفتگی ایجاد می‌کنه.

چند سایه هم‌زمان

.layered-shadow {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.1),
    0 4px 8px rgba(0, 0, 0, 0.1),
    0 12px 24px rgba(0, 0, 0, 0.1);
}

دقیقاً مثل text-shadow، می‌شه چند سایه رو با کاما از هم جدا کرد و هم‌زمان اعمال کرد. این تکنیک، برای ساخت سایه‌های چندلایه و طبیعی‌تر (که در طراحی مدرن به سایه‌های «نرم و عمیق» معروفن) بسیار رایجه؛ چون یک سایه واحد و ساده، معمولاً به‌اندازه چند سایه ظریف روی هم، طبیعی به‌نظر نمی‌رسه.

کاربرد رایج: Hover Effect با تغییر سایه

.card {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.2s;
}

.card:hover {
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}

یکی از الگوهای بسیار رایج در طراحی مدرن، بزرگ‌تر و پررنگ‌تر شدن سایه یک کارت هنگام Hover؛ که با کمک transition (که در فصل مربوط به Transitions به‌طور کامل بررسیش می‌کنیم)، این تغییر به‌آرومی و نرم اتفاق می‌افته، و حس بلند شدن جزئی کارت از سطح صفحه رو القا می‌کنه.

مقایسه Outline، Border و Box Shadow

ویژگی border outline box-shadow
بخشی از Box Model بله خیر خیر
اثر روی اندازه جعبه بله (در content-box) خیر خیر
پیروی از border-radius - در برخی مرورگرها متفاوت است بله
کاربرد رایج خط دور جعبه نشانگر Focus سایه و عمق بصری

نکات مهم

  • outline بخشی از Box Model نیست و هیچ تأثیری روی اندازه یا Layout جعبه ندارد.
  • outline: none نباید بدون یک جایگزین بصری مناسب استفاده شود، چون به دسترسی‌پذیری صفحه آسیب می‌زند.
  • box-shadow با کلیدواژه inset، به‌جای بیرون، داخل جعبه رسم می‌شود.

اشتباهات رایج

  • حذف کامل outline در حالت focus بدون تعریف یک استایل جایگزین، که کاربران صفحه‌کلید را از بازخورد بصری محروم می‌کند.
  • قاطی کردن Blur Radius و Spread Radius در box-shadow؛ اولی لبه‌ها را نرم می‌کند، دومی کل سایه را بزرگ یا کوچک می‌کند.
  • استفاده از یک سایه واحد و پررنگ به‌جای چند سایه ظریف، که نتیجه‌ای کمتر طبیعی و حرفه‌ای ایجاد می‌کند.

جمع‌بندی

outline شبیه border رسم می‌شود، ولی بخشی از Box Model نیست و روی اندازه جعبه اثر نمی‌گذارد؛ کاربرد اصلی‌اش نشان دادن وضعیت Focus برای دسترسی‌پذیری است. box-shadow امکان افزودن سایه (بیرون یا با inset، داخل جعبه) را، با کنترل دقیق روی افست، محو شدگی، گسترش و رنگ، فراهم می‌کند و برای ساخت جلوه‌های عمق بصری، مثل کارت‌ها و دکمه‌های مدرن، بسیار پرکاربرد است.