پیش پردازنده‌های CSS

مدتی هست که می‌خوام مقاله‌ای رو انتشار بدم که در مورد چند مورد جدید در JavaScript هست، ولی بر اثر چند مورد پیش اومده احساس کردم شاید اونطور که باید حق مطلب، در مورد CSS و مسائل، چالش‌ها و ابزارهای مربوط به اون بیان نشده. توی این مقاله قصد دارم در مورد پیش پردازنده‌های CSS یا همون CSS Preprocessors و فواید استفاده از اون‌ها صحبت کنم. امیدوارم که شما دوستان علاقمند به برنامه نویسی UI و کلا دولوپ سمت front-end از این مطلب خوشتون بیاد.

CSS
CSS

کلا CSS چیه؟

درواقع Cascading Style Sheets یا همون CSS مفسر این هستند که چطور المان‌های HTML روی صفحه نشون داده بشن و به چند شکل به پروژه افزوده میشن و مرورگر با لود کردن و اعمال اون‌ها به صورت آبشاری UI رو می‌سازه. هر مرورگری بسته به دانش خودش از CSS ظاهری رو نشون میده که فکر کنم توی این جمع همه با Internet Explorer آشنا هستیم. بعله. مخصوصا نسخه‌های قدیمیش که واقعا برای front-end کارها دردسرهای زیادی رو فراهم کرده.

خوشبختانه در سالهای اخیر شاهد مرگ نسخه ۶، ۷ و ۸ این مرورگر هستیم و ان‌شاءالله تا یه چند وقت دیگه الباقیشم به خاطره‌ها می‌پیوندن و راحت می‌شیم از دستشون. گرچه مایکروسافت دست بردار نیست و همچنان داره مرورگر میسازه. الحمدالله این نسخه‌های جدید که با نام edge معرف حضور هستند دارند کمی بهتر عمل می‌کنن


پردازش روی CSS

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

درواقع، منظور از پردازش در زمان ساخت یا همون develop هست. یعنی شما کد‌ها رو می‌نویسید و از شیوه‌ها و از syntax های خاصی استفاده می‌کنید و کتاب خونه‌ای این وسط میاد اون شیوه‌ها و syntax ها رو ترجمه می‌کنه به یک یا چند فایل CSS و ضمن این کار، شما خیلی از کارهایی که قبلا دستی انجام می‌دادید رو به ماشین می‌سپارید.

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


پیش پردازشگر SCSS

توی این زمینه پیش پردازشگرهای زیادی وجود دارند که معروف ترین‌های اونها Less هست. Less توی نسخه‌های قدیمیش کمبود‌هایی داشت و توی حجم بالای پروژه پردازش دولوپش فوق العاده کـُند میشد برای همین برنامه نویس‌ها به سمت Sass رفتن. نسخه‌های اولیه اون با ruby نوشته شد که هنوز هم پایدار هستند ولی بعد node-sass هم ساخته شد که توی پروژه‌های بزرگ جاوااسکرپتی مثل React App ها ازش استفاده میشه. کلمه Sass مخفف مجموعه کلمات Syntactically awesome style sheets هست. ولی این نسخه خیلی syntax جالبی نداشت و به جای curly brace از indent استفاده می‌کرد. چیزی شبیه python

کمی بعد نسخه‌ای از Sass منتشر شد که از آکولاد استفاده کرد و چهره‌اش خیلی خیلی شبیه CSS شد. این نسخه رو Sassy CSS یا همون SCSS نامگذاری کردند. سینتکس بسیار جالب و شبیه به CSS که قابلیت‌های nesting, function, loop, placeholder, extend, include, mixins و خیلی چیزهای دیگه رو داشت.

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


فواید استفاده از پیش پردازش‌گرها

دوست ندارم خیلی ریز و دقیق بشم و متن حوصله سر بر بشه. فرض کنید طراح از یه سری رنگ استفاده کرده. مثلا پالت پروژه رو با ۷ رنگ ساخته و با این ۷ رنگ طرح‌ها رو پیاده کرده و جاهایی که خواسته تیره و روشن کنه روی Photoshop یا Sketch ش از همین رنگ‌ها استفاده کرده و شما هم با دست خالی و بدون هیچ ابزاری کد زدید. یا مثلا فاصله‌ها و padding, margin ها رو یه عدد خواص مثل ۱۲ گذاشته.

بعد یهو به دلایل UXی یا دستورات مدیریتی یا هرچیز دیگه میان اون ۷ رنگ اصلی رو عوض می‌کنن یا مثلا اون ۱۲ رو می‌کنن ۱۶.

فاجعه شروع شد! شما باید کل CSS ‌ها رو از زیر ذره بین رد کنی و همه این مقادیر رو تغییر بدی. خیلی خیلی بده. در صورتی که توی پروژه‌ای که با یک پیش پردازشگر استارت خورده ما همچین چیزی داریم:

$primary: #f00;
$secondary: #0a0;
...
$gutter: 12px;

و در کد اصلی استفاده می‌کنیم:

.wrapper {
    padding: $gutter;
    
    &__header {
        background-color: $primary;
    }
}

خروجی هم اینه:

.wrapper {
    padding: 12px;
}
.wrapper__header {
    background-color: #f00;
}

یعنی اینجا شما نیاز نداری بری کل پروژه رو چرخ بزنی مقادیر رو عوض کنی. فقط اونجایی که variables رو تعریف کردی تغییرات جدید رو می‌ذاری و CSS فایل جدید با مقادیر جدید برات ساخته میشه.

پیش پردازنده‌ها فواید زیاد دارن. مثلا Cross-Browser بودن کدهای خروجی. شما می‌تونید از mixins ها یا از placeholder ها استفاده کنید و کدهایی رو بنویسید که نسخه‌های مختلفش نوشته شده و دیگه نیاز نیست دستی همه نسخه‌ها رو با هم بزنید. مثلا:

%displayFlexPlaceholder { 
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-box;
    display: -ms-flexbox;
    display: flex;
}
...
.container {
    @export %displayFlexPlaceholder;
}
.box {
    @export %displayFlexPlaceholder;
}
#rootWrapper {
    @export %displayFlexPlaceholder;
}

و خروجی:

.container, .box, #rootWrapper {
    display: -webkit-box;
    display: -webkit-flex;
    display: -moz-box;
    display: -ms-flexbox;
    display: flex;
}

روش بالا اسمش placeholder هست. mixin ها یکم متفاوت هستند ولی تقریبا کار مشابهی می‌کنن. حتی شما می‌تونید کد‌هاتون رو تیکه تیکه کنید. یعنی فولدر بندی کنید و همه رو یک جا import کنید. مثلا فایل variables رو جدا کنید. فایل تعریف fonts رو جدا کنید. اسم صفحات رو از هم جدا کنید. قسمت‌های مختلف هر صفحه رو جدا کنید و توی یک زیر فولدر قرار بدید. قسمت‌های public رو که همه استفاده می‌کنن رو توی یه public.scss بگذارید. به این کار partialise کردن میگن.

این partialise کردن فوق العاده مهمه، چون وقتی پروژه بزرگ میشه دیباگ رو خیلی خیلی راحت می‌کنه. من خودم همیشه یه پوشه می‌سازم به اسم helpers و ۴ تا فایل توش تعریف می‌کنم به نام‌های reset, variables, requirement, extensions. توی extensions میام تمام placeholder ها رو قرار میدم. همونی که توی مثال بالا نوشتم و اولش % داشت. اینا به هیچی تبدیل نمی‌شن، وقتی فایل آخر ساخته شد اون‌هایی که ازش extend گرفتن مقادیر اون placeholder رو بر میدارن و توی requirement هم تعریف فونت‌ها، انیمیشن‌ها،‌ اشکال فونتی و غیره رو انجام می‌دم. نمی‌گم این استاندارده و همه اینطوری می‌نویسن ولی طبق تجربه‌ام به این تقسیم بندی خوب رسیدم.

کنار پوشه helpers یه پوشه می‌سازم به اسم public که توش menu, header, footer و کلا چیزهایی که توی کل پروژه استفاده می‌شه رو قرار می‌دم. الباقی پوشه بندی هم طبق ساختار جلو می‌رم مثلا pages یا routes و توی pages باز پوشه می‌سازم و دونه دونه صفحات رو می‌نویسم. و اگر نیاز شد که صفحات رو به قسمت‌های ریزی تبدیل کنم توی پوشه صفحات یه فولدر می‌سازم به نام partials که اونجا قطعات ریز‌تر رو میذارم. این آخرین مرحله از تقسیم گری هست و درخت فایل‌های SCSS از این عمیق‌تر نمیشه.

فولدر بندی من برای partialise کردن فایل‌ها.
فولدر بندی من برای partialise کردن فایل‌ها.

بعدش توی فایل style که میشه گفت ریشه اصلی این درخت هست، اینطوری می‌نویسم:

/* @import helpers */
@import 'helpers/variables';
@import 'helpers/requirement';
@import 'helpers/extensions';
@import 'helpers/reset';

/* @import public */
@import 'public/public';

/* @import home; */
@import 'pages/pages';

ترتیب در کد بالا، خیلی اهمیت داره. همین کار رو برای public و pages هم باید انجام بدیم، مثلا فایل pages رو هم اینجا می‌نویسم:

/* @import pages */
@import 'home/home';
@import 'login/login';
@import 'sourcePayment/sourcePayment';
@import 'requestMoney/request-money';
@import 'ipgBack/ipg-back';

و چون طبق عکس صفحه sourcePayment قسمت زیرین هم داشت بد نیست کد اون رو هم ببینید:

/* @import partials */
@import "partials/buttons";

/** @define source payment; */
.source-payment {

    &__text-field {
        @extend %align-row;
        justify-content: space-between;
        margin-bottom: 20px;
        width: 85%;

        &--money {
            @extend %align-row;
            justify-content: center;
            margin-bottom: 20px;
            width: 85%;
        }

        &__help-text {
            display: block;
            width: 235px;
        }

        &__avatar {
            @extend %radius-circle;
            @extend %center;
            width: 100px;
            height: 100px;
        }
    }

    input {
        width: 85%;
    }
}

.single-button {
    @extend %align-row;
    justify-content: flex-end;
}

.modal-pin-code {
    @extend %position-c-c;
    width: 85%;
    padding: 20px;

    > div > div {
        margin-bottom: 20px;
    }
}


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

امیدوارم که این مقاله تونسته باشه اونطور که باید حق مطلب رو ادا کرده باشه.