چجوری با SASS یکبار کد بزنیم و دو خروجی RTL و LTR بگیریم؟

یکی از مشکلاتی که همیشه در طراحی سایت درگیرش بودیم و ساعت‌ها وقتمون را در شرکت می‌گرفت طراحی سایت‌های دو زبانه و ماجرای RTL کردن بود. اما با استفاده از Sass و ایده گرفتن از روشی که Foundation برای راست به چپ کردن استفاده کرده به روشی رسیدم که به راحتی می‌توانید یکبار کد بزنید اما با تغییر مقدار یک متغیر خروجی متفاوتی از فایل CSS خود بگیرید.

کد زیر بر همین اساس نوشته شده:

// Choose your site direction. LTR or RTL?
$text-direction: ltr;

// We equal $text-direction to $dir, you can use both of them in your code
@import "direction-controller";

body {
    direction: $dir;
    text-align: $left;

    // For different image in your code, you can use this solution. Use
    background-image: url(../img/#{$dir}/bg.png);
    background-position: $left top;

	@include if-ltr {
		line-height: 18px;
	}
	@include if-rtl {
		line-height: 22px;
		h1 {
			line-height: 25px;
		}
	}
}

#container {
    float: $left;
    line-height: dir-check(52px, 30px);
    padding: dir-values(1px 2px 3px 0);
}

#sidebar {
    float: $right;
    margin-#{$left}: 50px;
}
.next {
	content: dir-check('>', '<');
}
.br {
	border-radius: br-values(0 0 25px 0);
}

همانطور که میبینید فقط کافی است یکسری قوانین را در نوشتن رعایت کنید. برای گرفتن خروجی rtl یا ltr مقدار متغیر text-direction را تغییر دهد.(خروجی را ببینید: RTL، LTR)

روش استفاده

یک مجموعه توابع و میکسین نوشتم که پس از متغیر text-direction آن را import می‌کنیم. نگاهی به این فایل بیاندازید.

متغیر‌ها

در این فایل دو متغیر right و left تعریف شده که این دو بر اساس rtl بودن یا نبودن مقدار آن‌ها تغییر می‌کند:

// Choose Your Site Language Direction: ltr or rtl?
$text-direction: ltr 	!default;

// No need to change this conditional statement, $text-direction variable controls it all.
$dir: $text-direction;

$left: left;
$right: right;

// Mixin and Functions
@if $dir != ltr {
	$left: right;
	$right: left;
}

در این روش دید من این بوده که شما دارید یک سایت چپ به راست طراحی می‌کنید. پس حالا با استفاده از این دید کد خود را شروع کنید و از این به بعد به جای کلمه right و left از متغیر آن استفاده کنید. مثال زیر را ببینید:

#sidebar {
    float: $right;
    margin-#{$left}: 50px;
    #{$left}: 0;
}

خروجی با مقدار ltr:

#sidebar {
  float: right;
  margin-left: 50px;
  left: 0;
}

خروجی با مقدار rtl:

#sidebar {
  float: left;
  margin-right: 50px;
  right: 0;
}

توابع

سه تابع برای تکمیل این روش اضافه کردم که برای کنترل margin، padding، border-radius و content بیشتر به کار می‌آید:

dir-check
این تابع دو پارامتر ورودی می‌گیرد و اگر سایت چپ به راست باشد پارامتر اول و گرنه پارامتر دوم را بر می‌گرداند. کد زیر را ببینید:

// dir-check function check if direction equal ltr return first parametr, else return secound parameter
@function dir-check($a, $b) {
	@if $dir == ltr {
		@return $a;
	} @else {
		@return $b;
	}
}

.next {
	content: dir-check('>', '<');
}

خروجی با مقدار ltr:

.next {
	content: '>';
}

خروجی با مقدار rtl:

.next {
	content: '<';
}

dir-values
این تابع یک ورودی چهار پارامتری می‌گیرد مانند مقدار margin یا padding و بر اساس زبان سایت پارامتر‌ها را جابجا می‌کند.کد زیر را ببینید:

// dir-values Reorder right and left positions in padding/margin values list
@function dir-values($values) {
	@if $dir == rtl and length($values) == 4 {
		@return nth($values, 1) nth($values, 4) nth($values, 3) nth($values, 2);
	}
	@else {
		@return $values;
	}
}
#container {
    padding: dir-values(1px 2px 3px 0);
}

خروجی با مقدار ltr:

#container {
    padding: 1px 2px 3px 0;
}

خروجی با مقدار rtl:

#container {
    padding: 1px 0 3px 2px;
}

br-values
این تابع هم مانند تابع قبلی یک ورودی چهار پارامتری می‌گیرد اما نحوه جابجایی پارامتر‌هایش فرق دارد و برای border-radius استفاده می‌شود.کد زیر را ببینید:

// br-values Reorder right and left positions in border-radius values list
@function br-values($values) {
	@if $dir == rtl and length($values) == 4 {
		@return nth($values, 2) nth($values, 1) nth($values, 4) nth($values, 3);
	}
	@else {
		@return $values;
	}
}
.box {
	border-radius: br-values(0 0 25px 0);
}

خروجی با مقدار ltr:

.box {
    border-radius: 0 0 25px 0;
}

خروجی با مقدار rtl:

.box {
    border-radius: 0 0 0 25px;
}

میکسین‌ها

علاوه بر تابع‌ها دو تا میکسین به نام‌های if-ltr و if-rtl وجود دارد برای نمایش بلوک کد خاصی در rtl و ltr. کد زیر را ببینید:

// These Mixins check your direction and display @content
@mixin if-ltr { 
	@if $dir == ltr {
		@content;
	}
}
@mixin if-rtl {
	@if $dir != ltr {
		@content;
	}
}

body {
	@include if-ltr {
		line-height: 18px;
	}
	@include if-rtl {
		line-height: 22px;
		h1 {
			line-height: 25px;
		}
	}
}

خروجی با مقدار ltr:

body {
  line-height: 18px;
}

خروجی با مقدار rtl:

body {
  line-height: 22px;
}
body h1 {
  line-height: 25px;
}

این پروژه را توی گیت‌هاب گذاشتم تا با هم بتونیم کامل‌ترش کنیم:

پی‌نوشت: بر همین اساس، Bootstrap Sass را هم RTL پذیر کردم، که بزودی لینکش را اینجا میذارم استفاده کنید.

ساختار فایل بندی و اسم چندتا از متغیرها با چیزی که در این مقاله نوشته شده است تغییر کرده است. فایل جدید را از روی گیت‌هاب بردارید.

منتشرشده توسط

پرهام خوشبخت

طراح تعاملی رابط کاربری

6 دیدگاه برای «چجوری با SASS یکبار کد بزنیم و دو خروجی RTL و LTR بگیریم؟»

  1. ای‎ول با sass چقد راحت تر میشه این کار رو کرد، این کار رو با less انجام داده بودم حجم کدش بیشتر شد (البته مهم اینه که کار می‎کرد و می‎کنه :دی)، لینک این پست رو توی اون پست بذارین به نظرم
    به نظرم به جای right و left از start و end استفاده کنین، منطقی تره یا مثلاً far و near.

  2. الان توی CSS جاهایی که برای مقدار، راست یا چپ می گیرن start و end هم قبول می کنه که بر اساس دایرکشن هست، برای همین Start و end رو پیشنهاد دادم

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *