جاوااسکریپت | JavaScript
506 subscribers
654 photos
139 videos
3 files
512 links
کانال @IR_javascript حاوی اطلاعات مفید در حوزه برنامه نویس فرانت که بصورت روزانه بروز می‌شود.
در این کانال شما به:
[1] مطالب تازه
[2] تحلیل‌های عمیق
[3] نکات آموزشی
[4] چالش
[5] ابزار و راهنمایی‌های کاربردی
دسترسی خواهید داشت.

🆔@IR_javascript
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
:hover > \:not(\:hover)
معمولاً از ویژگی hover برای برجسته‌سازی یک عنصر خاص استفاده می‌شود؛ اما گاهی‌اوقات زیباتر است اگر به‌جای آن، کاری با سایر عناصر انجام دهیم.

CSS

ul {
@media (hover) and (prefers-reduced-motion: no-preference) {
& > li {
transform-origin: left center;
transition: transform یک ثانیه با تابع زمان‌بندی var(--ease-spring-۳)،
opacity صفر ممیز سه ثانیه با تابع زمان‌بندی var(--ease-۳);
}
&:hover > li:not(:hover) {
opacity: ۰.۲۵;
transform: scale(۰.۸);
}
}
}


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


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍4
افزونه‌هایی مفید برای vscode:

Angular Language Service – پیشنهاد خودکار کد و امکان پیمایش آسان بین کامپوننت‌ها

ESLint + Prettier – کدی پاک و یکپارچه، بدون نیاز به تلاش اضافی

Import/Export Sorter برای JavaScript/TypeScript – مرتب‌سازی خودکار import و export هنگام ذخیره‌سازی

Path IntelliSense – تکمیل خودکار مسیر فایل‌ها با سرعت و دقت

Gremlins – هشدار در صورت وارد کردن اشتباه حروف، مانند تایپ «С» روسی به‌جای «C» انگلیسی

GitLen‎s – مشاهده‌ی تاریخچه تغییرات در کد: چه کسی، چه زمانی، چه چیزی را تغییر داده است


Run Terminal Command — امکان اجرای مستقیم دستورات (مثل npm، ng، یا git) از طریق منوی زمینه‌ی فایل‌ها یا از پنل فرمان را فراهم می‌کند.

CSS Peek — اجازه می‌دهد از کلاس‌ها یا شناسه‌های (id) موجود در HTML، مستقیماً به محل تعریف آن‌ها در فایل‌های CSS یا SCSS بروید.

Import ‎Cost — اندازه‌ی هر ماژول واردشده را نمایش می‌دهد و کمک می‌کند وابستگی‌های «سنگین» پروژه را تحت کنترل داشته باشید.


#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
رویداددهی تفویضی (Event Delegation) چیست؟
رویداددهی تفویضی یا Event Delegation تکنیکی در برنامه‌نویسی است که به‌جای آن‌که برای هر عنصر تعاملی (دکمه، لینک، آیتم فهرست و غیره) یک شنونده‌ی رویداد (event listener) جداگانه تعریف کنیم، یک شنونده‌ی واحد را روی عنصر والد آن‌ها (یا حتی روی کل سند document) قرار می‌دهیم.
زمانی که کاربر روی یک عنصر فرزند کلیک می‌کند، رویداد به سمت بالا در سلسله‌مراتب عناصر حرکت می‌کند (این پدیده به نام *Event Bubbling* شناخته می‌شود)، و ما می‌توانیم آن را در نقطه‌ای بالاتر دریافت و مدیریت کنیم.

### چرا این روش مفید است؟

کاهش تعداد شنونده‌ها = کاهش مصرف منابع
هر شنونده‌ی رویداد مقداری از حافظه را اشغال می‌کند و هنگام وقوع رویدادها درگیر فرآیند بررسی می‌شود. در مقابل، یک شنونده‌ی مرکزی می‌تواند همان عملکرد را با کارایی بالاتر انجام دهد. این موضوع برای مرورگر بسیار ساده‌تر و بهینه‌تر است.

پشتیبانی خودکار از عناصر اضافه‌شده به‌صورت دینامیک
وقتی با کد دکمه‌ها یا آیتم‌های جدیدی (مثلاً با جاوااسکریپت) ایجاد می‌کنید، نیازی به تعریف شنونده برای هرکدام نیست—چراکه شنونده‌ی والد از قبل آماده‌ی دریافت رویداد آن‌هاست.

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

---

### چند نکته‌ی کاربردی:

* از e.target.matches() استفاده کنید
برای آن‌که تشخیص دهید رویداد دقیقاً روی کدام عنصر اتفاق افتاده است.

* از closest() بهره بگیرید
برای پیدا کردن نزدیک‌ترین عنصر والد مانند یک <li> که حاوی دکمه یا عنصر موردنظر باشد.

* محدوده‌ی تفویض را هوشمندانه انتخاب کنید
نیازی نیست شنونده را روی کل سند (document) قرار دهید؛ اگر می‌توان آن را به نزدیک‌ترین والد مشترک محدود کرد، از این کار بهره‌مند شوید تا از پردازش‌های غیرضروری جلوگیری شود.

---

### جمع‌بندی

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


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
بررسی Type Guardهای امن در TypeScript برای مقادیر unknown یا any

در اینجا به یکی از ویژگی‌های موردعلاقه‌ام در TypeScript می‌پردازم:
استفاده از عبارت value is Type که به کامپایلر کمک می‌کند تا نوع واقعی یک مقدار را شناسایی کرده و بدون نیاز به تبدیل‌های پرخطر از نوع any یا بروز خطاهای زمان اجرا، با آن کار کند.

### چرا نباید از as به‌صورت سرسری استفاده کنیم؟

اغلب هنگام مواجهه با مقادیر از نوع unknown یا `any`، خیلی ساده می‌نویسیم:

const data = value as MyType;


یا حتی:

const data = value as any;


در این حالت، در واقع چشم خود را بر هشدارهای کامپایلر می‌بندیم. اما این کار باعث می‌شود از مزایای سیستم نوع‌گذاری TypeScript محروم شویم و ممکن است در زمان اجرا با مقدار `undefined` به‌جای فیلدی که انتظار داریم، مواجه شویم.

### راه‌حل: استفاده از تابع تشخیص (Type Predicate)

به‌جای تبدیل‌های کورکورانه، می‌توانیم با صرف کمی وقت بیشتر، تابعی بنویسیم که:

۱. بررسی کند مقدار null یا undefined نباشد
۲. وجود ویژگی‌های موردنیاز را بررسی کند
۳. نوع این ویژگی‌ها را با دقت بررسی نماید (مثلاً string، number، و غیره)

### نمونه‌ای از یک بررسی امن:

function isMyType(value: unknown): value is MyType {
return (
typeof value === 'object' &&
value !== null &&
/* بررسی وجود ویژگی‌ها */
/* بررسی نوع اولیه‌ی آن‌ها */
);
}


در اینجا:

* value: unknown یعنی ما به ورودی اعتماد نداریم.
* value is MyType به کامپایلر قول می‌دهد: «اگر خروجی true بود، قطعاً نوع مقدار MyType است».
* درون تابع، می‌توانیم از انواع بررسی‌ها استفاده کنیم: بررسی کلیدها، استفاده از instanceof`، `Array.isArray() و هر روش منطقی دیگری.

### یک مثال واقعی از کاربرد:

function handle(resp: unknown) {
if (isMyType(resp)) {
// در اینجا مطمئن هستیم که resp از نوع MyType است
// بنابراین می‌توانیم با خیال راحت از ویژگی‌های آن استفاده کنیم
}
}


### نتیجه‌گیری

این روش، راهکاری مؤثر برای حفظ ایمنی نوع‌ها هنگام کار با مقادیر unknown یا any است. نه‌تنها به کدی مطمئن‌تر منجر می‌شود، بلکه تجربه‌ی توسعه را نیز با خطاهای کمتر و پیش‌بینی‌پذیری بیشتر بهبود می‌بخشد.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
دسترس‌پذیری وب‌سایت و نقش ویژگی‌های ARIA

به‌تازگی شروع کرده‌ام درباره‌ی اهمیت دسترس‌پذیری وب‌سایت‌ها صحبت کنم. امروز این موضوع را ادامه می‌دهم و درباره‌ی ویژگی‌های ARIA توضیح می‌دهم؛ عناصری کلیدی که باعث می‌شوند رابط‌های کاربری وب برای همه‌ی کاربران قابل فهم باشند.

ARIA (مخفف *برنامه‌های اینترنتی غنی قابل دسترس*) مجموعه‌ای از ویژگی‌هاست که به عناصر HTML افزوده می‌شود تا فناوری‌های کمکی مانند صفحه‌خوان‌ها، نمایشگرهای بریل و ابزارهای مشابه، اطلاعات بیشتری درباره‌ی نقش و وضعیت عناصر رابط کاربری دریافت کنند.

مثالی بدون استفاده از ARIA:
فرض کنید یک دکمه‌ی چندرسانه‌ای داریم که به هر دلیلی فقط با یک عنصر <div> ساخته شده است. در این حالت، یک صفحه‌خوان قادر نخواهد بود تشخیص دهد که این عنصر در واقع یک دکمه است.

نمونه‌ی بهبودیافته با استفاده از ARIA:
در این مثال ما صراحتاً مشخص می‌کنیم که این عنصر یک دکمه است:

<div role="button" tabindex="0">Play</div>


چطور می‌توان این موارد را پیاده‌سازی کرد؟
می‌توان از گام‌های کوچک آغاز کرد: بررسی دکمه‌ها، فرم‌ها و بخش‌های تعاملی. بررسی کنیم که آیا صفحه‌خوان‌ها می‌توانند مفهوم آن‌ها را درک کنند یا خیر، و در صورت نیاز، ویژگی‌های ARIA را به آن‌ها اضافه کنیم.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
رنگ currentColor
یکی از قابلیت‌های CSS که گاهی فراموش می‌شود، اما می‌تواند در مدیریت رنگ‌ها بسیار مفید واقع شود، ویژگی currentColor است.

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

این ویژگی، یک واژه‌ی کلیدی خاص در CSS است که برای ارجاع به رنگ فعلی عنصر به کار می‌رود.

به عنوان مثال، اگر رنگ متن یک عنصر با استفاده از ویژگی color تعیین شده باشد، currentColor به همان رنگ اشاره خواهد کرد، فارغ از این‌که در کجا یا چگونه مورد استفاده قرار می‌گیرد.

چه زمانی باید از currentColor استفاده کرد؟
زمانی که می‌خواهید رنگ متن، حاشیه و سایر ویژگی‌ها یکسان باشند و به‌راحتی قابل تغییر باشند.

در فایل‌های SVG نیز می‌توان رنگ پرشدگی یا خط دور عناصر را با currentColor تعیین کرد. این موضوع زمانی بسیار کاربردی است که نیاز دارید رنگ آیکون با رنگ متن یا سایر عناصر هماهنگ باشد.

مثال:

button {
color: blue; /* تعیین رنگ متن */
background-color: white;
border: ۲px solid currentColor; /* حاشیه به رنگ آبی، همانند رنگ متن خواهد بود */
}

svg {
fill: currentColor; /* آیکون به رنگ آبی، همانند رنگ متن نمایش داده می‌شود */
}


در مجموع، استفاده از currentColor روشی عالی برای بهبود مدیریت سبک‌ها و کاهش تکرار در کدنویسی است.




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍31
all: unset – بازنشانی تمام استایل‌ها تنها با یک خط

احتمالاً بارها پیش آمده که به‌صورت دستی استایل‌های پیش‌فرض یک عنصر را پاک کرده‌اید؛ مثلاً به این شکل:

button {
background: none;
border: none;
padding: 0;
font: inherit;
color: inherit;
}


حالا تصور کنید تمام این تنظیمات را بتوان فقط با یک خط جایگزین کرد:

button {
all: unset;
}


و دقیقاً همان نتیجه را گرفت!

### ویژگی all: unset چیست؟

این ویژگی تمام استایل‌های اعمال‌شده را ــ حتی استایل‌های پیش‌فرض مرورگر ــ بازنشانی می‌کند،
در عین حال، ویژگی‌هایی که قابل ارث‌بری هستند (مانند color یا font-family) را از عنصر والد حفظ می‌کند.

در واقع، این ویژگی مانند فشردن دکمه «پاک کردن همه چیز» است؛
و بعد از آن، می‌توانید ظاهر دلخواه خود را از پایه و با کنترل کامل طراحی کنید.

### نمونه‌ی نهایی:

button {
all: unset;
background-color: blue;
color: white;
font-size: ۱۶px;
padding: ۱۰px ۲۰px;
border-radius: ۵px;
}


اکنون شما هستید که ظاهر دکمه را مشخص می‌کنید — بدون مزاحمت از سمت استایل‌های مرورگر.

### چه زمانی از all: unset استفاده کنیم؟

* زمانی که می‌خواهید تمام استایل‌های پیش‌فرض را حذف کنید؛
* هنگام طراحی مؤلفه‌های سفارشی (custom components) با ظاهر کاملاً خالص؛
* وقتی که می‌خواهید همه چیز دقیقاً از «صفر» شروع شود.

all: unset ابزاری قدرتمند برای بازنشانی استایل است —
اما باید با احتیاط از آن استفاده کنید،
چرا که ممکن است ناخواسته ویژگی‌هایی را نیز حذف کنید که قصد حفظ آن‌ها را داشتید.
در چنین مواردی، گاهی بهتر است به‌صورت انتخابی استایل‌ها را پاک کنید تا بعداً مجبور به بازگرداندن دستی آن‌ها نشوید.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍4
متوقف کردن یک Watcher

Watcher**هایی که به‌صورت هم‌زمان (synchronous) درون تابع `setup()` یا در قالب `<script setup>` تعریف می‌شوند، به نمونه (instance) کامپوننت مالک وابسته هستند و به‌طور خودکار هنگام **unmount شدن آن کامپوننت متوقف خواهند شد. در اغلب موارد، نیازی نیست نگران متوقف کردن دستی آن‌ها باشید.

نکته‌ی کلیدی در این‌جاست که Watcher باید به‌صورت هم‌زمان ایجاد شود؛ اگر Watcher در یک تابع غیرهم‌زمان (asynchronous) مانند setTimeout ایجاد گردد، دیگر به کامپوننت والد وابسته نخواهد بود و باید به‌صورت دستی متوقف شود تا از نشت حافظه (memory leak) جلوگیری شود. به مثال زیر توجه کنید:
<script setup>
import { watchEffect } from 'vue'

// این Watcher به‌صورت خودکار متوقف خواهد شد
watchEffect(() => {})

// ...اما این یکی نه!
setTimeout(() => {
watchEffect(() => {})
}, ۱۰۰)
</script>

برای متوقف کردن دستی یک Watcher**، می‌توان از تابع بازگشتی استفاده کرد. این روش هم برای `watch` و هم برای `watchEffect` کاربرد دارد:


const unwatch = watchEffect(() => {})

// ...در زمانی دیگر، زمانی که دیگر نیازی نیست
unwatch()


توجه داشته باشید که تنها در موارد بسیار محدود نیاز به ایجاد **Watcher
به‌صورت غیرهم‌زمان وجود دارد، و در هر زمان ممکن، بهتر است از ایجاد هم‌زمان استفاده شود.

اگر نیاز دارید منتظر داده‌ای غیرهم‌زمان بمانید، می‌توانید منطق Watcher خود را مشروط طراحی کنید:

// داده‌ای که به‌صورت غیرهم‌زمان بارگذاری می‌شود
const data = ref(null)

watchEffect(() => {
if (data.value) {
// انجام عملیات زمانی که داده بارگذاری شد
}
})


#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
1👍1
ویدیو دوبله شده در مورد انواع روش‌های آپلود فایل و رمزگذاری Base64 [+لینک]

به بررسی روش‌های مختلف آپلود فایل‌ها به سرور از جمله استفاده از داده‌های فرم چندبخشی (Multi-Part Form Data) و رمزگذاری Base64 پرداخته شد. روش‌های مختلف مانند ارسال فایل‌ها به صورت متن ساده (Plain Text)، رمزگذاری URL و فرم داده چندبخشی به تفصیل بررسی شد. همچنین استفاده از رمزگذاری Base64 برای جاسازی تصاویر در ایمیل‌ها و صفحات HTML شرح داده شد. در نهایت، نکات مهم در مورد محدودیت‌ها و بهترین شیوه‌های استفاده از این تکنیک‌ها در دنیای واقعی بیان گردید.


🔗https://www.aparat.com/v/pqz7475
#️⃣#tip #dub
👥@IR_javascript_group
🆔@IR_javascript
در حال پیاده‌سازی بارگذاری فایل همراه با نوار پیشرفت هستیم

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

بیایید به نحوه‌ی پیاده‌سازی آن بپردازیم:

در این پیاده‌سازی، از شیء XMLHttpRequest استفاده می‌کنم؛ این شیء وظیفه‌ی ارسال فایل به‌صورت غیرهم‌زمان به سرور را بر عهده دارد و مجموعه‌ای از رویدادها را برای کنترل دقیق‌تر این فرآیند در اختیار ما می‌گذارد.

در این میان، لازم است بدانیم که کنترل‌کننده‌ی استاندارد xhr.onprogress`، پیشرفت *دریافت پاسخ از سرور* را پیگیری می‌کند؛ اما آنچه ما نیاز داریم، پیشرفت *ارسال فایل به سرور* است. از این رو، از `xhr.upload.onprogress بهره می‌گیریم تا رویدادهایی را که در طول انتقال هر بخش از داده‌ها به سرور رخ می‌دهند، دریافت کرده و وضعیت بارگذاری را با دقت به کاربر نمایش دهیم.

const xhr = new XMLHttpRequest();


این شیء دارای مجموعه‌ای از رویدادهای مفید است که در اسلاید بالا به آن‌ها اشاره کرده‌ام. با ترکیب این رویدادها و محاسبات ساده‌ای که در آن‌ها:

* lengthComputable مشخص می‌کند آیا می‌توان اندازه‌ی کل داده را محاسبه کرد،
* loaded میزان بایت‌های ارسال‌شده را نشان می‌دهد،
* total نیز نشان‌دهنده‌ی حجم کلی داده‌های ارسالی است،

می‌توان نوار پیشرفتی طراحی کرد که به‌صورت درصدی، وضعیت بارگذاری را نمایش دهد.

نمونه کد جاوااسکریپت:

if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
// به‌روزرسانی رابط کاربری
}


به این ترتیب، یک نوار پیشرفت واکنش‌گرا خواهیم داشت که وضعیت لحظه‌ای بارگذاری را به‌روشنی به کاربر نمایش می‌دهد.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🤔1
وب کامپوننت‌ها چیستند؟
وب کامپوننت‌ها مجموعه‌ای از APIهای بومی مرورگر هستند که امکان ساخت عناصر رابط کاربری (UI) به‌صورت مستقل، قابل استفاده‌ی مجدد و به‌طور کامل کپسوله‌شده را فراهم می‌کنند — بدون نیاز به وابستگی به هیچ فریم‌ورکی.

این فناوری بر پایه‌ی سه مفهوم کلیدی بنا شده است:

* عناصر سفارشی (Custom Elements)
* دام سایه (Shadow DOM)
* قالب‌های HTML (HTML Templates)
پیش‌تر در یکی از پست‌هایم درباره‌ی آن نوشته بودم.

چرا باید از آن استفاده کنیم؟

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

وب کامپوننت‌ها در طراحی سیستم‌های طراحی (Design Systems)، رابط‌های کاربری سازمانی، معماری میکرو-فرانت‌اند و کتابخانه‌های سفارشی UI کاربرد گسترده‌ای دارند.

برای شروع، کافی‌ست تگی ساده مانند <my-alert> بسازید — به‌سرعت متوجه خواهید شد که چقدر کد شما تمیزتر، پایدارتر و ساخت‌یافته‌تر خواهد شد، زمانی که کنترل رابط کاربری را یک کامپوننت واقعی بر عهده دارد.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
1
واحدهای CSS که اغلب فراموش می‌شوند — lh و rlh

هر دوی این واحدها به *ارتفاع خط* (line-height) مرتبط‌اند — یعنی ارتفاع یک سطر از متن. این واحدها به شما امکان می‌دهند که اندازه‌گیری‌ها را بر اساس ارتفاع خط تعیین کنید، نه بر پایهٔ پیکسل‌های ثابت یا درصدها.

### lh — ارتفاع خط محلی

واحد یک lh معادل ارتفاع خط عنصر جاری است.

p {
line-height: ۲۴px;
margin-top: ۲lh; /* معادل ۴۸px */
}


اگر عنصری دارای مقدار مشخصی برای line-height باشد، آنگاه lh معادل همان مقدار خواهد بود.
اگر line-height به‌طور مستقیم مشخص نشده باشد، مقدار به‌ارث‌رسیده استفاده می‌شود.
این واحد یک *واحد محلی* است؛ یعنی مقدار آن به عنصر فعلی بستگی دارد.

### rlh — ارتفاع خط ریشه

واحد یک rlh معادل ارتفاع خط عنصر ریشه (معمولاً html) است.

html {
font-size: ۱۶px;
line-height: ۱.۵; /* معادل ۲۴px */
}

.section {
padding-top: ۲rlh; /* معادل ۴۸px */
}


این واحد یک *واحد جهانی* است، درست مانند rem که از font-size عنصر html پیروی می‌کند، اما در اینجا مبنا ارتفاع خط است، نه اندازهٔ فونت.
کاربرد آن بیشتر در ایجاد فاصله‌گذاری عمودی هماهنگ و یکپارچه در سراسر صفحه است.

### جمع‌بندی

با استفاده از lh و `rlh`، شما ابعاد و فاصله‌ها را به ارتفاع واقعی خطوط متن گره می‌زنید، نه به پیکسل‌های سخت یا درصدهای وابسته به اندازهٔ فونت.
نتیجهٔ این کار، سیستمی انعطاف‌پذیر، مقیاس‌پذیر و منسجم برای فاصله‌گذاری عمودی خواهد بود.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍2