مقدمه

در درس قبل با مؤلفه‌های اصلی تشکیل‌دهنده‌ی RWD آشنا شدیم و بررسی مهمترین مؤلفه یعنی Media Query‌ را به این درس موکول کردیم. با استفاده از مدیا کوئری‌ها می‌توانیم قاعده‌هایی را تعریف کنیم که اعمال آنها روی عناصر به برآورده شدن شرط یا شروط مشخصی وابسته شود.

تعریف یک مدیا کوئری

یک media query با استفاده از یک at-rule به فرم @media تعریف می‌شود و یک نوع رسانه (medium) مثل screen یا print را به همراه صفر، یک یا چند شرط تعیین می‌کند و سپس، با یک بلاک شامل قاعده‌های CSS ادامه می‌یابد. قاعده‌های درون بلاک یک مدیا کوئری تنها در صورتی اجرا می‌شوند که دستگاهی که کاربر از آن برای مشاهده‌ی صفحه استفاده می‌کند، از نوع رسانه‌ی مشخص‌شده توسط مدیا کوئری باشد و شرط یا شرط‌های تعریف‌شده نیز برآورده شوند.

تا قبل از CSS3، یک @media فقط نوع دستگاه را با استفاده از مقادیری مثل screen، print، tv، braille و غیره مشخص می‌کرد و کاربرد اصلی آن تعیین استایل‌های مجزایی برای اسناد چاپی بود:

Copy Icon CSS
/* Print only */
@media print {
    /* Hide navigation */
    #navigation {
        display: none;
    }

    /* Start h1 elements on a new page */
    h1 {
        page-break-before: always;
    }
}

قاعده‌های @media معمولاً در انتهای سند قرار داده می‌شوند تا به مکانیزم Cascade امکان لغو یا override قاعده‌هایی که زودتر تعریف شده‌اند، داده شود. به علاوه، این امکان هم وجود دارد که استایل‌های مورد نظر را در یک استایل‌شیت مجزا وارد کرد و سپس، شرط مورد نظر را با استفاده از صفت media برای یک عنصر link تعیین کرد. البته باید توجه داشته باشید که در این روش، استایل‌شیتِ مشخص‌شده فارغ از برآورده شدن یا نشدن شرط، دانلود می‌شود.

Copy Icon HTML
<link rel="stylesheet" media="print" href="myprint.css">

در اینجا فایل استایل‌شیت myprint.css دانلود می‌شود اما فقط زمانی اِعمال می‌شود که صفحه را چاپ کنیم.

اما در CSS3، امکان افزودن شرط یا شرط‌هایی مربوط به قابلیت‌های دستگاه نیز فراهم شد که مهمترین آنها min-width، max-width، min-height و max-height هستند.

Copy Icon CSS
@media screen and (min-width: 600px) {

}

اجازه دهید مثالی از یک مدیا کوئری ساده ببینیم.

 Copy Icon CSS
h1{
  color: red;
}

@media screen and (min-width: 800px) {
  h1 {
      color: blue;
  }
}

در اینجا رنگ قرمز برای عناصر h1 موجود در صفحه تعیین شده و در ادامه یک مدیا کوئری آورده شده که حرفش این است: اگر دستگاه از نوع screen باشد و عرض viewport (یعنی ناحیه‌ای از پنجره‌ی مرورگر که صفحه در آن نمایش داده می‌شود) بیشتر یا مساوی با 800px باشد، رنگ عناصر h1 موجود در صفحه آبی شود.

یک ویژگی مهم مدیا کوئری‌ها، دینامیک بودن آنهاست. یعنی مدام ارزیابی می‌شوند و با تغییر شرایط، مجدداً روی صفحه اعمال می‌شوند. برای تأیید این موضوع، کد بالا را اجرا کنید و پنجره‌ی مرورگر یا در واقع، عرض viewport را تغییر اندازه دهید و ببینید که در عرض 800px تغییر رنگ برای عناصر h1 رخ می‌دهد.

در طراحی واکنشگرا، پراپرتی‌های min-width و max-width از اهمیت زیادی برخوردارند، چون شاخص‌های مناسبی برای سایز viewport هستند. اما انواع دیگری از این پراپرتی‌ها هم وجود دارد که البته کاربرد کمتری دارند. مثلاً قاعده‌ی زیر فقط زمانی اجرا می‌شود که دستگاه کاربر در وضعیت landscape (افقی)‌ قرار داشته باشد؛ یعنی عرضش از ارتفاعش بیشتر باشد.

 Copy Icon CSS
@media screen and (orientation: landscape) {
  h1 {
    color: blue;
  }
}

به طور کلی، بعضی از کوئری‌ها بر اساس ویژگی‌های فیزیکی دستگاه (مثل width و orientation) هستند و برخی دیگر بر اساس تنظیماتی که کاربر در سیستم‌عامل خود انجام داده است. ما قبلاً کوئری prefers-reduced-motion را دیده‌ایم و به عنوان یک مثال دیگر، می‌توانیم به prefers-color-scheme اشاره کنیم که در پلتفرم‌هایی که از dark mode پشتیبانی می‌کنند، می‌توانیم اجرای استایل‌هایی را به فعال بودن dark mode مشروط کنیم.

Copy Icon CSS
@media (prefers-color-scheme: dark) { 

}

استایل‌هایی که در بلاک مربوط به این مدیا کوئری قرار دهیم، در صورتی روی صفحه اعمال می‌شوند که کاربر dark mode را برای سیستم‌عاملش فعال کرده باشد.

عملگرهای منطقی در مدیا کوئری‌ها

مدیا کوئری‌ها علاوه بر عملگر منطقی and می‌توانند شامل عملگرهای منطقی not، only و or نیز باشند. کاما به عنوان عملگر or برای جداسازی گروه‌هایی از چندین کوئری به کار می‌رود. شرط مدیای زیر در صورتی برآورده می‌شود که صفحه‌نمایش دارای عرض حداقل 700px باشد یا دستگاه دارای مود landscape باشد.

Copy Icon CSS
@media (min-width: 700px), (orientation: landscape) {

}

عملگر not نیز برای نفی یک مدیا کوئری کاربرد دارد. برای مثال، قاعده‌ی مدیای زیر تنها در صورتی اعمال می‌شود که عرض صفحه نمایش 800px نباشد.

Copy Icon CSS
@media not screen and (device-width: 800px) {

}

نقاط توقف یا Breakpoints

یک breakpoint یک نقطه‌ی مرزی یا آستانه‌ای است که طرح‌بندی صفحه در آن نقطه تغییر می‌کند. در واقع، در یک breakpoint شرطی که برای یک مدیا کوئری تعریف شده، برآورده می‌شود و از اینرو استایل‌های تعریف‌شده توسط ان مدیا کوئری روی صفحه اعمال می‌شود. سؤال مهم به تعیین این نقاط توقف یا breakpoints مربوط می‌شود و البته هیچ جواب قطعی و مشخصی برای این سؤال وجود ندارد.

تنوع و تعدد دستگاه‌های پشتیبانی‌کننده از وب به حدی زیاد شده که تعیین breakpoints بر اساس سایز نمایشگرهای دستگاه‌ها کار درستی نیست و در عوض، بهتر است که breakpoints را بر اساس محتوا تعیین کنیم. یعنی طراحی صفحه را با شروع از کوچکترین سایز viewport انجام دهیم و با بزرگ شدن viewport هر جا لازم بود، مدیا کوئری‌هایی را تعریف کرده و تغییرات را اعمال کنیم.

طراحی واکنشگرا با مدیا کوئری‌ها

گفتیم که تجربه نشان داده که بهترین رویکرد برای RWD رویکرد mobile first است که با تکیه بر مدیا کوئری‌ها پیاده‌سازی می‌شود. در این روش، استایل‌های پایه برای نمایشگرهای کوچک و موبایلی مستقیماً و بدون استفاده از مدیا کوئری نوشته می‌شوند. همینطور که viewport را بزرگ‌تر می‌کنید، دقت کنید که طرح‌بندی صفحه چه زمانی به تغییر نیاز دارد و این نقطه یک breakpoint محسوب می‌شود. با استفاده از پراپرتی‌های مدیای min-width و max-width یک مدیا کوئری در این breakpoint تعریف می‌کنیم و قاعده‌های مورد نیاز را در آن وارد می‌کنیم. این روش را با پیدا کردن نقاط توقف بعدی ادامه می‌دهیم.

اجازه دهید با به کارگیری مدیا کوئری‌ها در یک مثال ساده، نقش آنها در RWD را در عمل ببینیم. ابتدا به کد زیر نگاه کنید.

 Copy Icon CSS
body{
  margin: 0;
}

.container{
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.header{
  background: orange;
  padding: 1rem;
}

.main{
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}

.content{
  background: salmon;
  padding: 1rem;
  flex-grow: 1;
}

.sidebar{
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  background: skyblue;
  padding: 1rem;
}

.sidebar a{
  margin: 1rem;
  padding: .5rem 2rem;
  border: 1px solid black;
}

.sidebar2{
  background: lime;
  padding: 1rem;
}

.footer{
  background: beige;
  padding: 1rem;
}

فعلاً از مدیا کوئری‌ها استفاده نکرده‌ایم اما صفحه‌ی ما به لطف واکنشگرایی ذاتی تکنولوژی Flexbox همین الان هم واکنشگراست. این مثال را اجرا کنید و پنجره‌ی نمایش را کوچک کنید تا به عرض 300px برسد. همانطرو که می‌بینید، صفحه دارای یک طرح‌بندی تک‌ستونه است و به‌خوبی نمایش داده می‌شود. حالا عرض پنجره را بیشتر کنید تا ببینید که چطور نمایش لینک‌های درون nav از حالت عمودی به افقی تغییر می‌کند؛ این اتفاق به‌خاطر استفاده از پراپرتی flex-wrap با مقدار wrap برای عنصر nav رخ می‌دهد.

حالا با استفاده از یک مدیا کوئری ترتیبی می‌دهیم تا در عرض 700px تغییراتی در صفحه ایجاد شود.

 Copy Icon CSS
@media screen and (min-width: 700px) {
.main {
  flex-direction: row;
}
            
.sidebar {
  flex-direction: column;
  justify-content: flex-start;
}
}