برای راحتتر شدن طراحی واکشگرا(Responsive) ابزار، فریمورک و روشهای بسیاری آمده که در همین رابطه قصد دارم ساختاری که برای تعریف مدیا کوئریها در Sass استفاده میکنم را شرح دهم. در انتها این مطلب با مفاهیم زیر آشنا میشوید:
- Interpolation – #{}
- @content
- nth()
- length()
- @warn
من طرفدار فریمورک Zurb Foundation هستم، پس اول به روش فاندیشن متغیرهای مربوط به مدیا کوئری را تعریف میکنم.
اولین سری متغیرها مشخص کننده محدودهی مدیا کوئریها هستند که به پنج قسمت تقسیم شدند(شما میتونید این محدودهها و تعدادشون را بر اساس نیاز خودتون تغییر بدهید):
//
// Settings
//
// Media Query Ranges
$small-range: (0em, 40em);
$medium-range: (40.063em, 64em);
$large-range: (64.063em, 90em);
$xlarge-range: (90.063em, 120em);
$xxlarge-range: (120.063em, 99999999em);
دومین سری متغیرها برای ساختارمند شدن، عبارتهای مدیا کوئریها هستند(عبارتهایی که در مقابل @media قرار خواهد گرفت):
// Media Query Expressions
$screen: "only screen";
$landscape: "#{$screen} and (orientation: landscape)";
$portrait: "#{$screen} and (orientation: portrait)";
$small-up: $screen;
$small-only: "#{$screen} and (max-width: #{upper-bound($small-range)})";
$medium-up: "#{$screen} and (min-width:#{lower-bound($medium-range)})";
$medium-only: "#{$screen} and (min-width:#{lower-bound($medium-range)}) and (max-width:#{upper-bound($medium-range)})";
$large-up: "#{$screen} and (min-width:#{lower-bound($large-range)})";
$large-only: "#{$screen} and (min-width:#{lower-bound($large-range)}) and (max-width:#{upper-bound($large-range)})";
$xlarge-up: "#{$screen} and (min-width:#{lower-bound($xlarge-range)})";
$xlarge-only: "#{$screen} and (min-width:#{lower-bound($xlarge-range)}) and (max-width:#{upper-bound($xlarge-range)})";
$xxlarge-up: "#{$screen} and (min-width:#{lower-bound($xxlarge-range)})";
$xxlarge-only: "#{$screen} and (min-width:#{lower-bound($xxlarge-range)}) and (max-width:#{upper-bound($xxlarge-range)})";
در تعریف متغیرهای بالا از خاصیت Interpolation(#{}) استفاده شده که این اجازه را به ما میدهد تا یک متغیر را درون یک متن(نوع محتوای String) نمایش دهیم.
دو تابع به نامهای lower-bound و upper-bound تعریف شده که خیلی ساده به ترتیب عدد اول محدوده هر مدیا کوئری و عدد دوم محدودهی هر مدیا کوئری را میگیرد. این دو تابع را به صورت زیر قبل از تعریف متغیرها بنویسید:
//
// Functions
//
// RANGES
// We use these functions to define ranges for various things, like media queries.
@function lower-bound($range){
@if length($range) <= 0 {
@return 0;
}
@return nth($range,1);
}
@function upper-bound($range) {
@if length($range) < 2 {
@return 999999999999;
}
@return nth($range, 2);
}
اگر قسمت @if را در تابعهای بالا در نظر نگیرید کار اصلی این تابعها خیلی سادست و با استفاده از تابع پیش فرض Sass به نام nth مقدار اول یا دوم لیست را برمیگرداند که برای ما حداقل و حداکثر محدوده مدیا کوئریها خواهد بود. شرطهای گذاشته شده در توابع هم برای کنترل خطا در نوشتار است که با استفاده از تابع length در تابع اول اگر تعداد مقدارهای لیست $range مساوی یا کمتر از صفر باشد مقدار صفر را برمیگرداند و در تابع upper-bound اگر تعداد خانه های لیست $range بیشتر از دو تا باشد عدد بزرگی به عنوان حداکثر محدوده برگشت داده میشود. با توجه به این نوع تعریف متغیر، از این به بعد اگر بخواهیم مدیا کوئری را تعریف کنیم فقط کافی است اینگونه بنویسیم:
@media #{$medium-only} {
// CSS Codes Here
}
بعد از کامپایل خروجی CSS به صورت زیر خواهد شد:
@media only screen and (min-width:40.063em) and (max-width:64em) {
// CSS Codes Here
}
همانطور که دیدید با این روش تعریف مدیا کوئریها خیلی سادهتر شد. میخواهیم با تعریف یک میکسین بتوانیم در هر قسمت کدهای مربوط به Responsive آن بخش را در همان قسمت تعریف کنیم:
//
// Mixin
//
@mixin breakpoint($point) {
@if $point == small {
@media #{$small-only} { @content; }
}
@else if $point == small-up {
@media #{$small-up} { @content; }
}
@else if $point == medium {
@media #{$medium-only} { @content; }
}
@else if $point == medium-up {
@media #{$medium-up} { @content; }
}
@else if $point == large {
@media #{$large-only} { @content; }
}
@else if $point == large-up {
@media #{$large-up} { @content; }
}
@else if $point == xlarge {
@media #{$xlarge-only} { @content; }
}
@else if $point == xlarge-up {
@media #{$xlarge-up} { @content; }
}
@else if $point == xxlarge {
@media #{$xxlarge-only} { @content; }
}
@else if $point == xxlarge-up {
@media #{$xxlarge-up} { @content; }
}
@else {
@warn "This breakpoint '#{$point}' doesn't exist!";
}
}
میکسینها خاصیتی دارند به نام @content که این امکان را میدهد تا مجموعه از کد را به میکسین ارسال کنید و میکسین دوباره آن را برگرداند، کد زیر را ببینید تا منظورم را متوجه شوید:
#nav {
@include breakpoint(small) {
li {
display: block;
margin-right: 0;
}
}
@include breakpoint(medium-up) {
ul {
float: left;
width: 80%;
}
li {
display: inline-block;
margin-right: 1rem;
}
}
}
خروجی کد:
@media only screen and (max-width: 40em) {
#nav li {
display: block;
margin-right: 0;
}
}
@media only screen and (min-width: 40.063em) {
#nav ul {
float: left;
width: 80%;
}
#nav li {
display: inline-block;
margin-right: 1rem;
}
}
با استفاده از این روش میکسین breakpoint را درون selector مورد نظر include کنید و نام مدیا کوئری را به عنوان پارامتر میکسین و CSS های مربوط به حالت واکنشگرا را به عنوان Content میکسین بفرستید.
نمایش این کد را در Sass Meister ببینید: http://sassmeister.com/gist/8699429cdf4dec17332c
کدها را از این آدرس میتونید دریافت کنید: https://gist.github.com/parhumm/8699429cdf4dec17332c
نکته: @warn برای کنترل خطاها قرار داده شده تا اگر نام مدیا کوئری را اشتباه وارد کردید مشکل را در Terminal نمایش دهد.
اگر مایلید بیشتر در مورد این موضوعات بدونید، خواندن این دو مطلب نیز به شما کمک میکند:
امیدوارم این مطلب برای شما گویا و مفید باشد. لطفا اگر جایی از توضیحات نامفهوم بود، در نظرات آن را مطرح کنید.
کامل و جامع. نه خسته :)
یه ماه پیش که اون قسمت آخر کدت که مربوط به خاصیت content میشه رو دیدم، نمیدونم چطور شد که فکر کردم این کار میکنه!! https://github.com/hail2u/node-css-mqpacker
الان که برگشتم، یه نگاه بهش بندازم تازه فهمیدم چشام باباقوری دیده!
لذا با اجازت، قسمت اول کامنت قبلیم، پس میگیرم؛ و اون اسمایلی رو هم به خودم تقدیم میکنم بابت این سوتی بزرگ :)
+ (خداییش اون موقع برق از سه فازم پریده بود، که چطور مدیا کوئری ها تجمیع میشدن به این راحتی و من ازش بی خبر بودم. امان از عجله و زندگی مینیمال :)
نه این کار که من یه عمر تو Sass دنبالش بودم دیدم هیچ جوره در حال حاضر با خود Sass امکان نداره!