مقدمه

در درس قبلی با مفهوم Cascade آشنا شدیم و دیدیم که این الگوریتم چطور مسئله‌ی تعارض بین قاعده‌ها را حل کرده و برنده‌ی هر تعارض را مشخص می‌کند. یکی دیگر از مفاهیم کلیدی در CSS که توسعه‌دهندگان باید با آن آشنا بوده و درک خوبی از آن داشته باشند، مفهوم وراثت (inheritance) است. وراثت نیز مانند Cascade مفهومی است که به چگونگی اعمال استایل‌ها روی عناصر مربوط می‌شود.

جریان وراثت در اسناد وب

داستان وراثت در CSS به زبان ساده از این قرار است که: برخی پراپرتی‌ها مقداری را که دریافت می‌کنند، به عناصر فرزند خود نیز به ارث می‌رسانند و برخی دیگر خیر. آنچه که رابطه‌ی توارث یا پدر و فرزندی را بین عناصر مشخص می‌کند، ساختار درختی DOM است. این ساختار درختی، سلسله‌مراتب وراثت را برای سند مفروض نشان می‌دهد و هر عنصری در جایی از این سلسله‌مراتب قرار دارد. طبیعتاً جریان وراثت یک جریان رو به پایین (downward) است؛ چون ارث از والد به فرزند می‌‌رسد نه برعکس.

مقداری که قاعده‌ی برنده‌ی یک تعارض بر اساس الگوریتم Cascade دریافت می‌کند، اصطلاحاً یک مقدار cascaded نامیده می‌شود. اگر برای یک پراپرتیِ یک عنصر مفروض، هیچ مقدار cascaded وجود نداشته باشد، این پراپرتی می‌تواند مقدار خود را از یک عنصر والدش دریافت کند؛ در این صورت، گفته می‌شود که مقدار مورد نظر به آن پراپرتی به ارث رسیده است. پس، مقداری که یک پراپرتی دریافت می‌کند یا یک مقدار cascaded است و یا یک مقدار inherited. به بیان دقیق‌تر: وراثت از بالا به پایین در جریان است و هر پراپرتی پشتیبانی‌کننده از وراثت، مقدار خود را به فرزندان خود در سلسله‌مراتب وراثت به ارث می‌رساند تا جایی که یک مقدار cascaded آن را لغو کند.

اجازه دهید مثالی در این رابطه ارائه دهیم. یکی از پراپرتی‌هایی که از وراثت پشتیبانی می‌کند و مقدار خود را به فرزندان به ارث می‌رساند، پراپرتی font-family است که برای تعیین فونت عناصر کاربرد دارد. وقتی بخواهیم فونت مشخصی را برای همه‌ی ‌عناصر یک صفحه تعیین کنیم، نیازی نیست که این کار را برای تک‌تک عناصر سند انجام دهیم؛ بلکه کافیست این پراپرتی را برای عنصر body تنظیم کنیم و مقدار تعیین‌شده برای این پراپرتی از عنصر body به سایر عناصر فرزند این عنصر به ارث می‌رسد. حالا اگر برای عنصری در صفحه، پراپرتی font-family را با مقدار دیگری به کار بگیریم، این مقدار cascaded برای آن عنصر در نظر گرفته می‌شود و مقدار inherited لغو می‌شود.

 Copy Icon CSS
body{
  font-family: monospace;
}

address{
  font-family: serif;
}

در این کد، مقدار monospace برای پراپرتی font-family عنصر body در نظر گرفته شده و چون این پراپرتی ماهیتاً یک پراپرتی پشتیبانی‌‌کنننده از وراثت است، مقدار خود را به عناصر فرزند body به ارث می‌رساند و بنابراین، مقدار monospace به عنوان یک مقدار inherited برای پراپرتی font-family همه‌ی عناصر در نظر گرفته می‌شود. اما در مورد عنصر address مقدار دیگری (serif) مستقیماً به این پراپرتی تخصیص داده شده و لذا مقدار serif برای پراپرتی font-family مربوط به عنصر address یک مقدار cascaded محسوب می‌شود که مقدار inherited را لغو می‌کند.

پراپرتی‌های پشتیبانی‌کننده از وراثت

همانطور که گفتیم، به ارث رساندن مقدار به فرزندان، اتفاقی نیست که برای همه‌ی پراپرتی‌ها رخ دهد و تنها برخی از پراپرتی‌های CSS این قابلیت را دارند. اینکه مقدار یک پراپرتی مانند font-family به فرزندان عنصر مورد نظر به ارث برسد، کاملاً طبیعی و مورد انتظار است اما طبیعتاً منطقی نیست که پراپرتی‌هایی مانند width و height و یا padding و margin مقدار خود را به فرزندانشان به ارث برسانند. پس، این سؤال مطرح می شود که دقیقاً چه پراپرتی‌هایی از وراثت پشتیبانی می‌کنند؟

یک پاسخ کوتاه به این سؤال این است: پراپرتی‌های مربوط به متون، لیست‌ها و برخی پراپرتی‌های مربوط به جداول.

کنترل وراثت

آنچه که تا اینجا دیدیم، جریان و روند طبیعی وراثت در CSS بود. اما در ادامه، قصد داریم در مورد امکان دستکاری این روند طبیعی و کنترل آن صحبت کنیم. برای نمونه، می‌توانیم ترتیبی بدهیم که پراپرتی‌هایی که در حالت پیش‌فرض از وراثت پشتیبانی نمی‌کنند، مانند یک عنصر پشتیبانی‌کننده از وراثت رفتار کنند و مقدار خود را به ارث برسانند. بازیگران اصلی داستان کنترل وراثت، چهار مقدار inherit، initial، unset و revert هستند که می‌توانیم آنها را مقادیر خاص (special values) نیز بنامیم.

مقدار خاص inherit

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

فرض کنید بخواهیم یک بخش footer با رنگ پس‌زمینه‌ی خاکستری روشن به صفحه‌ی خود اضافه کنیم. از طرفی، می‌خواهیم درون footer یک یا چند لینک قرار گیرد که نباید خیلی برجسته به نظر برسند و بنابراین، باید از یک رنگ خاکستری تیره برای نمایش آنها استفاده شود. این کارها را به روش زیر اتجام می‌دهیم.

 Copy Icon CSS
a:link{
  color: blue;
}

footer{
  colro: #666;
  background-color: #ccc;
  padding: 15px 0;
  text-align: center;
  font-size: 14px;
}

اگر استایل color:inherit; را حذف کنیم، مطابق روال طبیعی، رنگ آبی که صراحتاً برای پراپرتی color مربوط به لینک‌های صفحه تعریف کرده‌ایم (و یا در غیاب چنین استایلی، از روی استایل‌شیت پیش‌فرض مرورگر تعیین می‌شود) برای لینک‌های درون footer در نظر گرفته می‌شود و این یک مقدار cascaded محسوب می‌شود. اما وقتی مانند بالا، پراپرتی color را برای لینک‌های درون footer با مقدار inherit تنظیم می‌کنیم، این پراپرتی مقدار خود را از عنصر والدش یعنی footer دریافت می‌کند و بنابراین، لینک درون footer با رنگ خاکستری تیره (#666) نمایش داده می‌شود. دقت داشته باشید که مزیت این روش آن است که اگر مقدار پراپرتی color برای عنصر footer تغییر داده شود، این تغییر روی لینک‌های درون footer نیز منعکس می‌شود.

علاوه بر این، از کلمه کلیدی inherit می‌توان برای فعال کردن وراثت برای پراپرتی‌هایی که در حالت عادی از وراثت پشتیبانی نمی‌کنند، استفاده کرد. مثلاً می‌توانیم مقدار inherit را به یک پراپرتی مانند padding اختصاص دهیم تا عنصر مورد نظر مقدار پراپرتی padding را از والدش دریافت کند. البته موارد انگشت‌شماری وجود دارد که چنین کاری مفید باشد.

مقدار خاص initial

برخی اوقات شرایطی پیش می‌آید که استایل‌هایی روی یک عنصر اعمال شده که می‌خواهیم آنها را undo کنیم؛ این کار را می‌توانیم با استفاده از مقدار initial انجام دهیم. هر پراپرتی CSS دارای یک مقدار اولیه (initial) یا پیش‌فرض است. تخصیص مقدار initial به یک پراپرتی، به معنای بازنشانی (reset) آن به آن مقدار پیش‌فرض است.

مثال قبل را طوری تغییر می‌دهیم که به جای مقدار inherit از مقدار initial برای پراپرتی color مربوط به لینک‌های درون footer استفاده کند:

 Copy Icon CSS
a:link{
  color: blue;
}

footer{
  color: #666;
  background-color: #ccc;
  padding: 15px 0;
  text-align: center;
  font-size: 14px;
}

footer a{
  color: initial;
  text-decoration: underline;
}

از آنجایی که مقدار پیش‌فرض یا اولیه‌ی پراپرتی color در اغلب مرورگرها مقدار black است، با اجرای کد بالا، لینک‌های درون footer با رنگ سیاه نمایش داده می‌شوند.

مزیت استفاده از مقدار initial این است که مجبور نیستیم بیش از اندازه‌‌ای که واقعاً لازم است، فکر کنیم! اگر بخواهیم border را برای یک عنصر حذف کنیم، کافیست از border:initial; استفاده کنیم و یا اگر بخواهیم یک عنصر را به عرض ابتدایی‌اش برگردانیم، کافیست از width:initial; استفاده کنیم.

در اینجا ذکر دو نکته لازم به نظر می‌رسد:

  • نکته‌ی اول اینکه مقدار پیش‌فرض پراپرتی width در همه‌ی مرورگرها برابر با auto است و از این‌روست که با تخصیص مقدار auto به این پراپرتی نتیجه‌ی مشابهی با مقدار initial بدست می‌آید و نباید فکر کنیم که در مورد سایر پراپرتی‌ها نیز می‌توان از auto به جای initial استفاده کرد.
  • نکته‌ی دوم به پراپرتی display مربوط است. مقدار initial برای این پراپرتی، فارغ از نوع عنصر (block یا inline) همواره مقدار inline است. پس، تصور نکنید که اگر مقدار initial را به پراپرتی display یک عنصر از نوع block اختصاص دهیم، مقدار block را برای آن در نظر می‌گیرد؛ خیر، این مقدار در هر صورت معادل inline خواهد بود.

مقدار خاص inset

استفاده از مقدار unset برای یک پراپرتی باعث می‌شود که آن پراپرتی به مقدار طبیعی خود برگردد. مقدار طبیعی یک پراپرتی به ماهیت آن پراپرتی بستگی دارد؛ یعنی مقدار unset برای پراپرتی‌های inherited مانند مقدار inherit عمل می‌کند و برای سایر پراپرتی‌ها مانند مقدار initial. در مثال زیر، تأثیر هر یک از مقادیر خاص inherit، initial و unset را می‌بینید:

 Copy Icon CSS
body{
  color: green;
}

.my-class-1 a{
  color: inherit;
}

.my-class-2 a{
  color: initial;
}

.my-class-3 a{
  color: unset;
}

یک مقدار خاص دیگر با نام revert نیز وجود دارد که اخیراً معرفی شده و فعلاً از پشتیبانی خوبی در مرورگرها برخوردار نیست. بنابراین، بهتر است از آن استفاده نکنیم.

بازنشانی همه‌ی پراپرتی‌های یک عنصر

با استفاده از پراپرتی all می‌توانیم ترتیبی دهیم تا یکی از مقادیر خاص معرفی شده در بالا روی (تقریباً) همه‌ی پراپرتی‌ها اعمال شود. این یک روش مناسب برای برگرداندن تغییرات و برگشتن به یک استایل مشخص است. مثال زیر را ببینید:

 Copy Icon CSS
blockquote{
  background-color: red;
  border: 2px solid green;
}

.fix-this{
  all: unset;
}

پراپرتی all یک نمونه از پراپرتی‌هایی است که در CSS با نام shorthand شناخته می‌شوند. یک پراپرتی shorthand همانطور که در مورد پراپرتی all هم دیدیم، نوعی مختصرنویسی است که چند پراپرتی دیگر را در قالب تنها یک استایل، مقداردهی می‌کند. در درس بعدی، چند نکته‌ی مهم در مورد پراپرتی‌های اختصاری بیان خواهد شد.