تاروپود — خودآموز HTML و CSS

فصل ۹ از ۱۰

پیشرفت ترم
۰٪

ترم ۱ · HTML: ساختار و معنا

دسترس‌پذیری از همان HTML

فصل ۹پیش‌نمایش رایگان
۱۵ دقیقه مطالعه فصل ۹

در این فصل چه می‌سازی#

آخر این فصل یک صفحهٔ کوچک ولی واقعی داری — یک صفحهٔ باشگاه کتاب — که برای همه کار می‌کند: هم برای تو که با چشم و ماوس نگاهش می‌کنی، هم برای کسی که صفحه را نمی‌بیند و با یک screen reader گوش می‌دهد، هم برای کسی که اصلاً ماوس ندارد و فقط با keyboard در صفحه می‌چرخد. نکتهٔ غافلگیرکننده این است: در این فصل هیچ tag تازه‌ای یاد نمی‌گیری. هر چیزی که لازم داری از ترم ۱ بلدی؛ فقط این‌بار همه را از یک زاویهٔ تازه می‌بینی — دسترس‌پذیری. و خواهی دید که نصفِ این کار را قبلاً، بی‌آنکه اسمش را بدانی، انجام داده‌ای.

صفحه‌ای که فقط با keyboard پیمایش می‌شود: یک حلقهٔ focus دور یک لینک و مسیری شماره‌دار که ترتیب حرکت با کلید Tab را از منو تا فرم نشان می‌دهد

آخر این فصل می‌توانی:

  • بگویی accessibility یعنی چه و چرا از خودِ HTML شروع می‌شود، نه از چیزی که آخرِ کار اضافه کنی
  • outline صفحه را با ترتیب درست heading بسازی، و یک پرشِ سطح را پیدا کنی و درست کنی
  • landmark های صفحه را بشناسی و بگویی screen reader چطور بینشان می‌پرد
  • کل صفحه را فقط با کلید Tab پیمایش کنی و بگویی چرا ترتیب focus همان ترتیب کدِ توست
  • بین یک alt معنادار و alt="" برای تصویرِ تزئینی درست انتخاب کنی

قبل از شروع#

  • از فصل ۶: landmark ها — <header>، <nav>، <main>، <footer>. ستون فقراتِ این فصل همان‌هاست.
  • از فصل ۲: heading و outline — ترتیب <h1> تا <h6> و اینکه چرا سطحشان مهم است.
  • از فصل ۴: alt — همان‌جا یک بدهی گذاشتیم («تصویرهای تزئینی را در فصل دسترس‌پذیری می‌بینیم»)؛ اینجا می‌پردازیمش.
  • از فصل ۸: <label> — که هر ورودی را به معنایش وصل می‌کند.

مثل همیشه فقط یک مرورگر لازم داری، یا همین آزمایشگاه.

۱. دسترس‌پذیری یعنی چه، و چرا نصفش را قبلاً انجام داده‌ای#

همه صفحه را جوری که تو الان می‌بینی استفاده نمی‌کنند — با چشم و ماوس. بعضی‌ها صفحه را اصلاً نمی‌بینند و با یک screen reader کار می‌کنند: برنامه‌ای که متنِ صفحه را با صدا برایشان می‌خواند. بعضی‌ها نمی‌توانند از ماوس استفاده کنند و فقط با keyboard در صفحه حرکت می‌کنند، با کلید Tab از یک element به element بعدی می‌پرند. accessibility یعنی صفحه را جوری بسازی که برای همهٔ این‌ها کار کند، نه فقط برای حالتِ چشم‌وماوس.

حالا خبرِ خوب. هر بار که در ترم ۱ tag معنادار را انتخاب کردی — <h1> برای تیترِ واقعی، <nav> برای منو، <label> برای هر ورودی، alt برای هر تصویر — داشتی همین کار را می‌کردی، بدون اینکه اسمش را بشنوی. semantic HTML نصفِ کارِ accessibility را برایت انجام داد. این فصل بیشتر دربارهٔ دیدنِ آن کار است، امتحان‌کردنش، و تمام‌کردنِ نیمهٔ دوم.

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

💡 نکته: accessibility یک قابلیت نیست که آخرِ کار به صفحه بچسبانی. یا از خطِ اولِ HTML داخلش هست، یا نیست. برای همین این فصل را اینجا، آخرِ ترمِ HTML، گذاشته‌ایم، نه به‌عنوان یک فکرِ بعدی در انتهای کلِ دوره.

۲. outline: نقشه‌ای که screen reader از رویش می‌پرد#

یادت هست در فصل ۲ گفتیم عنوان‌ها روی‌هم یک outline می‌سازند، مثل فهرستِ مطالبِ یک کتاب؟ حالا می‌بینی این outline دقیقاً به چه دردی می‌خورد.

تو صفحه را با چشمت اسکن می‌کنی و تیترهای بزرگ را پیدا می‌کنی. کاربرِ screen reader نمی‌تواند اسکن کند — ولی چیزِ بهتری دارد: می‌تواند به screen reader بگوید «فقط عنوان‌ها را برایم بخوان»، کلِ outline را بشنود، و مستقیم بپرد به بخشی که می‌خواهد. پس عنوان‌های تو واقعاً یک فهرستِ مطالب هستند که یک نفر با آن‌ها در صفحه پیمایش می‌کند.

برای اینکه این کار کند، ترتیب باید سالم باشد: <h1> بعد <h2> بعد <h3>، بدون پرش. بیا یک نمونهٔ خراب بسازیم. در آزمایشگاه به بخشِ «کتاب این ماه» نگاه کن؛ عنوانش این‌طور نوشته شده:

<h1>باشگاه کتاب</h1>
<h4>کتاب این ماه</h4>

برای چشمِ تو شاید فقط یک عنوانِ کمی کوچک‌تر باشد — مشکلی نیست. ولی کاربرِ screen reader که دارد از روی عنوان‌ها می‌پرد این را می‌شنود: «عنوانِ سطح ۱... عنوانِ سطح ۴». و فکر می‌کند: سطح ۲ و ۳ کجا رفتند؟ دو تا بخش را رد کردم؟ مثل کتابی است که از «فصل ۱» می‌پرد به «بخشِ ۱ـ۱ـ۱ـ۱». نقشه سوراخ دارد.

این یک بخشِ اصلی است که مستقیم زیرِ تیترِ صفحه می‌آید، پس سطحش <h2> است، نه <h4>:

<h1>باشگاه کتاب</h1>
<h2>کتاب این ماه</h2>

چک کن: در آزمایشگاه هر دو هنوز مثلِ عنوان دیده می‌شوند و برای چشمت تقریباً هیچ فرقی نکرد — ولی outline حالا کامل و بی‌سوراخ است. همان درسِ فصل ۲ برمی‌گردد: سطحِ عنوان را بر اساس جایش در outline انتخاب کن، نه اندازه‌اش. بخشِ «عضو شو» هم همین مشکل را دارد؛ آن را هم به <h2> عوض کن.

۳. landmark: نقشهٔ بزرگِ ناحیه‌ها#

در فصل ۶ به صفحه یک اسکلت دادی: <header>، <nav>، <main>، <footer>. حالا پاداشِ accessibility اش را ببین. screen reader به کاربر یک فهرست از این ناحیه‌ها می‌دهد — «سرصفحه، ناوبری، محتوای اصلی، پاصفحه» — و کاربر مستقیم می‌پرد به همان که می‌خواهد، دقیقاً مثل تو که یک نگاه به صفحه می‌اندازی و بی‌درنگ می‌فهمی «منو بالاست، مطلبِ اصلی وسط». همان‌طور که در فصل ۶ دیدی، به این ناحیه‌های بزرگ landmark می‌گویند.

جادویش این است که این را مجانی می‌گیری، فقط با انتخابِ tag درست. <main> خودش یک landmark است. <nav> خودش یک landmark است. چیزی اضافه نمی‌کنی. اسکلتِ همین صفحهٔ باشگاه کتاب این است:

<header>
  <h1>باشگاه کتاب</h1>
  <nav>
    <ul>
      <li><a href="#books">کتاب‌ها</a></li>
      <li><a href="#join">عضویت</a></li>
    </ul>
  </nav>
</header>

<main>
  <!-- ketab-e in mah + form -->
</main>

<footer>
  <p>باشگاه کتاب — ۱۴۰۵</p>
</footer>

حالا تصور کن همین صفحه را — مثلِ صفحهٔ فصل ۶ — فقط از <div> ساخته بودی. آن‌وقت صفر landmark داشتی؛ کاربرِ screen reader هیچ فهرستی برای پریدن نداشت، فقط یک دیوارِ صافِ متن. پس semantic HTML همان نقشهٔ ناحیه‌هاست، مجانی و بدون یک خطِ اضافه.

⚠️ مواظب باش: landmark را با tag واقعی بگیر، نه با <div> و یک role. در فصل ۶ دیدی که <nav> خودش می‌گوید «این ناوبری است»؛ نوشتنِ role="navigation" روی یک <div> راهِ طولانی و پرخطا برای رسیدن به چیزی است که <nav> در یک کلمه می‌دهد. اول tag درست.

۴. فقط با Tab: چرا ترتیب focus همان ترتیب کدِ توست#

بعضی‌ها هیچ‌وقت ماوس نمی‌زنند — یا به‌خاطرِ یک ناتوانیِ حرکتی، یا فقط چون با keyboard سریع‌ترند. این‌ها با کلید Tab از یک چیزِ تعاملی (لینک، کادرِ ورودی، دکمه) به بعدی می‌پرند. آن element ای که همین حالا keyboard رویش است می‌گوییم focus دارد، و مرورگر دورش یک حلقه (outline) می‌کشد تا ببینی کجایی.

بیا خودت حسش کنی. در آزمایشگاه یک‌بار داخلِ صفحه کلیک کن، بعد چند بار پشتِ‌هم Tab بزن و حلقهٔ focus را تماشا کن. اول می‌پرد روی لینکِ «کتاب‌ها»، بعد «عضویت»، بعد لینکِ «دربارهٔ این کتاب بیشتر بخوان»، بعد کادرِ «نام تو»، بعد کادرِ «ایمیل»، و آخر روی دکمهٔ «عضو شو».

چک کن: حلقه دقیقاً به همان ترتیبی سراغِ element ها می‌رود که در کدت از بالا به پایین نوشته‌ای. قانون همین است: ترتیب focus همان ترتیب DOM است — یعنی ترتیبِ element ها در HTML تو. تو هیچ ترتیبی تعیین نکردی؛ چون element ها را به ترتیبِ درست نوشتی، ترتیبِ درستِ focus را مجانی گرفتی.

حالا بیا خرابش کنیم تا سرِ کارِ ما را بهتر بفهمی. یک attribute هست به‌نام tabindex که می‌گذارد ترتیبِ طبیعیِ focus را دستکاری کنی. به کادرِ ایمیل یک عددِ مثبت بده:

<input type="email" id="email" name="email" tabindex="1">

حالا دوباره از بالای صفحه Tab بزن. focus اول می‌پرد روی کادرِ ایمیل — قبل از منو، قبل از همه‌چیز — بعد برمی‌گردد بالا سراغِ لینک‌های منو. حس می‌کنی صفحه دارد بی‌قاعده این‌ور و آن‌ور می‌پرد. یک tabindex مثبت آن element را به جلوی صف می‌کشد، پس ترتیبِ focus دیگر با چیزی که چشم می‌خواند نمی‌خواند. برای کاربرِ keyboard این گیج‌کننده است: Tab می‌زند و انتظار دارد به چیزِ پایین‌تر برسد، ولی پرت می‌شود آن‌سرِ صفحه.

حالا آن tabindex="1" را پاک کن. ترتیب دوباره از بالا به پایین برمی‌گردد. درسش این است: تقریباً هیچ‌وقت tabindex مثبت ننویس. اگر ترتیبِ focus غلط به‌نظر می‌رسد، راهِ درست این است که HTML ات را جابه‌جا کنی تا ترتیبِ DOM درست شود — نه اینکه با tabindex وصله‌اش کنی. ترتیبِ focus را برابرِ ترتیبِ DOM نگه دار.

🔧 اگر کار نکرد: Tab می‌زنی و هیچ‌چیز داخلِ صفحه تکان نمی‌خورد، یا به‌جایش نوارِ ابزارِ خودِ مرورگر focus می‌گیرد؟ اول یک‌بار داخلِ پیش‌نمایشِ آزمایشگاه کلیک کن تا keyboard «داخلِ» صفحه بیفتد، بعد Tab بزن. و اگر اصلاً حلقه‌ای نمی‌بینی، شاید آن element focus نمی‌گیرد — به‌طور پیش‌فرض فقط لینک‌ها، دکمه‌ها و کادرهای فرم focus می‌گیرند.

۵. alt: وقتی هدف را می‌گوید، و وقتی باید خالی بماند#

در فصل ۴ گفتیم هر تصویرِ معنادار یک alt معنادار می‌خواهد، و یک بدهی گذاشتیم: تصویرهای صرفاً تزئینی یک حالتِ خاص دارند که در فصلِ دسترس‌پذیری می‌بینیم. رسیدیم به همان‌جا. دو سؤال تصمیمِ alt را می‌گیرند:

  1. این تصویر معنا یا هدفی دارد؟ ← alt همان هدف را توصیف می‌کند.
  2. صرفاً تزئینی است (یک خطِ جداکننده، یک نقشِ پس‌زمینه، یک آیکنِ کنارِ متنی که خودش همان را می‌گوید)؟ ← alt="" خالی، عمداً.

اول حالتِ معنادار، با یک خطای عمدی. به جلدِ کتاب در آزمایشگاه نگاه کن؛ alt اش این‌طور نوشته شده:

<img src="https://picsum.photos/id/24/300/400" alt="image" width="300" height="400">

alt="image" مثلِ نداشتنِ alt است. screen reader می‌خواند «image» — چیزی که کاربر از قبل می‌دانست. هیچ اطلاعاتی به او نمی‌دهد. درستش کن تا هدف را بگوید: کاربری که تصویر را نمی‌بیند، چه چیزی را باید از این جلد بفهمد؟

<img src="https://picsum.photos/id/24/300/400" alt="جلد کتاب: یک قایق تنها روی دریای آرام هنگام غروب" width="300" height="400">

چک کن: روی صفحه هیچ‌چیز عوض نشد — alt همان قهرمانِ بی‌سروصدای فصل ۴ است. ولی حالا کاربرِ screen reader به‌جای کلمهٔ «image»، خودِ جلد را می‌شنود.

حالا حالتِ تزئینی. در بخشِ «عضو شو» یک آیکنِ ریزِ تزئینی هست که هیچ‌چیز به معنا اضافه نمی‌کند — عنوانِ «عضو شو» خودش همه‌چیز را گفته. اگر برایش یک alt معمولی بنویسی، screen reader یک توضیحِ بی‌فایده می‌خواند و فقط وسطِ کار مزاحمت می‌شود. اگر alt را کاملاً حذف کنی، بعضی screen reader ها به اسمِ فایل پناه می‌برند و آن را می‌خوانند (یادت هست از فصل ۴؟). جوابِ درست یک alt خالیِ عمدی است:

<img src="https://picsum.photos/id/1025/40/40" alt="" width="40" height="40">

alt="" یعنی «به این تصویر نگاه کردم و تصمیم گرفتم هیچ اطلاعاتی ندارد — screen reader، ردش کن». این تنبلی نیست؛ یک تصمیم است. و با نداشتنِ alt فرق دارد: نبودِ alt یک اتفاق است، alt="" یک انتخاب.

کنار هم: همان عکس یک‌بار بزرگ به‌عنوان تصویرِ معنادار با یک alt توصیفی، و یک‌بار کوچک و تزئینی با alt خالی که screen reader از رویش رد می‌شود

💡 نکته: آزمون از فصل ۴ عوض نشده: «اگر این تصویر ناپدید می‌شد، این جمله کارش را انجام می‌داد؟» برای جلد، بله (می‌فهمیدی یک قایقِ تنها سرِ غروب است). برای آن آیکنِ ریز هیچ کاری برای انجام‌دادن نیست، پس صادقانه‌ترین alt، خالی است.

چالش: یک عکس، دو جا

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

۶. صفحهٔ کامل و دسترس‌پذیر#

حالا همه‌چیز را کنار هم بگذار: صفحهٔ باشگاه کتاب، با یک outline کامل، landmark ها، یک فرم که هر ورودی‌اش یک <label> دارد، یک alt معنادار روی جلد، و یک alt خالی روی آیکنِ تزئینی — همهٔ تصمیم‌های این فصل در یک فایل:

<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
  <head>
    <meta charset="UTF-8">
    <title>باشگاه کتاب</title>
  </head>
  <body>
    <header>
      <h1>باشگاه کتاب</h1>
      <nav>
        <ul>
          <li><a href="#books">کتاب‌ها</a></li>
          <li><a href="#join">عضویت</a></li>
        </ul>
      </nav>
    </header>

    <main>
      <article id="books">
        <h2>کتاب این ماه</h2>
        <img src="https://picsum.photos/id/24/300/400" alt="جلد کتاب: یک قایق تنها روی دریای آرام هنگام غروب" width="300" height="400">
        <p>این ماه «دریای آرام» را با هم می‌خوانیم و یکشنبه دربارهٔ آن حرف می‌زنیم.</p>
        <p><a href="https://example.com/book">دربارهٔ این کتاب بیشتر بخوان</a></p>
      </article>

      <section id="join">
        <h2>عضو شو</h2>
        <img src="https://picsum.photos/id/1025/40/40" alt="" width="40" height="40">
        <form>
          <p>
            <label for="name">نام تو</label>
            <input type="text" id="name" name="name">
          </p>
          <p>
            <label for="email">ایمیل</label>
            <input type="email" id="email" name="email">
          </p>
          <p>
            <button type="submit">عضو شو</button>
          </p>
        </form>
      </section>
    </main>

    <footer>
      <p>باشگاه کتاب — ۱۴۰۵</p>
    </footer>
  </body>
</html>

چک کن: روی صفحه یک باشگاه کتابِ معمولی می‌بینی — تیتر، منو، کتابِ این ماه با جلدش، فرمِ عضویت، و پاصفحه. حالا بخشِ نامرئی: عنوان‌ها را از بالا به پایین بخوان (h1، h2، h2 — یک outline کامل)؛ Tab بزن و ببین focus مرتب صفحه را قدم می‌زند؛ و دقت کن که جلد حرف می‌زند ولی آیکنِ تزئینی ساکت می‌ماند. این یک صفحه است که برای همه کار می‌کند.

و آن نصفی که لازم نبود انجامش بدهی: بشمار امروز واقعاً چقدر «کارِ accessibility» به این صفحه اضافه کردی. landmark ها، <label> ها، alt ها — همه را در ترم ۱ به دلیل‌های دیگری نوشته بودی. semantic HTML نصفِ accessibility را برایت انجام داده بود؛ این فصل بیشتر دربارهٔ دیدنِ همان کار و تمام‌کردنِ لبه‌هایش بود.

🤖 با AI: صفحهٔ کاملت را به دستیار AI ات بده و بپرس «این صفحه چه مشکلاتِ accessibility دارد؟». یک جفت‌چشمِ دومِ عالی است — ولی هر مورد را با چیزی که حالا می‌فهمی بسنج. دو جا لغزش می‌کند: اول، ممکن است ARIA از خودش دربیاورد — بگوید روی <nav> یا <button> که خودشان معنا دارند role="..." یا aria-label="..." بگذار، دقیقاً همان شلوغیِ فصل ۶؛ روی صفحه‌ای که از tag های واقعی ساخته شده، بیشترِ این‌ها لازم نیست. دوم، AI نمی‌تواند واقعاً Tab بزند یا screen reader را بشنود، پس حدس می‌زند. هر ادعایش را خودت راستی‌آزمایی کن: واقعاً عنوان جایی می‌پرد؟ Tab واقعاً آن element را رد می‌کند؟ اول خودت، بعد AI — به حلقهٔ focus ای که می‌بینی و outline ای که می‌خوانی بیشتر از یک فهرستِ بااعتمادبه‌نفس اعتماد کن. و یادت باشد AI هم اشتباه می‌کند.

واژه‌های تازهٔ این فصل#

کلمه تلفظ به حروف فارسی یعنی چه
accessibility اَکسِسیبیلیتی ساختنِ صفحه جوری که برای همه کار کند، از جمله کاربرِ screen reader و keyboard
screen reader اسکرین ریدِر برنامه‌ای که متنِ صفحه را برای کسی که نمی‌بیند با صدا می‌خواند
focus فوکِس element ای که همین حالا keyboard رویش است؛ مرورگر دورش یک حلقه می‌کشد
landmark لَندمارک ناحیهٔ بزرگِ صفحه (<nav>، <main>، …) که کاربر می‌تواند مستقیم به آن بپرد
tabindex تَب‌ایندِکس attribute ای که ترتیبِ focus را دستکاری می‌کند؛ مقدارِ مثبتش تقریباً همیشه اشتباه است

تمرین‌ها

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

در فصل بعد#

با این فصل، مفهوم‌های تازهٔ ترم ۱ تمام شد — حالا ساختار، معنا، فرم و دسترس‌پذیری را با هم داری. فصل بعد فصلِ پروژه است: صفحهٔ معرفی خودت. هیچ tag تازه‌ای نیست؛ همه‌چیزِ این ترم را در یک صفحهٔ واقعیِ چندبخشی کنار هم می‌گذاری، و دو ابزارِ حرفه‌ای را می‌بینی: validator که می‌گوید HTML ات معتبر است یا نه، و پنلِ Elements در DevTools که می‌گذارد اسکلتِ صفحه‌ات را همان‌طور که مرورگر می‌بیند تماشا کنی.

به آخر این فصل رسیدی!

اگر ساختی و جواب داد، این دکمه مال توست.