کوئری مدیا در CSS — آموزش CSS (بخش سی و سوم)
کوئری مدیا در CSS یک روش برای اعمال CSS صرفاً در زمان تطبیق مرورگر و محیط دستگاه با یک قاعده مشخص مانند داشتن عرض ویوپورت بیشتر از 480 پیکسل است. کوئریهای مدیا بخشی کلیدی از طراحی واکنشگرای وب محسوب میشوند، چون امکان ایجاد لیآوتهای مختلف را بسته به اندازه ویوپورت فراهم میسازند.
از کوئریهای مدیا میتوان برای شناسایی موارد دیگر در مورد محیطی که سایت اجرا میشود نیز استفاده کرد. برای نمونه میتوانیم بفهمیم آیا کاربر از یک صفحه لمسی استفاده میکند یا از یک ماوس بهره گرفته است. در این بخش از سری مطالب آموزش CSS ابتدا به بررسی ساختار کوئری مدیا در CSS میپردازیم و سپس از آنها در یک مثال عملی استفاده میکنیم تا نشان دهیم که طراحی واکنشگرا چه قدر میتواند آسان باشد. برای مطالعه بخش قبلی این سری مقالات آموزشی، روی لینک زیر کلیک کنید:
مبانی کوئری مدیا
سادهترین ساختار کوئری مدیا به صورت زیر است:
1@media media-type and (media-feature-rule) {
2 /* CSS rules go here */
3}
این ساختار شامل موارد زیر است:
- نوع رسانه که به مرورگر اعلام میکند این کد برای چه نوع رسانهای طراحی شده است (صفحه نمایش یا پرینت).
- عبارت مدیا که یک قاعده یا تست است که باید برقرار باشد تا CSS مورد استفاده قرار گیرد.
- مجموعه قواعد CSS که در صورت پاس شدن تست و صحیح بودن نوع مدیا، اعمال خواهند شد.
انواع مدیا
انواع مدیایی که ممکن است وجود داشته باشند، شامل موارد زیر هستند:
- all
- screen
- speech
کوئری مدیای زیر تنها در صورتی اندازه متن را روی 12pt تنظیم میکند که مدیا از نوع پرینت باشد. در غیر این صورت اگر صفحه در مرورگر بارگذاری شده باشد، این قاعده اعمال نخواهد شد.
1@media print {
2 body {
3 font-size: 12pt;
4 }
5}
نکته: نوع مدیا در اینجا متفاوت از MIME type مشهور است.
نکته: انواع دیگری از مدیا در سطح 3 مشخصات کوئریهای مدیا تعریف شدهاند که در ادامه کاهش یافتهاند و نباید از آنها استفاده کرد.
نکته: تعیین انواع مدیا اختیاری است، یعنی اگر نوع مدیا را در کوئری مدیا تعیین نکنید، در این صورت کوئری مدیا به صورت پیشفرض از نوع all استفاده میکند.
قواعد ویژگی مدیا
پس از تعیین نوع مدیا، میتوانید یک ویژگی مدیا را نیز با یک قاعده تعیین کنید.
عرض و ارتفاع
آن ویژگی مدیا که در اغلب موارد به منظور ایجاد طراحیهای واکنشگرا شناسایی میشود، عرض ویوپورت است. بدین ترتیب میتوانیم در صورتی که ویوپورت عرضی کمتر یا بیشتر از یک مقدار مشخص و یا دقیقاً یک عرض معین داشته باشد، قواعد خاصی را اعمال کنیم. این کار با استفاده از ویژگیهای مدیای min-width ،max-width و width انجام مییابد.
این ویژگیها برای ایجاد لیآوتهایی استفاده میشوند که بسته به اندازههای متفاوت صفحهها، واکنش نشان میدهند. برای نمونه برای تغییر دادن رنگ متن صفحه در صورتی که عرض ویوپورت کمتر از 600 پیکسل باشد، میتوان از کوئری مدیای زیر استفاده کرد:
1@media screen and (width: 600px) {
2 body {
3 color: red;
4 }
5}
ویژگیهای مدیای width (و height) میتوانند به صورت یکباره نیز مورد استفاده قرار گیرند. از این رو پیشوندهای min- و max- نشان میدهد که مقادیر مفروض به صورت کمینه یا بیشینه هستند. برای نمونه برای این که در صورت کم بودن عرض ویوپورت از 600 پیکسل، رنگ متن آبی باشد، باید از ویژگی max-width به صورت زیر استفاده کنیم:
1@media screen and (max-width: 600px) {
2 body {
3 color: blue;
4 }
5}
در عمل استفاده از مقادیر کمینه یا بیشینه برای طراحیهای واکنشگرا، بسیار مفیدتر است، بنابراین به ندرت میبینید که width یا height به تنهایی استفاده شده باشند. چند ویژگی مدیای دیگر نیز وجود دارند که میتوانید آنها را تست کنید، اگر چه برخی از ویژگیهای جدیدتر در سطوح 4 و 5 مشخصات کوئری مدیا معرفی شدهاند و پشتیبانی مرورگر محدودی دارند.
جهتگیری
یکی از ویژگیهای مدیا که پشتیبانی خوبی دارد جهتگیری یا Orientation است. این ویژگی به ما امکان میدهد که حالت افقی یا عمودی بودن دستگاه را تشخیص دهیم. برای تغییر رنگ متن در صورتی که دستگاه در حالت افقی قرار داشته باشد، از کوئری مدیای زیر استفاده میکنیم:
1@media (orientation: landscape) {
2 body {
3 color: rebeccapurple;
4 }
5}
نمای استاندارد دسکتاپ به طور معمول افقی است و یک طراحی که در این جهتگیری کار میکند، ممکن است زمانی که روی گوشی یا تبلت در حالت عمودی مورد استفاده قرار گیرد، به درستی نمایش نیابد. تست کردن جهتگیری میتواند به ایجاد لیآوتی که برای حالت افقی دستگاه بهینه شده باشد، کمک کند.
استفاده از دستگاههای اشارهگر
بخشی از مشخصات سطح 4 کوئریهای مدیا به ویژگی مدیای hover اختصاص دارد. با استفاده از این ویژگی میتوان تست کرد که آیا کاربر توانایی بردن یک دستگاه اشارهگر را به روی عنصر دارد یا نه. نتیجه این تست مشخص میکند که کاربر از یک نوع دستگاه اشارهگر مانند صفحه لمسی و یا روش غیر اشارهگر مانند ناوبری کیبورد استفاده میکند.
1@media (hover: hover) {
2 body {
3 color: rebeccapurple;
4 }
5}
اگر بدانیم که کاربر امکان hover ندارد، میتوانیم برخی ویژگیهای تعاملی را به صورت پیشفرض نمایش دهیم. برای کاربرانی که امکان hover دارند، میتوانیم کاری کنیم که بتوانند روی یک لینک hover کنند.
همچنین در مشخصههای سطح 4 با ویژگی مدیای pointer نیز مواجه میشویم. این ویژگی سه مقدار به صورت none ،fine و coarse دارد. اشارهگر fine چیزی مانند یک ماوس یا ترکپد است. این اشارهگر به کاربران امکان میدهد که ناحیه کوچکی را به دقت هدفگیری کنند. اشارهگر coarse به استفاده از انگشت روی صفحههای لمسی گفته میشود. مقدار none به آن معنی است که کاربر دستگاه اشارهگر ندارد و شاید با استفاده از کیبورد یا فرمان صوتی ناوبری میکند.
استفاده از ویژگی pointer به طراحی بهتر اینترفیسها برای پاسخدهی به انواع گوناگونی از تعاملهای کاربری که صفحه نمایش دارد، کمک میکند. برای نمونه در صورتی که بدانید کاربر با استفاده از صفحه لمسی دستگاه در حال تعامل با صفحه است، میتوانید یک ناحیه تماس بزرگتری در اختیار وی قرار دهید.
کوئریهای مدیای پیچیدهتر
با توجه به وجود انواع بسیار مختلفی از کوئریهای مدیا، ممکن است بخواهید آنها را با هم ترکیب کنید یا لیستی از کوئریها ایجاد کنید که هر یک از آنها میتوانند تطبیق پیدا کنند.
منطق and در کوئریهای مدیا
برای ترکیب کردن ویژگیهای مدیا، میتوانیم از and به همان روشی که برای ترکیب نوع و ویژگی مدیا استفاده میکردیم، بهره بگیریم. برای نمونه ممکن است بخواهیم ویژگیهای min-width و orientation را تست کنیم. در این صورت متن ما در صورتی که عرض ویوپورت کمتر از 600 پیکسل باشد و دستگاه نیز در حالت افقی باشد، به رنگ آبی درمیآید.
1@media screen and (min-width: 600px) and (orientation: landscape) {
2 body {
3 color: blue;
4 }
5}
منطق or در کوئریهای مدیا
اگر یک مجموعه از کوئریها داشته باشید که هر یک از آنها میتوانند تطبیق پیدا کنند، در این صورت میتوانید با قرار دادن کاما بین کوئریها، آنها را از هم جدا کنید. در مثال زیر متن در صورتی به رنگ آبی درمیآید که عرض ویوپورت کمتر از 600 پیکسل باشد «یا» جهتگیری دستگاه به صورت افقی باشد. اگر هر کدام از این موارد برقرار باشند، کوئری تطبیق پیدا خواهد.
1@media screen and (min-width: 600px), screen and (orientation: landscape) {
2 body {
3 color: blue;
4 }
5}
منطق not در کوئریهای مدیا
امکان منفی ساختن کل یک کوئری مدیا با استفاده از عملگر not وجود دارد. این عملگر معنای کل کوئری مدیا را معکوس میسازد. از این رو در مثال زیر، متن صفحه در صورتی به رنگ آبی درمیآید که جهتگیری دستگاه به صورت افقی باشد.
1@media not all and (orientation: landscape) {
2 body {
3 color: blue;
4 }
5}
انتخاب breakpoint
در آغازین روزهای ظهور طراحیهای واکنشگرا (Responsive)، بسیاری از طراحان تلاش میکردند تا اندازههای بسیار خاص صفحهها را هدفگیری کنند. لیستی از اندازههای صفحههای گوشیها و تبلتهای رایج در بازار جمعآوری شده بود تا طراحان بتوانند دقیقاً طراحی خود را بر مبنای آن ویوپورتها تطبیق بدهند.
اینک تعداد دستگاهها و تنوع آنها چنان گسترش یافته است که این کار ناممکن شده است. این بدان معنی است که اکنون به جای هدفگیری اندازه دقیق برای همه طراحیها، بهتر است طراحی را در یک اندازه خاص تغییر دهیم. شاید طول خطوط متن بیش از حد طولانی باشد یا سایدبار چنان فشرده شده باشد که خوانایی آن دشوار شود. این همان نقطهای است که باید از کوئری مدیا استفاده کنیم تا طراحی را برای استفاده بهتر از فضا تغییر دهیم. بر اساس این رویکرد مهم نیست که ابعاد واقعی دستگاه چه قدر است. نقاطی که کوئریهای مدیا برای آنها ساخته شدهاند به نام «نقاط توقف» (breakpoints) شناخته میشوند.
حالت طراحی واکنشگرا در بخش DevTools مرورگر فایرفاکس برای کار با این نقاط توقف بسیار عالی است. شما میتوانید به سادگی کاری کنید که ویوپورت کوچکتر یا بزرگتر شود تا ببینید محتوا افزودن کوئری مدیا و دستکاری طراحی چطور بهبود مییابد.
مثال عملی برای یک طراحی واکنشگرای اول-موبایل
به طور کلی دو رویکرد برای یک طراحی واکنشگرا وجود دارد. شما میتوانید کار خود را با دسکتاپ یا عریضترین نما آغاز کنید و سپس نقاط توقف را برای جابجا کردن موارد مختلف در هنگام کاهش عرض ویوپورت اضافه کنید و یا از کوچکترین نما آغاز کنید و لیآوتی را در زمان افزایش عرض ویوپورت اضافه کنید. این رویکرد دوم به صورت طراحی واکنشگرای «اول-موبایل» (mobile first) شناخته میشود و غالباً به عنوان رویکرد مناسبی برای اجرا نگریسته میشود.
نما برای کوچکترین دستگاهها در اغلب موارد یک ستون ساده منفرد از محتوا است که غالباً به شکل گردش نرمال صفحه دیده میشود. این بدان معنی است که احتمالاً نیازی به دستکاری زیادی برای طراحی لیآوت دستگاه روی دستگاههای کوچک نخواهید داشت. در صورتی که سورس صفحه را به ترتیب خوبی بچینید، به صورت پیشفرض یک لیآوت خوانا خواهید داشت.
مسیری که در بخش زیر معرفی شده است شما را با استفاده از این رویکرد برای خلق یک لیآوت کاملاً ساده آشنا میسازد. در یک سایت عملیاتی احتمالاً باید موارد بیشتری را درون کوئریهای مدیا تنظیم کنید، اما رویکرد کلی دقیق همین گونه است.
یک لیآوت ساده اول-موبایل
نقطه آغازین مثال ما یک سند HTML با مقداری CSS اعمال شده روی رنگهای پسزمینه برای بخشهای مختلف لیآوت است.
1* {
2 box-sizing: border-box;
3}
4
5body {
6 width: 90%;
7 margin: 2em auto;
8 font: 1em/1.3 Arial, Helvetica, sans-serif;
9}
10
11a:link,
12a:visited {
13 color: #333;
14}
15
16nav ul,
17aside ul {
18 list-style: none;
19 padding: 0;
20}
21
22nav a:link,
23nav a:visited {
24 background-color: rgba(207, 232, 220, 0.2);
25 border: 2px solid rgb(79, 185, 227);
26 text-decoration: none;
27 display: block;
28 padding: 10px;
29 color: #333;
30 font-weight: bold;
31}
32
33nav a:hover {
34 background-color: rgba(207, 232, 220, 0.7);
35}
36
37.related {
38 background-color: rgba(79, 185, 227, 0.3);
39 border: 1px solid rgb(79, 185, 227);
40 padding: 10px;
41}
42
43.sidebar {
44 background-color: rgba(207, 232, 220, 0.5);
45 padding: 10px;
46}
47
48article {
49 margin-bottom: 1em;
50}
ما هیچ تغییری در لیآوت ایجاد نکردهایم، اما سورس سند به ترتیبی مرتب شده است که محتوای آن خوانا باشد. این یک گام مهم است و ما را مطمئن میسازد که اگر قرار باشد محتوا از سوی یک نرمافزار قرائت صفحه خوانده شود، قابل درک خواهد بود.
1<body>
2 <div class="wrapper">
3 <header>
4 <nav>
5 <ul>
6 <li><a href="">About</a></li>
7 <li><a href="">Contact</a></li>
8 <li><a href="">Meet the team</a></li>
9 <li><a href="">Blog</a></li>
10 </ul>
11 </nav>
12 </header>
13 <main>
14 <article>
15 <div class="content">
16 <h1>Veggies!</h1>
17 <p>
18 ...
19 </p>
20 </div>
21 <aside class="related">
22 <p>
23 ...
24 </p>
25 </aside>
26 </article>
27
28 <aside class="sidebar">
29 <h2>External vegetable-based links</h2>
30 <ul>
31 <li>
32 ...
33 </li>
34 </ul>
35 </aside>
36 </main>
37
38 <footer><p>©2019</p></footer>
39 </div>
40 </body>
این لیآوت ساده روی موبایل نیز به خوبی کار میکند. اگر نمای طرحبندی شده خودمان را در حالت طراحی واکنشگرای بخش DevTools مرورگر بررسی کنیم، میبینیم که به صورت یک نمای موبایل سرراست از سایت به درستی کار میکند.
در این بخش، به تدریج عرض صفحه را کشیده و افزایش دهید تا این که ببینید خطوط بیش از حد طولانی میشود و خوانایی آن کاهش مییابد. اینک امکان نمایش منوی ناوبری در خط افقی وجود دارد. این همان جایی است که کوئری مدیای اول را اضافه میکنیم. ما از ems استفاده میکنیم، زیرا اگر کاربر بخواهد اندازه متن را افزایش دهید، نقاط توقف در طول خطوط یکسانی رخ میدهند، اما عرض ویوپورت در موردی که اندازه متن کوچکتر باشد، بیشتر خواهد بود.
کد زیر را به انتهای CSS فایل قبلی اضافه کنید:
1@media screen and (min-width: 40em) {
2 article {
3 display: grid;
4 grid-template-columns: 3fr 1fr;
5 column-gap: 20px;
6 }
7
8 nav ul {
9 display: flex;
10 }
11
12 nav li {
13 flex: 1;
14 }
15}
CSS فوق از لیآوت دو ستونی درون مقاله استفاده میکند. همچنین از flexbox برای قرار دادن ناوبری در یک ردیف استفاده کردهایم. اکنون اگر فایل را در یک زبانه جدید مرورگر باز کنید، با تصویری مانند زیر مواجه میشوید.
در ادامه عرض را اضافه میکنیم تا این که حس کنیم آن قدر افزایش یافته که سایدبار را نیز بتوان در یک ستون جدید اضافه کرد. در کوئریهای مدیا، عنصر اصلی را یک گرید دو ستونی قرار میدهیم. سپس باید margin-bottom روی article را حذف کنیم تا دو سایدبدر با یکدیگر همسو شوند و یک border به بالای فوتر اضافه میکنیم. به طور معمول این دستکاریهای کوچک کارهایی هستند که برای نمایش بهتر لیآوت در هر breakpoint باید انجام دهیم. یک بار دیگر کد زیر را به انتهای CSS قبلی اضافه کنید:
1@media screen and (min-width: 70em) {
2 main {
3 display: grid;
4 grid-template-columns: 3fr 1fr;
5 column-gap: 20px;
6 }
7
8 article {
9 margin-bottom: 0;
10 }
11
12 footer {
13 border-top: 1px solid #ccc;
14 margin-top: 2em;
15 }
16}
اگر به این مثال نهایی نگاه کنید، میبینید که در عرضهای مختلف، طراحی چطور به صورت تکستونی، دو ستونی و یا سهستونی تبدیل میشود. این یک مثال بسیار ساده از طراحی واکنشگرای اول-موبایل است.
تگ متای ویوپورت
اگر به سورس HTML مثال فوق نگاه کنید، خواهید دید که عنصر زیر در بخش head سند قرار دارد:
1<meta name="viewport" content="width=device-width,initial-scale=1">
این تگ متای ویوپورت است و برای کنترل شیوه رندر محتوا از سوی مرورگرهای موبایل استفاده میشود. این گزینه باید به صورت پیشفرض استفاده شود، زیرا اغلب مرورگرهای موبایل در مورد عرض ویوپورتشان دروغ میگویند. سایتهای غیر واکنشگرا به طور معمول زمانی که روی مرورگرهای با عرض کم رندر شوند، ظاهر بسیار بدی مییابد و از این رو مرورگرهای موبایل معمولاً سایت را با یک عرض ویوپورت عریضتر از عرض واقعی دستگاه و به صورت پیشفرض 960 پیکسل رندر میکنند و سپس نتیجه رندر شده را طوری کوچک میکنند که در نمایشگر دستگاه جا شود.
این رویه بدی نیست، اما از طرف دیگر موجب میشود که سایتهای واکنشگرا مطابق انتظار ما عمل نکنند. اگر عرض ویوپورت به مقدار 960 پیکسل باشد، در این صورت لیآوتهای موبایل، برای مثال آنها که با دستور زیر ساخته شدهاند، مطابق انتظار رندر نمیشوند:
1@media screen and (max-width: 600px) { ... })
برای رفع این مشکل باید تگ متای ویوپورت را مانند کد فوق در صفحه قرار دهید تا به مرورگر اعلام کنید که محتوا را با عرض 960 پیکسل ویوپورت رندر نکند و آن را با استفاده از عرض دستگاه واقعی رندر کند و سطح مقیاس اولیه پیشفرض برای انسجام بهتر تعیین کند. در این صورت کوئریهای مدیا به درستی کار میکنند.
برخی گزینههای دیگر نیز وجود دارند که میتوان درون خصوصیت content تگ متای ویوپورت قرار داد. برای کسب اطلاعات بیشتر به این صفحه (+) مراجعه کنید.
آیا ما واقعاً به یک کوئری مدیا نیاز داریم؟
لیآوتهای چندستونی، Flexbox و Grid همگی روشهایی برای ایجاد مؤلفههایی انعطافپذیر و در عین حال واکنشگرا بدون نیاز به کوئریهای مدیا فراهم میسازند. همواره بهتر است دستاوردهای استفاده از این موارد را بدون بهرهگیری از کوئریهای مدیا بررسی کنیم. برای نمونه ممکن است بخواهید یک مجموعه کارتها داشت باشید که عرضشان دست کم 200 پیکسل باشد و هر تعداد از این کارتهای 200 پیکسلی که ممکن است در عرض مقاله قرار گیرد. این کار با استفاده از لیآوت گرید ممکن است و هیچ نیازی به استفاده از کوئری مدیا وجود ندارد. به کد زیر توجه کنید:
1<ul class="grid">
2 <li>
3 <h2>Card 1</h2>
4 <p>...</p>
5 </li>
6 <li>
7 <h2>Card 2</h2>
8 <p>...</p>
9 </li>
10 <li>
11 <h2>Card 3</h2>
12 <p>...</p>
13 </li>
14 <li>
15 <h2>Card 4</h2>
16 <p>...</p>
17 </li>
18 <li>
19 <h2>Card 5</h2>
20 <p>...</p>
21 </li>
22</ul>
1.grid {
2 list-style: none;
3 margin: 0;
4 padding: 0;
5 display: grid;
6 gap: 20px;
7 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
8}
9
10.grid li {
11 border: 1px solid #666;
12 padding: 10px;
13}
در تصویر فوق میبینید که با افزایش یا کاهش عرض صفحه، تعداد کارتها تغییر مییابند. نکته جالب در مورد این روش آن است که گرید کاری با عرض ویوپورت ندارد، بلکه عرض موجود برای کامپوننت را بررسی میکند.
سخن پایانی
در این بخش از سری مطالب آموزش CSS با کوئریهای مدیا در CSS آشنا شدیم و شیوه استفاده عملی از آنها و ایجاد یک طراحی واکنشگرای اول-موبایل را بررسی کردیم. شما میتوانید از مثال اولیه که ما در این مطلب برای تست کوئریهای مدیا ایجاد کردیم، بهره بگیرید و با تغییر اندازه یا ناوبری یک لیآوت خاص و سفارشی برای خود بسازید.
همچنین میتوانید کامپوننتهای متفاوتی به این لیآوت اضافه کنید تا ببینید افزودن یک کوئری مدیا یا استفاده از روش لیآوتی مانند flexbox یا Grid چه تأثیری روی طراحی واکنشگرای شما خواهد داشت. در واقع در اغلب موارد هیچ روش درست یا نادرستی وجود ندارد و باید آزمایش کنید تا ببینید کدام گزینه برای نوع طراحی و محتوای شما بهتر است.
برای مطالعه بخش بعدی از مجموعه مطالب آموزش CSS میتوانید روی لینک زیر کلیک کنید: