data-*: وقتی HTML باید یه اطلاعات اضافه رو با خودش حمل کنه

تا اینجای دوره، با ده‌ها ویژگی استاندارد HTML آشنا شدیم: src، href، alt، type و ده‌ها مورد دیگه. اما گاهی نیاز داری یه اطلاعات کاملاً سفارشی و مخصوص پروژه‌ی خودت رو به یه عنصر HTML وصل کنی؛ اطلاعاتی که هیچ ویژگی استانداردی براش وجود نداره. HTML5 برای دقیقاً همین منظور، ویژگی‌های data-* رو معرفی کرده.

data-* چیه؟

<div data-user-id="4521">علی محمدی</div>

ویژگی‌های data-* یه الگوی استاندارد برای تعریف ویژگی‌های سفارشی هستن؛ هر ویژگی‌ای که با پیشوند data- شروع بشه، از نظر HTML5 کاملاً معتبره و می‌تونی هر اسم دلخواهی بعدش بذاری (مثل data-user-id، data-price، data-category). این ویژگی‌ها هیچ تأثیر بصری یا رفتاری خودکاری روی صفحه ندارن؛ صرفاً یه محل ذخیره‌ی اطلاعاته که بعداً با CSS یا جاوااسکریپت ازش استفاده می‌کنی.

چرا اصلاً به این ویژگی‌ها نیاز داریم؟

فرض کن یه لیست از محصولات داری و می‌خوای برای هرکدوم، یه شناسه‌ی داخلی (که کاربر نباید ببینتش، اما جاوااسکریپت بعداً بهش نیاز داره) ذخیره کنی. قبل از HTML5، برنامه‌نویس‌ها مجبور بودن از راه‌حل‌های غیراستاندارد و کثیف (مثل سوءاستفاده از ویژگی class یا id برای ذخیره‌ی داده) استفاده کنن. data-* این مشکل رو با یه روش تمیز و استاندارد حل می‌کنه.

یه مثال کاربردی: کارت محصول

<div class="product-card" data-product-id="1024" data-price="500000" data-category="shoes">
  <h3>کفش ورزشی رانینگ</h3>
  <p>قیمت: ۵۰۰,۰۰۰ تومان</p>
</div>

تو این مثال، سه تا ویژگی سفارشی داریم: data-product-id (شناسه‌ی داخلی محصول)، data-price (قیمت به‌صورت عدد خام، بدون فرمت‌بندی، برای محاسبات احتمالی)، و data-category (دسته‌بندی محصول). هیچ‌کدوم از این‌ها برای کاربر قابل‌مشاهده نیستن؛ فقط اطلاعاتی هستن که جاوااسکریپت می‌تونه بعداً ازشون استفاده کنه، مثلاً برای فیلترکردن محصولات بر اساس دسته‌بندی.

دسترسی به data-* با جاوااسکریپت

<div id="myProduct" data-product-id="1024" data-price="500000">کفش ورزشی</div>

<script>
  const product = document.getElementById("myProduct");
  console.log(product.dataset.productId); // "1024"
  console.log(product.dataset.price); // "500000"
</script>

جاوااسکریپت یه شیء ویژه به اسم dataset داره که به‌طور خودکار همه‌ی ویژگی‌های data-* رو در اختیار می‌ذاره. نکته‌ی جالب اینه که data-product-id تو HTML، با خط تیره نوشته می‌شه، اما تو جاوااسکریپت به‌صورت camelCase (یعنی productId، بدون خط تیره و با حرف بزرگ وسط کلمه) در دسترسه. جزئیات بیشتر جاوااسکریپت خارج از محدوده‌ی این دوره است و در دوره‌های جاوااسکریپت پوشش داده می‌شود.

استفاده از data-* با CSS

<p data-status="urgent">این پیام فوری است.</p>
<p data-status="normal">این یک پیام عادی است.</p>

<style>
  p[data-status="urgent"] {
    color: red;
    font-weight: bold;
  }
</style>

یه کاربرد جالب دیگه اینه که می‌شه مستقیم تو CSS هم از این ویژگی‌ها به‌عنوان یه انتخابگر (Selector) استفاده کرد؛ تو این مثال، فقط پاراگرافی که data-status="urgent" داره، قرمز و پررنگ نمایش داده می‌شه، بدون اینکه لازم باشه یه کلاس جداگانه براش تعریف کنیم.

چند مثال بیشتر از کاربردهای رایج

<button data-action="delete" data-item-id="42">حذف</button>

<li data-completed="false">خرید نان</li>

<div class="tab" data-tab-target="settings-panel">تنظیمات</div>

این ویژگی‌ها معمولاً تو سناریوهایی مثل موارد زیر استفاده می‌شن:

  • ذخیره‌ی شناسه‌های داخلی (مثل data-item-id) برای استفاده تو درخواست‌های بعدی به سرور
  • مدیریت وضعیت (مثل data-completed="false" برای یه آیتم لیست کارها)
  • پیاده‌سازی تب‌ها یا آکاردئون‌های سفارشی با جاوااسکریپت (مثل data-tab-target که مشخص می‌کنه با کلیک روی این تب، کدوم بخش دیگه باید نمایش داده بشه)

قوانین نام‌گذاری data-*

چند قانون ساده برای نام‌گذاری این ویژگی‌ها وجود داره:

  • همیشه باید با data- شروع بشن (حروف کوچک).
  • بعد از data-، نباید از حروف بزرگ استفاده کرد؛ به‌جاش از خط تیره برای جدا کردن کلمات استفاده می‌شه (مثل data-user-id، نه data-userID).
  • مقدار همیشه باید یه رشته‌ی متنی باشه (حتی اگه عدد به نظر برسه، مثل "500000")؛ برای تبدیل به عدد واقعی، باید تو جاوااسکریپت این تبدیل انجام بشه.

یه مثال کامل: لیست وظایف با data-*

<ul class="todo-list">
  <li data-task-id="1" data-completed="false">خرید نان</li>
  <li data-task-id="2" data-completed="true">تماس با دکتر</li>
  <li data-task-id="3" data-completed="false">ارسال ایمیل کاری</li>
</ul>

تو این مثال، هر آیتم لیست، یه شناسه‌ی منحصربه‌فرد (data-task-id) و وضعیت انجام‌شدن (data-completed) داره. یه برنامه‌نویس می‌تونه بعداً با جاوااسکریپت، بر اساس این مقادیر، مثلاً همه‌ی وظایف انجام‌نشده رو فیلتر کنه یا استایل خط‌خورده به وظایف تمام‌شده بده.

تفاوت data-* با ویژگی‌های استاندارد HTML

یه نکته‌ی مهم اینه که data-* هیچ رفتار خاصی از طرف مرورگر نداره؛ برخلاف چیزی مثل required (که خودش باعث اعتبارسنجی می‌شه) یا href (که خودش باعث لینک‌شدن می‌شه)، ویژگی‌های data-* کاملاً خنثی هستن و فقط یه محل نگهداری اطلاعاتن. تمام «معنا» و «رفتار» این ویژگی‌ها، کاملاً به کدی که خودت (با CSS یا جاوااسکریپت) می‌نویسی بستگی داره.

چند اشتباه رایج

  • استفاده از حروف بزرگ بعد از data- (مثل data-userID)، که با قوانین استاندارد نام‌گذاری تداخل داره.
  • سوءاستفاده از ویژگی‌های class یا id برای ذخیره‌ی داده‌های سفارشی، به‌جای استفاده‌ی درست از data-*.
  • ذخیره‌ی اطلاعات حساس (مثل اطلاعات کاربری خصوصی) داخل data-*، در حالی که این ویژگی‌ها کاملاً قابل‌مشاهده تو کد HTML صفحه‌ن (با View Page Source) و امن نیستن.

بهترین روش‌ها

  • برای هر اطلاعات سفارشی که نیاز داری به یه عنصر HTML وصل کنی و هیچ ویژگی استانداردی براش وجود نداره، از data-* استفاده کن.
  • اسم‌های data-* رو معنادار و خوانا انتخاب کن (مثل data-user-id، نه data-x).
  • هیچ‌وقت اطلاعات حساس یا محرمانه رو داخل data-* نذار.

نکته‌ی سئو

ویژگی‌های data-* تأثیر مستقیمی روی سئو ندارند، چون این‌ها برای مصرف داخلی جاوااسکریپت یا CSS طراحی شده‌اند، نه برای انتقال معنای محتوایی به موتورهای جستجو.

نکته‌ی دسترسی‌پذیری

ویژگی‌های data-* به‌طور مستقیم توسط صفحه‌خوان‌ها خوانده نمی‌شوند؛ برای انتقال اطلاعات معنایی به فناوری‌های کمکی، باید از ویژگی‌های استاندارد دسترسی‌پذیری مثل aria-* (که در درس‌های بعدی این فصل و فصل ۱۱ بیشتر می‌بینیم) استفاده کرد، نه data-*.

جمع‌بندی

ویژگی‌های data-* یک روش استاندارد برای ذخیره‌ی اطلاعات سفارشی و مخصوص پروژه روی هر عنصر HTML فراهم می‌کنند، بدون اینکه هیچ رفتار یا ظاهر خودکاری ایجاد کنند. این اطلاعات از طریق شیء dataset در جاوااسکریپت یا انتخابگرهای ویژگی در CSS قابل‌دسترسی هستند و نباید برای اطلاعات حساس یا به‌عنوان جایگزین ویژگی‌های دسترسی‌پذیری استفاده شوند.