تایپوگرافی سیال بسیار محبوب شده است، به ویژه از زمانی که clamp() تابع ریاضی در هر مرورگر همیشه سبز موجود است. اما اگر صادق باشیم، هنوز هم برای رسیدن به این هدف، ریاضیات زیادی است. می توانید از ابزارهایی مانند utopia.fyi، که فوق العاده هستند. اما در پروژه های بزرگ، می تواند خیلی سریع به هم ریخته شود. من از طرفداران پر و پا قرص کدهای قابل خواندن و نگهداری هستم و همیشه می خواهم ببینم کد من در یک نگاه چه می کند. من مطمئن هستم که تعداد بیشتری از شما مانند آن هستند، بنابراین به جای اضافه کردن کامل clamp() عملکرد داخل کد ما، شاید بتوانیم با Sass این را کمی خواناتر کنیم.

چرا باید از تایپوگرافی سیال استفاده کنیم؟

معمولاً هنگام طراحی برای اندازه های مختلف صفحه نمایش، از پرس و جوهای رسانه ای برای تعیین اندازه فونت عناصر تایپوگرافی خود استفاده می کنیم. اگرچه این معمولاً کنترل کافی را برای دستگاه‌های معمولی‌تر می‌دهد، اما همه اندازه‌های صفحه را پوشش نمی‌دهد.

با استفاده از تایپوگرافی سیال، می‌توانیم مقیاس تایپوگرافی را بین انواع دستگاه‌های مختلف منطقی‌تر کنیم.

این در حال حاضر در تمام مرورگرهای همیشه سبز امکان پذیر است زیرا clamp() عملکرد در CSS برای این کار عالی است و نوشتن پرس و جوی رسانه ما را کاهش می دهد، بنابراین مقداری از حجم فایل را در طول مسیر ذخیره می کنیم.

دقیقا چگونه این کار را انجام می دهد clamp() تابع کار برای تایپوگرافی؟

به طور خلاصه، عملکرد گیره به صورت زیر است:

clamp([min-bound], [value-preferred], [max-bound]);

این سه عدد را در نظر می گیرد: حداقل کران، ارزش ترجیحی، و حداکثر محدود. با استفاده از rem مقادیر، ما می‌توانیم دسترسی را کمی افزایش دهیم، اما هنوز 100% ضد خطا نیست، مخصوصاً برای ابزارهای مرورگر خارجی.

اگر می‌خواهید توضیح عمیق‌تری در مورد ریاضیات داشته باشید، پیشنهاد می‌کنم این پست از Adrian Bece «مدرن تایپوگرافی سیال با استفاده از گیره CSS» را بخوانید.

با این حال، کمی مشکل وجود دارد. وقتی آنها را می خوانی clamp توابع داخل CSS شما، هنوز هم دیدن اینکه دقیقا چه اتفاقی می افتد دشوار است. فقط یک فایل پر از اندازه فونت را تصور کنید که شبیه این است:

clamp(1.44rem, 3.44vw + 0.75rem, 2.81rem)

اما با کمک کمی از sass عملکرد، ما می توانیم این اندازه فونت ها را بسیار خواناتر کنیم.

ما می خواهیم با این تابع ساده Sass به چه چیزی برسیم؟

به طور خلاصه، ما می خواهیم چیزی شبیه به این انجام دهیم: ما یک حداقل اندازه فونت، از لحظه ای که ما نقطه شکست بزرگتر از 400px، ما آن را می خواهیم آن را به بزرگ‌ترین اندازه فونت خود تغییر دهید تا به حداکثر نقطه شکست رسیده است.

حداقل و حداکثر اندازه فونت به راحتی پوشش داده می شود. اگر حداقل اندازه فونت را می خواهیم 16px (یا 1rem) و حداکثر اندازه فونت 32px (یا 2rem، ما قبلاً دو بخش از عملکرد گیره خود را داریم:

clamp(1rem, [?], 2rem)
بیشتر بعد از پرش! ادامه مطلب زیر ↓

ایجاد یک تابع پایه سیال خودکار

اینجاست که همه چیز پیچیده می‌شود، و من به شما پیشنهاد می‌کنم مقاله آدریان بیس را دنبال کنید، که توضیح عمیقی در مورد ریاضیات پشت این موضوع ارائه می‌دهد.

به طور خلاصه، معادله به صورت زیر است:

(حداکثر اندازه قلم – حداقل اندازه قلم) / (حداکثر نقطه شکست – حداقل نقطه شکست)

بیایید برای انجام برخی ریاضیات آماده شویم تا این اتفاق در Sass رخ دهد، بنابراین بیایید خود را ایجاد کنیم fluid-typography.scss فایل تابع و با اضافه کردن شروع کنید sass:math و تابع با مقادیری که نیاز داریم:

@use "sass:math";

@function fluid($min-size, $max-size, $min-breakpoint, $max-breakpoint, $unit: vw) {
 
}

حالا، بیایید محاسبه شیب داخل تابع خود را با مقداری اضافه کنیم sass:math:

@function fluid($min-size, $max-size, $min-breakpoint, $max-breakpoint, $unit: vw) {
 $slope: math.div($max-size - $min-size, $max-breakpoint - $min-breakpoint);
}

برای بدست آوردن مقداری که بتوانیم با آن کار کنیم، باید شیب خود را در ضرب کنیم 100:

$slope-to-unit: $slope * 100;

تنها چیزی که باقی می ماند این است که ما رهگیری خود را برای ساختن معادله پیدا کنیم. با تابع زیر می توانیم این کار را انجام دهیم:

$intercept: $min-size - $slope * $min-breakpoint;

و در نهایت تابع ما را برگردانیم:

@return clamp(#{$min-size}, #{$slope-to-unit}#{$unit} + #{$intercept}, #{$max-size});

اگر ایجاد شده را صدا کنیم sass عملکرد در scss ما، اکنون باید تایپوگرافی سیال را دریافت کنیم:

h1 {
   font-size: #{fluid(1rem, 2rem, 25rem, 62.5rem)}
}

نکته ای در مورد واحدها

در بیشتر موارد، وقتی صحبت از تایپوگرافی سیال می‌شود، از عرض دید استفاده می‌کنیم، بنابراین این یک پیش‌فرض خوب است. با این حال، مواردی وجود دارد، به خصوص هنگام استفاده از clamp() عملکرد برای فاصله عمودی، جایی که می خواهید به جای عرض از ارتفاع درگاه دید استفاده کنید. در صورت تمایل، می‌توانیم واحد خروجی را تغییر دهیم و از حداقل و حداکثر نقطه شکست برای ارتفاع استفاده کنیم:

h1 {
   font-size: #{fluid(1rem, 2rem, 25rem, 62.5rem, vh)}
}

به روز رسانی تابع برای طبیعی تر کردن محاسبات

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

اول، ما به یک تابع اضافی برای محاسبه خود نیاز داریم rem مقادیر بر اساس ورودی پیکسل

توجه داشته باشید: اگر پایه خود را تغییر دهید، این کار نمی کند rem ارزش.

@function px-to-rem($px) {
    $rems: math.div($px, 16px) * 1rem;
    @return $rems;
}

اکنون می توانیم عملکرد سیال خود را به خروجی به روز کنیم rem مقادیر حتی اگر پیکسل ها را به عنوان ورودی دریافت کند. این نسخه به روز شده است:

@function fluid($min-size, $max-size, $min-breakpoint, $max-breakpoint, $unit: vw) {
    $slope: math.div($max-size - $min-size, $max-breakpoint - $min-breakpoint);
    $slope-to-unit: $slope * 100;
    $intercept-rem: px-to-rem($min-size - $slope * $min-breakpoint);
    $min-size-rem: px-to-rem($min-size);
    $max-size-rem: px-to-rem($max-size);
    @return clamp(#{$min-size-rem}, #{$slope-to-unit}#{$unit} + #{$intercept-rem}, #{$max-size-rem});
}

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

font-size: #{fluid(16px, 32px, 320px, 960px)}

این منجر به موارد زیر خواهد شد:

font-size: clamp(1rem, 2.5vw + 0.5rem, 2rem);

در نگاه اول، این کامل به نظر می رسد، اما بیشتر به این دلیل است که من از مقادیر بسیار ساده استفاده کرده ام. به عنوان مثال، هنگام بستن به حداکثر مقدار از 31px بجای 32px، ما rem مقادیر چندان گرد نخواهند بود و خروجی ما کمی نامرتب خواهد شد.

ورودی:

font-size: #{fluid(16px, 31px, 320px, 960px)}

خروجی:

font-size: clamp(1rem, 2.34375vw + 0.53125rem, 1.9375rem);

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

گرد کردن ارزش های ما و اضافه کردن برخی از پیش فرض ها

بیایید با اضافه کردن یک تابع گرد کردن به فایل Sass خود شروع کنیم. این هر ورودی را می گیرد و آن را به مقدار مشخصی از اعشار گرد می کند:

@function round($number, $decimals: 0) {
    $n: 1;
    @if $decimals > 0 {
        @for $i from 1 through $decimals {
            $n: $n * 10;
        }
    }
    @return math.div(math.round($number * $n), $n);
}

اکنون می توانیم مقادیر خروجی خود را با اعداد گرد شده به روز کنیم. تابع را متناسب با آن به روز کنید. من پیشنهاد می کنم حداقل دو اعشار را برای مقادیر خروجی برای ثابت ترین نتایج تنظیم کنید:

@function fluid($min-size, $max-size, $min-breakpoint, $max-breakpoint, $unit: vw) {
    $slope: math.div($max-size - $min-size, $max-breakpoint - $min-breakpoint);
    $slope-to-unit: round($slope * 100, 2);
    $intercept-rem: round(px-to-rem($min-size - $slope * $min-breakpoint), 2);
    $min-size-rem: round(px-to-rem($min-size), 2);
    $max-size-rem: round(px-to-rem($max-size), 2);
    @return clamp(#{$min-size-rem}, #{$slope-to-unit}#{$unit} + #{$intercept-rem}, #{$max-size-rem});
}

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

ورودی:

font-size: #{fluid(16px, 31px, 320px, 960px)};

خروجی:

font-size: clamp(1rem, 2.34vw + 0.53rem, 1.94rem);

افزودن نقطه انفصال پیش فرض

اگر تمایلی به تکرار خود ندارید، همیشه می‌توانید یک نقطه شکست پیش‌فرض برای عملکرد خود تنظیم کنید. سعی کنید تابع را به صورت زیر به روز کنید:

$default-min-bp: 320px;
$default-max-bp: 960px;

@function fluid($min-size, $max-size, $min-breakpoint: $default-min-bp, $max-breakpoint: $default-max-bp, $unit: vw) {
    // ...
}

در حال حاضر، ما نیازی به تکرار این viewport ها همیشه نداریم. ما هنوز هم می توانیم یک نقطه شکست سفارشی اضافه کنیم اما یک ورودی ساده مانند:

font-size: #{fluid(16px, 31px)};

همچنان منجر به:

font-size: clamp(1rem, 2.34vw + 0.53rem, 1.94rem);

در اینجا تابع کامل است:

@use 'sass:math';

$default-min-bp: 320px;
$default-max-bp: 960px;

@function round($number, $decimals: 0) {
    $n: 1;
    @if $decimals > 0 {
        @for $i from 1 through $decimals {
            $n: $n * 10;
        }
    }
    @return math.div(math.round($number * $n), $n);
}

@function px-to-rem($px) {
    $rems: math.div($px, 16px) * 1rem;
    @return $rems;
}

@function fluid($min-size, $max-size, $min-breakpoint: $default-min-bp, $max-breakpoint: $default-max-bp, $unit: vw) {
    $slope: math.div($max-size - $min-size, $max-breakpoint - $min-breakpoint);
    $slope-to-unit: round($slope * 100, 2);
    $intercept-rem: round(px-to-rem($min-size - $slope * $min-breakpoint), 2);
    $min-size-rem: round(px-to-rem($min-size), 2);
    $max-size-rem: round(px-to-rem($max-size), 2);
    @return clamp(#{$min-size-rem}, #{$slope-to-unit}#{$unit} + #{$intercept-rem}, #{$max-size-rem});
}

نکته پایانی: یک گیره شاد برای همه کاربران خارج از کشور باشید

اگر این آموزش کوچک را دنبال کردید و از آن شگفت زده شدید، ممکن است بخواهید این را اضافه کنید clamp() روش برای همه چیز است، اما یک نکته جانبی مهم در مورد دسترسی وجود دارد.

توجه داشته باشید: وقتی استفاده می کنید vw واحدها یا محدود کردن حجم متن clamp()، این احتمال وجود دارد که کاربر نتواند متن را تا 200٪ اندازه اصلی آن مقیاس کند.

اگر این اتفاق بیفتد، خرابی WCAG است. همانطور که آدریان بیس اشاره کرد، 100٪ بی خطا نیست. آدریان روزلی چند نمونه در این مورد نوشته است، که ممکن است برای شما جالب باشد.

به دلیل پشتیبانی عالی از مرورگر، امروزه می توانیم از این روش استفاده کنیم. با هوشمندی در استفاده، مطمئن هستم که می تواند افزودنی زیبا به پروژه آینده شما یا ارتقای پروژه قبلی باشد.

سرمقاله Smashing
(vf، yk، il)