एक्सेसिबिलिटी के लिए सिमैंटिक HTML

Semantic HTML का मतलब है वह element चुनना जो बताए कि content क्या है: section heading के लिए <h2>, site menu के लिए <nav>, options की list के लिए <ul>, action के लिए <button>, field के नाम के लिए <label>, table header के लिए <th>। इन्हीं elements से browser roles, names और states का accessibility tree बनाता है, और यही tree, screen पर दिखने वाले pixels नहीं, वह है जिसे screen reader बोलता है और जिसे voice control सुनता है। यही native elements यह भी तय करते हैं कि Tab key किन चीज़ों तक पहुँच सकती है।

टेस्टर्स के लिए HTML बेसिक्स वाले lesson में elements से परिचय हुआ था। यह lesson उन्हें दूसरी तरफ़ से देखता है: हर element assistive technology को क्या देता है, सिर्फ़ <div> और <span> से बना page क्या खो देता है, और keyboard या screen reader session से पहले असली page पर यह फ़र्क़ कैसे जाँचें।

यह क्यों ज़रूरी है

Styled <div> elements से बना page पूरा दिख सकता है और फिर भी इस्तेमाल के लायक़ नहीं: screen reader user "button" की जगह "clickable" सुनता है, headings की खाली list खोलता है, बिना नाम के field में पहुँचता है और table का कोई number बिना column के पढ़ता है। इनमें से हर एक WCAG 2.2 के success criterion 1.3.1 Info and Relationships या 4.1.2 Name, Role, Value का failure है, दोनों Level A हैं, इसलिए page सबसे निचले स्तर पर ही conformance में fail होता है और assistive technology पर निर्भर लोग काम पूरा नहीं कर पाते।

Tester के लिए semantics सबसे सस्ती accessibility जाँचों में से एक है। यह देखने के लिए screen reader नहीं चाहिए कि heading असल में styled <div> है या input का कोई <label> नहीं: markup और browser का accessibility panel इसे सेकंडों में दिखा देते हैं, और fix अक्सर एक element का बदलाव होता है। नए component की पहली review में यह पकड़ लेना बाद का पूरा screen reader round बचाता है, और यही roles और names automated tests और locators को भी ज़्यादा stable बनाते हैं।

Markup से accessibility tree तक

Browser जब HTML parse करता है तो DOM बनाता है, यानी page के elements का live tree, और DOM से एक दूसरी संरचना: accessibility tree। हर meaningful element एक node बनता है जिसका एक role होता है (heading, link, button, textbox, cell), एक accessible name (heading का text, link का text, field का label) और states या properties (heading level 2, required, checked, disabled)। जिन elements का कोई अर्थ नहीं, जैसे <div> और <span>, वे generic nodes बनते हैं या tree से पूरी तरह बाहर रह जाते हैं।

Screen readers और voice control इस tree को operating system के accessibility API से पढ़ते हैं, rendered pixels को नहीं। Screen reader role और name साथ में बोलता है ("Place order, button"), headings, landmarks और links की lists देता है ताकि user क्रम से पढ़ने के बजाय कूद सके, और role से तय करता है कि कौन-सी keys element चलाएँगी। Voice control वही activate करता है जिसका नाम user लेता है ("click Place order"), इसलिए बोला गया नाम tree में होना चाहिए। Keyboard users सिर्फ़ उसी तक पहुँचते हैं जो focusable है, और native controls default रूप से focusable होते हैं। Styling कोई role नहीं जोड़ सकती: CSS content को tree से छिपा सकती है, पर button जैसा styled <div> उसमें अब भी generic node ही रहता है।

  • Role: यह किस तरह की चीज़ है। यह element से आता है (<button>, <h2>, <a href>), या आख़िरी उपाय के तौर पर ARIA role attribute से, जो बाद का lesson समझाता है।
  • Name: इसे क्या कहा जाता है। Browser इसे content, <label>, alt, <caption> या ARIA attributes से, accessible name computation के तय क्रम में निकालता है।
  • State और value: यह अभी क्या कर रहा है। Native elements इन्हें मुफ़्त में updated रखते हैं: checked <input type="checkbox">, disabled <button>, <textarea> में टाइप किया गया text।

Headings, landmarks और lists: वह structure जिससे users navigate करते हैं

Screen reader users page को शायद ही कभी ऊपर से नीचे पढ़ते हैं। वे headings list खोलकर देखते हैं कि page में क्या है, menu छोड़ने के लिए main landmark पर कूदते हैं, और किसी list से पहले "list, four items" सुनते हैं ताकि पता रहे कि कितना आने वाला है। इनमें से हर move एक खास element के इस्तेमाल पर टिका है, और हर एक की एक सटीक जाँच है।

  • Headings, <h1> से <h6>: page के विषय के लिए एक <h1>, उसके sections के लिए <h2>, उनके अंदर <h3>। <div> में bold text से बनी visual heading headings list से ग़ायब रहती है और 1.3.1 में fail होती है; जो heading text अपने section का वर्णन नहीं करता वह 2.4.6 Headings and Labels (Level AA) में fail होता है। Levels skip करना users को उलझाता है लेकिन अपने आप में WCAG failure नहीं है, इसलिए इसे कम severity से report करें।
  • Landmarks: page के top level पर <header> banner role बनता है, <nav> navigation, <main> main, <aside> complementary और <footer> contentinfo। <section> तभी region बनता है जब उसका नाम हो, जो आम तौर पर उसकी heading की ओर इशारा करने वाले aria-labelledby से या aria-label से आता है। Landmarks users को हर page पर दोहराए गए blocks छोड़ने देते हैं, जो 2.4.1 Bypass Blocks माँगता है। जाँचें कि content <main> के अंदर है और दो <nav> elements के अलग-अलग नाम हैं, जैसे "Main menu" और "Footer links"।
  • Lists, <ul> और <ol>: screen reader बताता है कि list शुरू हो रही है और उसमें कितने items हैं। <div> rows से बना menu असंबंधित लाइनों की तरह पढ़ा जाता है, और checkout steps की <ol> divs बनते ही अपना क्रम खो देती है। सिर्फ़ styled bullets से list नहीं बनती।

Buttons, links, labels और tables: name, role और relationships

दूसरे समूह पर 4.1.2 Name, Role, Value लागू होता है: हर user interface component को अपना name, role, states और value assistive technology के सामने रखना होगा। Native elements यह default रूप से करते हैं; <div> या <span> से बने replacements नहीं करते, और ग़लत native element भी एक defect है।

  • Button या link: <button> इसी page पर कोई action करता है (submit, open, delete) और Enter तथा Space से activate होता है; <a href> कहीं और ले जाता है और Enter से activate होता है। Screen reader दोनों को अलग तरह से बोलता है और links की अलग list रखता है, इसलिए button का काम करने वाले <div onclick>, या button जैसे styled link जो सिर्फ़ script चलाता है, का expected result साफ़ है: जो काम वह करता है उसके लिए native element। बिना href का <a> link है ही नहीं: वह focusable नहीं है, और उसका text link की तरह नहीं, सादे text की तरह पढ़ा जाता है।
  • Labels: field का नाम उस <label> से आता है जिसका for field की id के बराबर हो, या उस <label> से जो field को wrap करता है। placeholder attribute name computation में सिर्फ़ fallback है और उसका hint user के टाइप करते ही ग़ायब हो जाता है, इसलिए जिस field का इकलौता label placeholder हो वह report करने लायक़ defect है। Radio buttons या checkboxes का समूह अपना साझा सवाल <fieldset> और <legend> से लेता है; इनके बिना user "Yes, radio button" सुनता है और सवाल क्या था, पता नहीं चलता।
  • Tables: <table> rows और columns वाले data के लिए है, headers के लिए <th scope="col"> या <th scope="row"> और title के लिए <caption> के साथ। तब tree हर data cell को उसके headers से जोड़ता है, इसलिए user जब एक cell से दूसरे पर जाता है तो screen reader बदला हुआ header बोलता है, जैसे हर value से पहले column का नाम, और user किसी row या column के साथ-साथ चल सकता है। <div> elements की grid, या ऐसी table जिसके headers bold <td> cells हों, ये relationships खो देती है और 1.3.1 में fail होती है। उलटी ग़लती भी होती है: layout के लिए इस्तेमाल हुई <table>, जो बेमतलब rows और columns announce कर सकती है।

Worked example: एक ही checkout page दो markups में

एक front-end component library checkout page को नीचे दिए markup A की तरह render करती है: input को छोड़कर हर element एक class वाला <div> है, जिसे heading, menu, field label, summary table और button जैसा style किया गया है। Design review pass हो जाती है, क्योंकि screen पर यह markup B से अलग नहीं दिखता, जो हर structure के लिए एक semantic element इस्तेमाल करता है।

दोनों को browser के DevTools में खोलें (किसी element पर right-click करके Inspect चुनें; Chrome और Edge में Styles वाली tabs की पंक्ति में मौजूद Accessibility tab चुने गए element का role और computed name दिखाता है) और फ़र्क़ तुरंत दिखता है। A में "Checkout" text वाला generic node है, इसलिए headings list खाली है; menu दो generic items हैं जिन तक Tab कभी नहीं पहुँचता; input का कोई नाम नहीं; "Total" और "600 SAR" असंबंधित text हैं; और "Place order" एक generic node है जिसे सिर्फ़ mouse activate कर सकता है। B में tree heading level 1 "Checkout", दो links की list वाला navigation landmark, एक main landmark, "Postal code" नाम का required textbox, ऐसी table जिसमें "600 SAR" अपने row header "Total" से जुड़ा है, और "Place order" नाम का button दिखाता है जिस तक Tab पहुँचता है और जिसे Enter या Space activate करता है। Visually कुछ नहीं बदला; assistive technology के लिए सब कुछ बदल गया।

<!-- A: div soup -->
<div class="title">Checkout</div>
<div class="menu">
  <div class="item" onclick="go('/orders')">Orders</div>
  <div class="item" onclick="go('/addresses')">Addresses</div>
</div>
<div class="hint">Postal code</div>
<input class="zip">
<div class="row"><div class="cell">Total</div><div class="cell">600 SAR</div></div>
<div class="btn" onclick="pay()">Place order</div>

<!-- B: semantic HTML, identical on screen -->
<nav>
  <ul>
    <li><a href="/orders">Orders</a></li>
    <li><a href="/addresses">Addresses</a></li>
  </ul>
</nav>
<main>
  <h1>Checkout</h1>
  <form action="/orders" method="post">
    <label for="zip">Postal code</label>
    <input id="zip" name="zip" required>
    <table>
      <caption>Order summary</caption>
      <tr><th scope="row">Total</th><td>600 SAR</td></tr>
    </table>
    <button type="submit">Place order</button>
  </form>
</main>
एक ही checkout page div soup और semantic HTML के रूप में: screen पर दोनों एक जैसे हैं, पर सिर्फ़ semantic version assistive technology को heading, landmarks, list, नाम वाला field, table header और Tab से पहुँचने लायक़ button देता है।

A: div soupदिखने में सही

Input को छोड़कर हर structure एक class वाला styled <div>

Headings की list:
खाली: "Checkout" generic text हैफ़ेल
Landmarks:
कोई नहीं: सिर्फ़ generic divsफ़ेल
Menu (Orders, Addresses):
Text की दो लाइनें; Tab कभी नहीं पहुँचताफ़ेल
Postal code वाला field:
बिना नाम का textboxफ़ेल
Order का total:
"Total" और "600 SAR" असंबंधित textफ़ेल
"Place order" control:
Generic node; सिर्फ़ mouseफ़ेल

B: semantic HTMLपढ़ने में भी सही

हर structure के लिए एक native element, screen पर वही रूप

Headings की list:
Heading level 1 "Checkout"पास
Landmarks:
navigation और mainपास
Menu (Orders, Addresses):
दो links की list, हर एक focusableपास
Postal code वाला field:
Textbox "Postal code", requiredपास
Order का total:
Cell "600 SAR" अपने row header "Total" से जुड़ापास
"Place order" control:
Button; Tab पहुँचता है, Enter या Space activate करता हैपास

हर row accessibility tree बताती है, जैसा browser का DevTools accessibility panel दिखाता है।

आज़माएँ: HTML फ़ॉर्मेटर

आम गलतियाँ

  • Accessibility को screen देखकर आँकना। सही दिखने वाले page का accessibility tree लगभग खाली हो सकता है; pixels नहीं, markup या accessibility panel जाँचें।
  • हर clickable चीज़ को एक जैसा मानना: <div onclick> button नहीं है, बिना href का <a> link नहीं है, और दूसरे page पर ले जाने वाला <button> link होना चाहिए।
  • placeholder को label मान लेना, या ऐसा <label> स्वीकार कर लेना जिसका for ऐसी id की ओर इशारा करता हो जो page पर है ही नहीं।
  • Headings कैसी दिखती हैं यह जाँचना, न कि वे क्या हैं: page में छह बड़ी bold लाइनें हो सकती हैं और एक भी <h1> नहीं।
  • Role और name बताए बिना "screen readers के लिए accessible नहीं" report करना: उपयोगी defect बताता है कि tree क्या expose करता है, क्या करना चाहिए और कौन-सा success criterion fail होता है।
  • <div> सुधारने के लिए ARIA की ओर लपकना, जबकि native element एक ही बदलाव में role, name, keyboard behaviour और states दे देता।

QA का नज़रिया

Team में semantics की जाँच review के सबसे शुरुआती चरण में होती है। जब pull request या design-system update में नया component या page template आए, किसी भी test session से पहले उसका markup पढ़ें: असली headings, हर action के लिए <button>, हर field के लिए <label>, data tables में <th>। ये उम्मीदें front-end developer से तय करें और definition of done में लिखें, ताकि जाँच code review में हो, हफ़्तों बाद finding बनकर न आए।

बने हुए page को टेस्ट करते समय DevTools accessibility panel खोलकर हर control का role और computed name पढ़ें, page पर Tab दबाकर पक्का करें कि हर control तक पहुँचा जा सकता है, और visual headings की तुलना tree की headings से करें। हर defect में element जैसा render हुआ, tree जो role और name expose करता है, expected element और success criterion (अक्सर 1.3.1 या 4.1.2) दर्ज करें। आगे के keyboard और screen reader guides ठीक इसी layer पर बनते हैं: semantics ग़लत हों तो बाद का हर test उसी root cause से fail होता है।

अभ्यास

Product card का markup review करें

आपका काम

एक product listing में cards हैं जिनमें product का नाम बड़े text में, star rating, price, एक "Add to cart" control और एक "Details" control है जो product page खोलता है। एक card का developer का markup नीचे है। बिना screen reader के लिखें कि accessibility tree हर हिस्से के लिए क्या expose करेगा, defects को उस WCAG 2.2 criterion के साथ नाम दें जिसमें हर एक fail होता है, और बताएँ कि उसकी जगह कौन-सा semantic element होना चाहिए।

फिर सुधारी हुई card के लिए एक test case लिखें जिसे सिर्फ़ keyboard वाला tester चला सके।

सामग्री
<div class="card">
  <div class="name">Wireless keyboard</div>
  <div class="rating">★★★★☆</div>
  <div class="price">249 SAR</div>
  <span class="btn" onclick="addToCart(42)">Add to cart</span>
  <a class="btn" onclick="openProduct(42)">Details</a>
</div>
चरण
  1. Card को ऊपर से नीचे देखें और लिखें कि accessibility tree में हर element का role और name क्या होगा।
  2. हर वह जगह mark करें जहाँ role generic है या name missing या misleading है।
  3. हर एक के लिए वह native element चुनें जो सही role, name और keyboard behaviour दे।
  4. Keyboard test case लिखें, हर step के साथ उसका expected result।
मॉडल उत्तर दिखाएँ
मॉडल उत्तर

आज का tree: text वाले पाँच generic nodes। Product का नाम heading नहीं है, इसलिए card headings list से नहीं मिल सकती (1.3.1)। Rating अपनी value सिर्फ़ star symbols से बताती है; screen reader चाहे "black star" चार बार और "white star" एक बार पढ़े या symbols को छोड़ दे, user को ख़ुद अंदाज़ा लगाना पड़ता है, इसलिए "4 of 5 stars" जैसा text equivalent चाहिए (1.1.1 Non-text Content: WCAG characters के ऐसे pattern को, जो इंसानी भाषा व्यक्त नहीं करता, जैसे ये stars, icon या image की तरह non-text content मानता है)। "Add to cart" बिना role का <span> है जो focusable नहीं, इसलिए keyboard user product जोड़ ही नहीं सकता (4.1.2 और 2.1.1 Keyboard)। "Details" बिना href का <a> है, इसलिए वह link नहीं, focusable नहीं और links list से ग़ायब है (4.1.2 और 2.1.1)।

Expected markup: हर card products की <ul> में एक <li>, नाम सही level की heading (जैसे <h2> "Results" के नीचे <h3>), "4 of 5 stars" वाला text equivalent (जैसे stars की <img> जिसका alt="4 of 5 stars" हो, या दिखने वाला text, जिसके star symbols को aria-hidden="true" accessibility tree से हटा दे), <button type="button">Add to cart</button>, और <a href="/products/42">Details</a>। चूँकि हर card वही control names दोहराती है, एक follow-up सवाल लिख लें: screen reader user कैसे जानेगा कि "Add to cart" किस product का है? Screen reader testing guide अपने section "व्यवहार में names, labels और descriptions जाँचना" में इसका जवाब देता है।

Keyboard test case। Precondition: product list खुली है और कम से कम एक card है। Step 1: page की शुरुआत से Tab दबाएँ जब तक focus पहली card पर न पहुँचे; expected: "Add to cart" पर दिखता हुआ focus ring। Step 2: Enter दबाएँ; expected: cart count एक बढ़ता है। Step 3: Space दबाएँ; expected: cart count फिर से एक बढ़ता है, क्योंकि button दोनों keys पर काम करता है। Step 4: Tab दबाएँ; expected: focus "Details" पर जाता है। Step 5: Enter दबाएँ; expected: wireless keyboard का product page खुलता है।

अक्सर पूछे जाने वाले सवाल

क्या semantic HTML से page WCAG-conformant हो जाता है?

नहीं। यह 1.3.1 और 4.1.2 का बड़ा हिस्सा cover करता है और keyboard operability मुफ़्त में देता है, लेकिन contrast, text alternatives, visible focus, error messages और कई दूसरे criteria बाक़ी रहते हैं। Semantics वह नींव है जिसे बाक़ी जाँचें मान कर चलती हैं।

क्या मैं बिना screen reader के semantics टेस्ट कर सकता हूँ?

ज़्यादातर, हाँ। DevTools accessibility panel किसी भी element का role और computed name दिखाता है, Tab key दिखाती है कि क्या focusable है, और headings outline structure दिखाता है। Screen reader session, जिसे बाद की guide समझाती है, पुष्टि करता है कि users असल में क्या सुनते हैं और वह पकड़ता है जो अकेला tree नहीं दिखा सकता।

अगर <div> पर role="button" है, तो क्या वह <button> जितना अच्छा है?

सिर्फ़ तब, जब developer हाथ से focusability, Enter और Space handling और disabled state जोड़े और यह सब चलता रखे। Native element में यह सब built-in है और हर browser में tested है, इसीलिए ARIA इस्तेमाल का पहला नियम इसे prefer करने को कहता है। ARIA lesson बताता है कि role कब सही चुनाव है।

संदर्भ

  • Web Content Accessibility Guidelines (WCAG) 2.2W3C · 2024W3C की Recommendation जो सुलभ वेब कंटेंट के लिए टेस्ट करने योग्य success criteria तय करती है — चार सिद्धांतों और तीन conformance स्तरों (A, AA, AAA) में व्यवस्थित।
  • HTML Living StandardWHATWGHTML भाषा, नामित कैरेक्टर रेफ़रेंस (एंटिटी) और ब्राउज़रों के पार्सिंग नियमों सहित।
  • Accessible Name and Description Computation 1.2W3C · 2026ब्राउज़र किसी एलिमेंट का accessible name और description लेबल, ARIA एट्रिब्यूट और कंटेंट से कैसे निकालते हैं (W3C Working Draft)।
  • Understanding WCAG 2.2W3C Web Accessibility Initiative (WAI)WCAG 2.2 की हर guideline और success criterion की व्याख्या: उद्देश्य, किसे लाभ, उदाहरण और तकनीकें (नॉर्मेटिव नहीं)।

Mutqan tools से अभ्यास करें

नेस्टेड एलिमेंट को सही इंडेंटेशन देकर HTML सुंदर बनाएँ, pre, script और style ब्लॉक सुरक्षित रखते हुए।

फ़ॉर्मेटिंग

फ़ीचर के विवरण और फ़ील्ड सूची से संरचित टेस्ट केस (id, शीर्षक, पूर्व-शर्तें, स्टेप, अपेक्षित परिणाम, प्राथमिकता) जनरेट करें।

टेस्ट डिज़ाइन

Mutqan AI से किसी भी फ़ीचर के लिए अनुकूलित QA चेकलिस्ट (functional, UI, API, security, performance, accessibility, release) बनाएँ।

टेस्ट जनरेशन AI

और गहराई से

इस topic में आपकी प्रगति

QA रोडमैप का हिस्सा