HTML scope Attribute

Beginner
⏱️ 5 min read
📚 Updated: Jun 2026
🎯 3 Examples
Tables & Accessibility

Introduction

The scope attribute is used on <th> header cells in HTML tables to describe which cells a header labels. It helps screen readers and other assistive technologies understand row and column relationships, making tabular data easier to navigate for everyone.

What You’ll Learn

01

<th> Headers

Where scope applies.

02

scope="col"

Column headers.

03

scope="row"

Row headers.

04

rowgroup

Grouped row headers.

05

colgroup

Grouped column headers.

06

JavaScript

Set scope dynamically.

Purpose of scope

The main purpose of the scope attribute is to specify the relationship between header cells (<th>) and the data cells (<td>) they describe. Without this hint, a screen reader user hearing “$10,000” may not know whether it is January’s revenue or February’s expenses.

By marking column headers with scope="col" and row headers with scope="row", you expose the table’s logical structure to assistive technology in a simple, declarative way.

💡
Accessibility First

scope does not change visual layout—it improves how tables are announced. Pair it with a clear <caption>, proper <thead>/<tbody> structure, and meaningful header text.

📝 Syntax

Add scope to <th> elements with one of four keyword values:

scope.html
<th scope="col">Revenue</th>
<th scope="row">January</th>

Syntax Rules

  • Valid on <th> elements in <table>, <thead>, <tbody>, and <tfoot>.
  • Value must be one of: row, col, rowgroup, or colgroup.
  • Use col for headers that label columns; row for headers that label rows.
  • Use rowgroup or colgroup when a header spans a group via rowspan or colspan.
  • Do not use scope on <td> data cells—use <th> for headers instead.
  • For very complex tables, the headers attribute on <td> can complement or replace scope.

💎 Values

The scope attribute accepts exactly four enumerated values:

  • row — The header applies to all cells in the same row (typical for the first cell in a data row).
  • col — The header applies to all cells in the same column (typical for headers in <thead>).
  • rowgroup — The header applies to a group of rows, often when the <th> spans multiple rows with rowspan.
  • colgroup — The header applies to a group of columns, often when the <th> spans multiple columns with colspan.
scope-values.html
<!-- Column header in thead -->
<th scope="col">Month</th>

<!-- Row header in tbody -->
<th scope="row">January</th>

<!-- Header spanning a row group -->
<th scope="rowgroup" rowspan="2">Q1</th>

⚡ Quick Reference

Header typescope valueTypical placement
Column labelcol<thead> top row
Row labelrowFirst <th> in each <tr>
Multi-row group labelrowgroup<th rowspan="n">
Multi-column group labelcolgroup<th colspan="n">
Applicable element<th>Not on <td>
JavaScriptth.scope = "row"Dynamic tables

Applicable Elements

ElementSupported?Notes
<th>YesPrimary and intended use
<td>NoUse <th> for headers; use headers on td if needed
<table>NoPut scope on th cells inside the table
<input>NoNot related to form controls

scope vs headers vs id

ApproachUsed onBest for
scope<th>Most tables with clear row/column headers
headers<td>Complex tables with irregular header associations
id on th + headers on tdBothExplicit many-to-many header links

Start with scope for straightforward data tables. Reach for headers when a single data cell is labeled by multiple non-adjacent headers.

Examples Gallery

Monthly report with column and row headers, rowgroup for quarterly sections, and dynamic th.scope in JavaScript.

👀 Live Preview

Accessible table with scope="col" and scope="row":

Monthly Report
MonthRevenueExpenses
January$10,000$7,000
February$12,000$8,500

Screen readers use scope to associate “January” with its row and “Revenue” with its column.

Example — Column and Row Headers

A simple financial table with column headers in <thead> and row headers in <tbody>:

scope.html
<table>
  <caption>Monthly Report</caption>
  <thead>
    <tr>
      <th scope="col">Month</th>
      <th scope="col">Revenue</th>
      <th scope="col">Expenses</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">January</th>
      <td>$10,000</td>
      <td>$7,000</td>
    </tr>
    <tr>
      <th scope="row">February</th>
      <td>$12,000</td>
      <td>$8,500</td>
    </tr>
  </tbody>
</table>
Try It Yourself

How It Works

scope="col" on Month, Revenue, and Expenses labels their columns. scope="row" on January and February labels their rows. A screen reader can announce “January, Revenue, $10,000” instead of a bare number.

Example — rowgroup for Grouped Rows

When a header spans multiple rows, use scope="rowgroup":

scope-rowgroup.html
<table>
  <thead>
    <tr>
      <th scope="col">Quarter</th>
      <th scope="col">Month</th>
      <th scope="col">Sales</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="rowgroup" rowspan="2">Q1</th>
      <th scope="row">January</th>
      <td>100</td>
    </tr>
    <tr>
      <th scope="row">February</th>
      <td>120</td>
    </tr>
  </tbody>
</table>
Try It Yourself

How It Works

rowgroup tells assistive tech that the header applies to a set of rows, not just one. Use colgroup similarly when a column header spans multiple columns with colspan.

Dynamic Values with JavaScript

Set scope when building or updating tables at runtime:

dynamic-scope.html
<table id="dataTable">
  <tr>
    <th id="dynamicHeader">Name</th>
    <td>John</td>
  </tr>
</table>

<script>
  document.getElementById("dynamicHeader").scope = "row";
</script>
Try It Yourself

How It Works

HTMLTableCellElement.scope reflects the content attribute. When you add rows via JavaScript, set scope on each new <th> as you create it—do not rely on visual position alone.

♿ Accessibility

  • Use scope on every th — Mark column headers scope="col" and row headers scope="row" consistently.
  • Add a caption<caption> gives the table a title for all users, not just screen reader users.
  • Prefer th over styled td — Do not use <td> with bold styling as a fake header; use <th> with scope.
  • Test with a screen reader — NVDA, JAWS, or VoiceOver should announce header associations correctly.
  • Complex tables need headers — When scope alone is insufficient, link cells with the headers attribute.

🧠 How scope Works

1

Author marks th with scope

col, row, rowgroup, or colgroup.

Markup
2

Browser builds table model

Links headers to data cells.

DOM
3

Assistive tech reads context

Announces row and column labels.

A11y
=

Clearer tabular data

Users understand every cell in context.

Browser Support

The scope attribute is supported in all modern browsers on <th> elements and is reflected by the scope IDL property.

HTML5 · Fully supported

Universal table accessibility attribute

All major browsers expose scope on header cells for the accessibility tree.

99% Browser support
Google Chrome Fully supported
Full support
Mozilla Firefox Fully supported
Full support
Apple Safari Fully supported
Full support
Microsoft Edge Fully supported
Full support
scope attribute 99% supported

Bottom line: Use scope confidently on <th> cells in all modern projects.

💡 Best Practices

✅ Do

  • Apply scope="col" to every column header in <thead>
  • Apply scope="row" to row header <th> cells in <tbody>
  • Use rowgroup and colgroup when headers span multiple rows or columns
  • Include a descriptive <caption> on data tables
  • Test tables with keyboard navigation and a screen reader

❌ Don’t

  • Put scope on <td> data cells
  • Use layout tables for page structure when semantic HTML suffices
  • Skip headers in complex tables and rely on color alone
  • Mix up col and row values on the wrong header type
  • Forget to set scope on dynamically inserted <th> elements

Conclusion

The scope attribute is a crucial tool for improving the accessibility and structure of HTML tables. By marking header relationships explicitly, you help assistive technologies interpret tabular data correctly.

Use scope="col" and scope="row" on every appropriate <th>, reach for rowgroup and colgroup when headers span groups, and combine scope with captions and semantic table markup for the best results.

Key Takeaways

Knowledge Unlocked

Five truths every developer should know about scope

Bookmark these before your next data table.

5
Core concepts
02

scope="col"

Column labels

Value
03

scope="row"

Row labels

Value
⚙️ 04

Groups

rowgroup / colgroup

Advanced
05

A11y win

Screen reader context

Why

❓ Frequently Asked Questions

It tells assistive technologies whether a <th> header labels a row, column, row group, or column group in a table.
<th> header cells only. Do not use scope on <td> data cells.
Use col for headers across the top (column labels). Use row for headers in the first column of each row (row labels).
Not strictly required for simple tables, but it is strongly recommended for accessibility and is considered a best practice in WCAG-aligned markup.
Yes. Set thElement.scope = "row" or use setAttribute("scope", "col") when building tables dynamically.
Yes in all modern browsers on <th> elements.

Build accessible data tables

Practice scope="col" and scope="row" on a monthly report table in the Try It editor.

Try monthly report example →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful