HTML Guides for div
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The aria-rowspan attribute is used in ARIA-based grid and table structures to indicate how many rows a cell spans. It serves a similar purpose to the rowspan attribute on native HTML <td> and <th> elements, but is designed for custom widgets built with ARIA roles like gridcell, rowheader, and columnheader within grid or treegrid structures.
According to the WAI-ARIA specification, the value of aria-rowspan must be a positive integer — a whole number greater than zero. A value of "0" is invalid because it implies the cell spans no rows, which is semantically meaningless. Note that this differs from native HTML’s rowspan attribute, where "0" has a special meaning (span all remaining rows in the row group). The ARIA attribute does not support this behavior.
This matters primarily for accessibility. Screen readers and other assistive technologies rely on aria-rowspan to convey the structure of custom grids to users. An invalid value of "0" can confuse assistive technology, potentially causing it to misrepresent the grid layout or skip the cell entirely. Ensuring valid values helps users who depend on these tools navigate your content correctly.
To fix this issue, determine how many rows the cell actually spans and set aria-rowspan to that number. If the cell occupies a single row, use "1". If it spans multiple rows, use the appropriate count. If you don’t need row spanning at all, you can simply remove the aria-rowspan attribute entirely, since the default behavior is to span one row.
Examples
Incorrect: aria-rowspan set to zero
<div role="grid">
<div role="row">
<div role="gridcell" aria-rowspan="0">Name</div>
<div role="gridcell">Value</div>
</div>
</div>
The value "0" is not a positive integer, so the validator reports an error.
Correct: aria-rowspan set to a positive integer
If the cell spans a single row, use "1" (or remove the attribute, since one row is the default):
<div role="grid">
<div role="row">
<div role="gridcell" aria-rowspan="1">Name</div>
<div role="gridcell">Value</div>
</div>
</div>
Correct: aria-rowspan for a cell spanning multiple rows
If the cell genuinely spans two rows, set the value accordingly:
<div role="grid">
<div role="row">
<div role="gridcell" aria-rowspan="2">Category</div>
<div role="gridcell">Item A</div>
</div>
<div role="row">
<div role="gridcell">Item B</div>
</div>
</div>
Correct: removing the attribute when no spanning is needed
If the cell doesn’t span multiple rows, the simplest fix is to remove aria-rowspan altogether:
<div role="grid">
<div role="row">
<div role="gridcell">Name</div>
<div role="gridcell">Value</div>
</div>
</div>
When to use aria-rowspan vs. native HTML
If you’re building a data table, prefer native HTML <table>, <tr>, <td>, and <th> elements with the standard rowspan attribute. Native table semantics are automatically understood by browsers and assistive technologies without any ARIA attributes. Reserve aria-rowspan for custom interactive widgets (like spreadsheet-style grids or tree grids) where native table elements aren’t appropriate. The aria-rowspan value should always match the actual visual and structural layout of your grid to avoid confusing assistive technology users.
The attribute aria-hidden must have a value of "true" (without extra quotes) or "false", not "\"true\"" (with double quotes inside the value).
The aria-hidden attribute is used to indicate whether an element and its children should be accessible to assistive technologies (like screen readers). Valid values are the strings "true" or "false" (without embedded quotation marks). Using extra quotation marks causes the validator to flag a bad value because the attribute’s value is interpreted literally.
Incorrect Example:
<div aria-hidden='"true"'>This is hidden from assistive tech</div>
Correct Example:
<div aria-hidden="true">This is hidden from assistive tech</div>
or
<div aria-hidden="false">This is visible to assistive tech</div>
Remove any extra quotation marks around your attribute value to resolve the error.
The rel attribute defines the relationship between the current document and a linked resource. The HTML specification maintains a set of recognized keyword values for this attribute, and the allowed keywords vary depending on which element the attribute appears on. For example, stylesheet is valid on <link> but not on <a>, while nofollow is valid on <a> and <form> but not on <link>.
When the validator encounters a rel value that isn’t a recognized keyword, it checks whether the value is a valid absolute URL. This is because the HTML specification allows custom link types to be defined using absolute URLs as identifiers (similar to how XML namespaces work). If the value is neither a recognized keyword nor a valid absolute URL, the validator raises this error.
Common causes of this error include:
- Typos in standard keywords — for example, rel="styelsheet" or rel="no-follow" instead of the correct rel="stylesheet" or rel="nofollow".
- Using non-standard or invented values — such as rel="custom" or rel="external", which aren’t part of the HTML specification’s recognized set.
- Using relative URLs as custom link types — for example, rel="my-custom-type" instead of a full URL like rel="https://example.com/my-custom-type".
This matters because browsers and other user agents rely on recognized rel values to determine how to handle linked resources. An unrecognized value will simply be ignored, which could mean your stylesheet doesn’t load, your prefetch hint doesn’t work, or search engines don’t respect your intended link relationship. Using correct values ensures predictable behavior across all browsers and tools.
Examples
Incorrect: Misspelled keyword
<link rel="styleshet" href="main.css">
The validator reports that styleshet is not a recognized keyword and is not an absolute URL.
Correct: Fixed spelling
<link rel="stylesheet" href="main.css">
Incorrect: Non-standard keyword on an anchor
<a href="https://example.com" rel="external">Visit Example</a>
The value external is not a standard rel keyword in the HTML specification, so the validator flags it.
Correct: Using a recognized keyword
<a href="https://example.com" rel="noopener">Visit Example</a>
Incorrect: Relative URL as a custom link type
<link rel="my-custom-rel" href="data.json">
Correct: Absolute URL as a custom link type
If you genuinely need a custom relationship type, provide a full absolute URL:
<link rel="https://example.com/rels/my-custom-rel" href="data.json">
Correct: Common valid rel values
Here are some frequently used standard rel keywords with their appropriate elements:
<!-- Linking a stylesheet -->
<link rel="stylesheet" href="styles.css">
<!-- Linking a favicon -->
<link rel="icon" href="favicon.ico">
<!-- Preloading a resource -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
<!-- Telling search engines not to follow a link -->
<a href="https://example.com" rel="nofollow">Sponsored link</a>
<!-- Opening a link safely in a new tab -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">External site</a>
Multiple rel values
You can specify multiple space-separated rel values. Each one must individually be either a recognized keyword or a valid absolute URL:
<!-- Correct: both values are recognized keywords -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">External</a>
<!-- Incorrect: "popup" is not a recognized keyword or absolute URL -->
<a href="https://example.com" target="_blank" rel="noopener popup">External</a>
To resolve this error, consult the MDN rel attribute reference for the full list of recognized keywords and which elements support them. If your value isn’t on the list, either replace it with the correct standard keyword or use a complete absolute URL to define your custom link type.
The <dl> element represents a description list — a collection of terms (<dt>) paired with their descriptions (<dd>). According to the HTML specification, the permitted content of a <dl> is either groups of <dt> and <dd> elements directly, or <div> elements that wrap those groups. This <div> wrapping option exists specifically to help with styling, since it lets you apply CSS to a term-description pair as a unit.
However, these wrapper <div> elements are not general-purpose containers inside <dl>. The spec requires that each <div> inside a <dl> contains at least one <dt> or <dd> child. A <div> that is empty, or that contains other elements like <span>, <p>, or another <div>, violates this rule and produces a validation error.
This matters for several reasons. Screen readers and assistive technologies rely on the semantic structure of description lists to convey the relationship between terms and definitions. An empty or improperly structured <div> inside a <dl> breaks that semantic contract, potentially confusing both assistive technology and browsers. Keeping your markup valid also ensures consistent rendering across all browsers.
How to Fix It
- Ensure every <div> inside a <dl> contains at least one <dt> or <dd> — don’t leave wrapper <div> elements empty.
- Don’t put non-<dt>/<dd> content directly inside these <div> wrappers — elements like <span>, <p>, or nested <div> elements should be placed inside a <dt> or <dd>, not as siblings to them.
- Remove unnecessary <div> wrappers — if a <div> inside a <dl> serves no styling or grouping purpose, remove it entirely.
Examples
❌ Empty <div> inside a <dl>
<dl>
<div>
</div>
<div>
<dt>HTML</dt>
<dd>A markup language for structuring web content.</dd>
</div>
</dl>
The first <div> is empty and has no <dt> or <dd> child, triggering the error.
❌ <div> with only non-<dt>/<dd> children
<dl>
<div>
<p>This is a description list:</p>
</div>
<div>
<dt>CSS</dt>
<dd>A style sheet language for describing presentation.</dd>
</div>
</dl>
The first <div> contains a <p> element but no <dt> or <dd>, which is invalid.
✅ Each <div> contains <dt> and <dd> elements
<dl>
<div>
<dt>HTML</dt>
<dd>A markup language for structuring web content.</dd>
</div>
<div>
<dt>CSS</dt>
<dd>A style sheet language for describing presentation.</dd>
</div>
</dl>
✅ Using <dl> without <div> wrappers
If you don’t need <div> elements for styling, you can place <dt> and <dd> directly inside the <dl>:
<dl>
<dt>HTML</dt>
<dd>A markup language for structuring web content.</dd>
<dt>CSS</dt>
<dd>A style sheet language for describing presentation.</dd>
</dl>
✅ A <dt> with multiple <dd> descriptions in a <div>
A single term can have multiple descriptions. The <div> is valid as long as it contains at least one <dt> or <dd>:
<dl>
<div>
<dt>JavaScript</dt>
<dd>A programming language for the web.</dd>
<dd>Supports event-driven and functional programming.</dd>
</div>
</dl>
The aria-required attribute tells assistive technologies that a form field must be filled in before the form can be submitted. However, this attribute is only valid on elements that function as interactive widgets. A bare div has no implicit ARIA role, so assistive technologies have no context for what kind of input is expected. The validator flags this because an aria-required attribute on a generic div is effectively meaningless without additional ARIA attributes that define the element’s role and behavior.
This matters for several reasons:
- Accessibility: Screen readers and other assistive technologies rely on roles to understand how to present an element to users. Without a role, aria-required provides incomplete information.
- Standards compliance: The WAI-ARIA specification defines which attributes are allowed on which roles. Using aria-required without an established role violates these constraints.
- Browser behavior: Browsers may ignore or misinterpret ARIA attributes when they appear on elements that lack the proper role context.
How to fix it
Option 1: Use native semantic HTML (preferred)
Whenever possible, use native HTML form elements. They come with built-in accessibility semantics, keyboard interaction, and validation — no ARIA needed.
Replace a div with aria-required="true" with an appropriate form control using the native required attribute:
<input type="text" required>
<select required>
<option value="">Choose one</option>
<option value="1">Option 1</option>
</select>
<textarea required></textarea>
Option 2: Add an appropriate role attribute
When you must use a div as a custom widget (styled and enhanced with CSS and JavaScript), add the correct role attribute to give it semantic meaning. Choose the role that matches the widget’s actual behavior — don’t just pick one arbitrarily.
Common roles that support aria-required:
- combobox — a custom dropdown with text input
- listbox — a custom selection list
- radiogroup — a group of radio-like options
- spinbutton — a numeric stepper (also requires aria-valuemax, aria-valuemin, and aria-valuenow)
- textbox — a custom text input
Option 3: Add other qualifying ARIA attributes
For certain widgets like sliders or spinbuttons, you may need aria-valuemax, aria-valuemin, and aria-valuenow in addition to (or as part of) defining the role. These attributes inherently establish a widget context.
Examples
❌ Invalid: aria-required on a plain div
<div aria-required="true">
<div data-value="One">1</div>
<div data-value="Two">2</div>
<div data-value="Three">3</div>
</div>
This triggers the validation error because the div has no role or other ARIA attributes to define what kind of widget it is.
✅ Fixed: Adding the appropriate role
<div aria-required="true" role="radiogroup" aria-label="Pick a number">
<div role="radio" aria-checked="false" tabindex="0">1</div>
<div role="radio" aria-checked="false" tabindex="0">2</div>
<div role="radio" aria-checked="false" tabindex="0">3</div>
</div>
Adding role="radiogroup" gives the div a semantic identity. Note that child elements also need appropriate roles and attributes for the widget to be fully accessible.
✅ Fixed: Using native HTML instead
<fieldset>
<legend>Pick a number</legend>
<label><input type="radio" name="number" value="1" required> 1</label>
<label><input type="radio" name="number" value="2"> 2</label>
<label><input type="radio" name="number" value="3"> 3</label>
</fieldset>
This approach uses native radio buttons with the required attribute, eliminating the need for ARIA entirely. The browser handles accessibility, keyboard navigation, and form validation automatically.
✅ Fixed: A custom spinbutton with value attributes
<div role="spinbutton"
aria-required="true"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
aria-label="Quantity"
tabindex="0">
50
</div>
For a spinbutton role, you must also provide aria-valuemin, aria-valuemax, and aria-valuenow to fully describe the widget’s state.
The HTML specification defines a strict content model for the <ul> (unordered list) element: its permitted content is zero or more <li> elements, optionally intermixed with <script> and <template> elements. A <div> is not among these allowed children, so placing one directly inside a <ul> produces a validation error.
This issue commonly arises when developers try to group or wrap list items for styling or layout purposes. For example, you might want to add a container around certain <li> elements for flexbox or grid alignment, or you might be using a templating system that injects wrapper <div> elements into your list markup.
Why this matters
- Browser parsing inconsistencies: When browsers encounter invalid nesting, they attempt to fix the DOM structure automatically, but different browsers may handle it differently. This can lead to unexpected rendering where list items appear outside their intended container or styles break unpredictably.
- Accessibility: Screen readers and assistive technologies rely on correct semantic structure to convey list relationships to users. A <div> breaking the <ul> → <li> relationship can cause assistive tools to misinterpret or skip list content entirely.
- Standards compliance: Invalid HTML can cause cascading parser errors — note that the validator message says “Suppressing further errors from this subtree,” meaning additional issues within that structure may be hidden from you.
How to fix it
- Move the <div> inside the <li>: If you need a wrapper for styling, place it inside the list item rather than around it.
- Remove the <div> entirely: If it serves no purpose, simply remove it and let the <li> elements sit directly inside the <ul>.
- Use CSS on the <li> elements: In many cases, you can apply the styles you need directly to the <li> elements without an extra wrapper.
- Use role="list" on a <div> parent: If your layout truly requires <div> wrappers, consider restructuring with ARIA roles, though native semantic elements are always preferred.
Examples
❌ Incorrect: <div> as a direct child of <ul>
<ul>
<div>
<li>Apples</li>
<li>Bananas</li>
</div>
<div>
<li>Carrots</li>
<li>Dates</li>
</div>
</ul>
✅ Correct: Move the <div> inside each <li>
<ul>
<li><div>Apples</div></li>
<li><div>Bananas</div></li>
<li><div>Carrots</div></li>
<li><div>Dates</div></li>
</ul>
✅ Correct: Remove the <div> entirely
<ul>
<li>Apples</li>
<li>Bananas</li>
<li>Carrots</li>
<li>Dates</li>
</ul>
❌ Incorrect: Using a <div> as a styling wrapper around list items
<ul class="product-list">
<div class="row">
<li>Product A</li>
<li>Product B</li>
<li>Product C</li>
</div>
</ul>
✅ Correct: Apply layout styles directly to the <ul> and <li> elements
<ul class="product-list row">
<li>Product A</li>
<li>Product B</li>
<li>Product C</li>
</ul>
❌ Incorrect: Template or component wrapper inserting a <div>
This often happens in frameworks where a component renders a wrapping <div>:
<ul>
<div class="list-item-wrapper">
<li>Item 1</li>
</div>
<div class="list-item-wrapper">
<li>Item 2</li>
</div>
</ul>
✅ Correct: Move the wrapper class to the <li> itself
<ul>
<li class="list-item-wrapper">Item 1</li>
<li class="list-item-wrapper">Item 2</li>
</ul>
The same rule applies to <ol> (ordered list) elements — they share the same content model restriction. Always ensure that <li> is the direct child of <ul> or <ol>, and place any additional wrapper elements inside the <li> rather than around it.
A <div> tag appears where the HTML structure does not expect it, often due to incorrect nesting or missing closing tags.
HTML elements must be properly nested and closed according to the specifications outlined by the HTML standard. A stray start tag usually occurs when a block-level element like <div> is used in a context where only phrasing (inline) content is permitted, or if required closing tags (such as </li>, </tr>, or </td>) are missing, causing the parser to be out of sync.
Incorrect Example: div after closing the html tag
<!DOCTYPE html>
<html lang="">
<head>
<title>Test</title>
</head>
<body>
<p></p>
</body>
</html>
<div>
some extra content
</div>
In the above, the <div> at the bottom is not valid because it appears after closing the html tag.
Always close elements properly and place block-level elements like <div> only inside appropriate containers. If your issue occurs elsewhere, look for missing closing tags or incorrect placement of the <div> relative to tables, lists, or other structural elements.
Ready to validate your sites?
Start your free trial today.