سلسه یادداشت‌هایی از جنس یکبار برای همیشه(‌شماره ۱)

ریز مقدمه:توی شماره قبلی یه توضیح دادم،‌الانم یه کوچولو دوباره بهش اشاره میکنم که من میخوام بخاطر خسته شدنم از سرگردونی بین بوک‌مارک‌ها و یادداشت‌های غیرمنسجم،‌مطالب جدید و قدیمی‌ای رو که بهشون بر میخورم توی این مجموعه بنویسم‌؛‌این مطلب میتونه از مسخره ترین چیزا مثل یه کانفیگ ساده/تعریف alias توی گیت یا گاهی یه‌ راه حل خفن (‌حداقل برای من) توی برنامه نویسی و بحث جدی و بلا بلا باشه . D:این داستان: «چرا استایل هایی که من نوشتم،‌تغییراتشون اعمال نمیشن؟»تذکر: مخاطب این داستان افراد تازه‌کار و یا کسانی هستند که دنبال چرایی هستند.:))حتما این حس گند رو تجربه کردید که یه پروژه با ابعاد بزرگ دارید که یا بهتون ارث رسیده یا خودتون در جریان گُنده کردنش و هنرنمایی‌هاتون(‌بالاخص در قسمت styling) بودید و می‌خواید یه استایل خاص رو روی یه المان اعمال کنید ولی جلل الخالق وقتی توی مرورگر تست می‌کنید،‌می‌بینید کار نمی‌کنه و از قسمت style از dev tools مرورگر‌ می‌بینید که استایلتون خط خورده و بعله تداخل استایل دارید(‌با استایل یاروی قبلی شاید، شاید بخاطر bootstrap یا اون استایلاییه که کِش رفتی) و حالا شما هی بگرد ببین این از کجا داره خط می‌گیره که استایلت اعمال نمیشه!یک رویکرد راحت،‌سریع در مواجه با همچین شلخته بازار CSS‌ای استفاده از دوست خوب ما «important!» هستنش.‌گاهی مجبوری، کسی قضاوتی نکرده یه‌چیزی مثل BootStrap مجبورت کرده که این حد از قلدری رو توی استایلت اعمال کنی! استفاده از important!‌روش غیر معمولی نیستش،‌شما با اضافه کردنش جلوی استایلت داری به مرورگر میگی که:‌«ببین بقیه استایل ها رو فراموش کن کلا،‌من فقط می‌خوام اینی که من می‌گم رو اعمال کنی»‌ و کارت راه میافته اما از اون طرف style‌کدهات کثیف و زیاد می‌شن(یکی اون استایل قبلی که پیداش نکردی و روی المان اعمال میشد و یکی اون important!‌ ای که نوشتی تا استایل قبلی رو override‌کنی) و بعدا که نیاز به اعمال کردن تغییرات درشون داشته باشی کلا گیج میشی که از کجا شروع کنی و جدا از اون مشکل هم به طور ریشه‌ای حل نشده(‌آخرش وقت نذاشتی که بفهمی کدوم استایل با مال تو تداخل داشت و مشکل رو از ریشه حل نکردی)برای اینکه بهتر بفهمیم چی میشه که اینجوری استایل ما نادیده گرفته میشه باید بفهمیم مرورگر وب چجوری با استفاده از روش آبشاری(‌cascade)می‌فهمه که کدوم استایل رو به کدوم المان از DOM اعمال کنه،‌پس:روش آبشاری(Cascade)‌چیست؟روش آبشاری(Cascade)‌چیست؟همونطور که مثال زدیم،‌از اونجایی که چندین استایل می‌تونن روی یک المان از DOM اعمال بشن،‌فهمیدن اینکه مرورگر وب چجوری با استفاده از روش cascade‌ میفهمه چطوری استایل‌ها باید روی یک المان از DOM‌اعمال بشن مهمه:توی روش cascade استایل‌ها خیلی ساده براساس دو معیار اعمال میشن:میزان مشخص بودن انتخابگر (Selector Specificity) - بابا ترجمه!!!!- و در مرحله بعدی هم:ترتیب قرار گرفتن استایل‌ها(Ruleset Order)اما از بین این ۲ تا معیار،‌منظور از میزان مشخص بودن انتخابگر یا همون Selector Specificity چیه و چجوری اندازه گرفته میشه؟میزان مشخص بودن انتخابگر (Selector Specificity) چیست؟منظور از مشخص بودن یا specificity‌ برای یک انتخابگر (selector) اینه که چقدر دقیق المان‌های DOM توسط اون selector‌ مشخص و متمایز شدن.خب این مقدار specificity برای یک selector چجوری اندازه گیری می‌شه؟برای اندازه‌گیری specificity یک selector‌ از یه ۴تایی مرتب مثل (a,b,c,d‌) استفاده میشه که توی اون هرکدوم از جایگاه حروف a,b,c‌وd‌به دسته خاصی از selector‌ها تعلق داره و در مجموع بعد از بررسی ها،‌هرمقداری که این ۴تایی مرتب تشکیل بده (مثل (1,0,0,1)) مقدار نهایی specificity‌میشه و اون selector‌ای که مقدار specificity‌اش بیشتر باشه برنده‌است و اعمال میشه :)))برای اینکه جغورپغور بالا رو کاملا واضح متوجه بشید،‌شکل زیر رو ببینید:شکل بالا نحوه محاسبه specificity‌ و اینکه هرجایگاه از حروف a,b,c,d‌به کدوم دسته از selector‌ها تعلق داره رو نشون میده جایگاه اول مربوط به ویژگی style‌هستش، یعنی اگه یه element با استفاده از style attribute‌استایل گرفته باشه توی محاسبه specificity‌مقدار a=1 می‌شه و اگه اینجوری استایل نگرفته باشه a=0‌میشه. مثال زیر واضح میکنه قضیه رو:توی مثال بالا مقدار specificity‌برابره (1,0,0,0)هستش چون style attribute‌داریم پس مقدار a=1‌ شده.جایگاه دوم مربوط به id هستش یعنی اگر یک element‌با id‌مشخص شده باشه مقدار b‌اش برابر با تعداد id selector‌هایی هستش که مشخص‌‌اش می‌کنه:توی مثال بالا مقدار specificity‌برابره (0,1,0,0)هستش چون یک id داریم پس مقدار b=1‌ شده. جایگاه سوم برابر با تعداد class selector‌ها، attribute selector‌ها و pseudoclass‌های موجود هستش، مثال زیر رو در نظر بگیرید:توی مثال بالا مقدار specificity‌برابره (0,0,1,0)هستش چون یک class داریم پس مقدار c=1‌ شده.جایگاه چهارم هم برابر تعداد type selector‌ها و pseudoelement‌های موجود هستش :توی مثال بالا مقدار specificity‌برابره (0,0,0,1)هستش چون یک type selector داریم پس مقدار d=1‌ شده.حالا اگه درست همه‌چیز توضیح داده شده باشه باید بتونید مقدار specificity‌ رو در مثال زیر خودتون حساب کنید:مثالیجات:مثال ۱-۱جواب:با استفاده از الگویی که اون بالا گفتیم مقدار specificity‌ این selector برابر هستش با (0,1,1,3) و اگه این مقدار رو بدست آوردید،‌درست هستش اما چرا:باتوجه به چیزی که نوشته شده میفهمیم که این استایل از طریق style attribute اعمال نشده پس a=0 هستش.یدونه ID selector به نام (nav-global#) وجود داره پس مقدار b=1‌ هستش.یدونه class selector‌به اسم (nav-link.) وجود داره پس مقدار c=1‌ هستش.۳تا type selector‌وجود دارند(ul,li,a) پس مقدار d=3‌ هستش.مثال ۲-۱ به همراه جوابمثال ۳-۱ به همراه جوابسوال: خب حالا اگه دوتا specificity‌داشته باشیم چجوری مقدارشون مقایسه میشه و کدوم برنده است و استایل‌اش اعمال می‌شه؟جواب: برای مقایسه کردن از سمت چپ مقدار specificity‌ها (همون ۴ تایی مرتبی که گفتیم میسازیمش) شروع می‌کنیم. selector‌ای که رقم سمت چپش بزرگتر هستش، بیشترین مقدار specificity‌رو داره. حالا اگه دوتا مقدار چپ برابر باشند برای دوتا selector‌،‌رقم بعدی کنار سمت چپ‌ترین‌هاشون باهم مقایسه می‌شه و به همین منوال. مثلا:(1,0,0,0)مقدارش از (0,1,1,3)بیشتر هستش و (0,1,1,3) مقدارش از (0,1,2,0) کمتر هستش.گفتیم عامل دومی که توی روش cascade‌مرورگر بهش توجه داره Ruleset order یا ترتیب حضور reulset‌استایل هستش پس:منظور از Ruleset order چیست:توی کد css‌ وقتی دوتا بلوک کد مقدار selector specificity‌اشون باهم برابر شده و هر دو می‌خوان به یک المان استایل اعمال کنند الویت با اونی هستش که بعدا نوشته شده(duh!) یعنی اگه کدها دارند از بالا به پایین خونده میشن اون دومی که پایین‌تره، استایل های اون اعمال میشه و قبلیه نادیده گرفته میشه.مثال زیر رو در نظر بگیرید:مثال ۴-۱ : rulset orderتوی این مثال از بین دو مقدار رنگ 000000#‌ و FFFFFF#‌ رنگ 000000#‌ اعمال میشه چراکه دوتا selector‌با مقدار specificity ‌برابر داریم و دومی بخاطر دومی بودنش اولویتش بیشتره.(متوجهم هستیم که در دنیای واقعی دقیقا پشت سر هم نمیان )چند عدد نکته:درسته که گفته شد دو عاملِ selector specificity‌ و ruleset order‌ برتری دارند برای اعمال استایل‌ها اما:استایل‌هایی که به صورت inline ‌(یعنی مسقیما از طریق ویژگی style جلوی html element‌نوشته میشن) همیشه به سایر استایل‌های که به صورت external ‌اضافه شدند اولویت دارند؛ دلیلش رو هم الان میدونیم دیگه مقدار specificity‌رو زیاد میکنه توی اون ۴تایی مرتب در نظر بگیرید داره چپ ترین جایگاه رو ۱ میکنه. این نکته رو هم در نظر میگیریم که نوشتن استایل‌ها به صورت inline علیرغم اینکه مقدار specificity‌ رو زیاد میکنه یه bad practice هستش،‌چراکه مسائلی در زمینه maintenance و reuseability‌ رو پیش میاره، css ها همه باید یکجا نگه داشته بشن.ابتدا به ساکن هم اشاره کردیم که important!‌ اگه جلوی css rule‌ای گذاشته بشه به چه معنی هستش و به جز مواقع ضروری مثل وقتی که گرفتار bootstrap‌ امثالهم شدید توصیه به استفاده نمیشه چون دیباگ کردن css ‌رو سخت میکنه و ...،‌حالا اگه دوتا بلاک کد css‌ باهم تداخل داشتند و هر دو از important!‌ استفاده میکردند، حکم چیست؟ خب اونی که specificity‌اش بیشتره برنده است و استایلش اعمال میشه(‌پس خوبه این رو هم در نظر داشته باشیم)انتخابگر های همگانی! (universal selector‌s)‌مثل *‌ و combinator‌ها مثل (.etc , > , +) و شبه کلاس های منفی (negation pseudo-classes )‌مثل ()not: هیچ تاثیر روی محاسبه میزان specificity ندارند برای همین موقع ساختن اون ۴ تایی مرتب بهشون اشاره نشد.منابع:کتاب CSS Refactoring: Architect Your Stylesheets for Success نوشته Steve Lindstromمقاله CSS Specificity از Emma Bostian