[wp-trac] [WordPress Trac] #65288: Use the semantic HTML <search> element in core search markup
WordPress Trac
noreply at wordpress.org
Tue May 26 22:59:54 UTC 2026
#65288: Use the semantic HTML <search> element in core search markup
-----------------------------+-----------------------------------------
Reporter: adamsilverstein | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: General | Version:
Severity: normal | Resolution:
Keywords: has-patch | Focuses: accessibility, performance
-----------------------------+-----------------------------------------
Changes (by sabernhardt):
* version: trunk =>
Old description:
> == Summary ==
>
> The HTML [https://developer.mozilla.org/en-
> US/docs/Web/HTML/Reference/Elements/search <search>] element is now part
> of [https://web.dev/baseline Baseline] and is supported in all evergreen
> browsers (Chrome 118+, Firefox 118+, Safari 17+, Edge 118+). It is a
> semantic landmark element that represents a group of search/filtering
> controls and has an implicit ARIA role of search.
>
> WordPress currently produces search markup by adding role="search" to the
> surrounding <form> in several places:
>
> get_search_form() in wp-includes/general-template.php (both the html5 and
> xhtml formats).
> The core/search block render callback in wp-includes/blocks/search.php.
> Bundled classic themes that override searchform.php (Twenty Sixteen,
> Twenty Seventeen, Twenty Twenty, Twenty Twenty-One).
> This ticket proposes updating core search markup and bundled themes to
> use the native <search> element, which removes the need for the explicit
> role="search" attribute and brings WordPress in line with current HTML
> semantics.
>
> == Background ==
>
> The <search> element was added to the HTML Living Standard to provide a
> dedicated semantic container for search functionality, similar to how
> <nav> covers navigation and <main> covers primary content. Per the HTML
> spec:
>
> ''The search element represents a part of a document or application that
> contains a set of form controls or other content related to performing a
> search or filtering operation.''
>
> Today, the equivalent semantics are conveyed by adding role="search" to
> the surrounding <form>. With the new element widely available, the role
> attribute can be dropped in favor of native markup.
>
> == Current state in core ==
>
> wp-includes/general-template.php (get_search_form(), html5 format):
>
> {{{ #!html
>
> Search for:
> Search …
>
> }}}
> wp-includes/blocks/search.php (render_block_core_search()):
>
> {{{ #!php sprintf( '<form role="search" method="get" action="%1s" %2s
> %3s>%4s', esc_url( home_url( '/' ) ), $wrapper_attributes,
> $form_directives, $label . $field_markup ); }}}
>
> Bundled themes with their own searchform.php follow the same <form
> role="search"> pattern:
>
> src/wp-content/themes/twentysixteen/searchform.php
> src/wp-content/themes/twentyseventeen/searchform.php
> src/wp-content/themes/twentytwenty/searchform.php
> src/wp-content/themes/twentytwentyone/searchform.php
> Newer block themes (Twenty Twenty-Two through Twenty Twenty-Five) inherit
> markup from the core/search block and need no theme-level change.
>
> == Proposal ==
>
> Wrap each search form in a <search> element and drop the now-redundant
> role="search" attribute on the inner <form>:
>
> {{{ #!html
>
> Search for:
>
> }}}
> For get_search_form(), the optional aria_label argument moves from the
> <form> to the new <search> landmark element, since the landmark is what
> assistive technology exposes.
>
> The xhtml fallback in get_search_form() is left unchanged because XHTML
> 1.x does not include the <search> element.
>
> Why drop role="search"? Keeping it on the inner <form> while the <search>
> wrapper also carries the implicit search role would produce nested search
> landmarks, which assistive technology may announce twice or report as a
> structural error. The HTML spec's intent is that <search> replaces the
> manual role.
>
> == Patch ==
>
> Patch and full test plan in the linked GitHub PR:
>
> [https://github.com/WordPress/wordpress-develop/pull/11913 wordpress-
> develop#11913] — General: Use the semantic <search> element in core
> search markup
> Two atomic commits:
>
> General: get_search_form() (html5) + core/search block.
> Bundled Themes: Twenty Sixteen, Twenty Seventeen, Twenty Twenty, Twenty
> Twenty-One searchform.php.
> == Backward compatibility ==
>
> The <form> element, its class="search-form", and all input markup are
> unchanged. Theme CSS targeting form.search-form or .wp-block-search
> continues to work.
> For the core/search block, block wrapper attributes (block class names,
> user-added classes) and Interactivity API directives remain on the <form>
> to preserve block CSS, hydration boundaries, and event handling.
> Browsers that pre-date <search> support treat it as a generic inline
> container with no landmark role. Forms still function and remain
> accessible via the <form> itself; the only loss is the explicit landmark
> announcement, which is no worse than the current state where
> role="search" is unsupported.
> Custom themes that override searchform.php are unaffected; this change
> only touches core defaults and bundled classic themes.
> The get_search_form and search_form_format filters continue to operate on
> the final HTML.
> == Accessibility ==
>
> <search> has the implicit ARIA role search, replacing the manual
> role="search".
> Screen readers that already announce the search landmark will continue to
> do so via the native element on supporting UAs.
> The aria_label argument now labels the <search> landmark directly, which
> is the standard pattern for distinguishing multiple search landmarks on
> the same page.
> == Tasks ==
>
> Patch get_search_form() (html5 format).
> Patch render_block_core_search().
> Patch bundled classic themes (Sixteen, Seventeen, Twenty, Twenty-One).
> Audit Twenty Twenty-Two through Twenty Twenty-Five for any inline search
> markup outside core/search.
> Update unit and E2E tests if any assert on role="search" markup (initial
> scan found none).
> Update developer documentation referencing <form role="search">.
> Confirm screen reader behavior across VoiceOver, NVDA, JAWS, and
> TalkBack on the patched markup.
> == Open questions ==
>
> Should we keep an explicit role="search" attribute on the <search>
> element for assistive technology that doesn't yet map <search> to the
> search landmark role? It would be redundant for compliant UAs but
> defensive for older AT during a transition period.
> Should the core/search block bump its apiVersion or expose a version flag
> so theme/block consumers can detect the markup change?
> Should the searchform.php change also be backported to Twenty Sixteen /
> Seventeen, given their long support tail, or limited to Twenty Twenty and
> later?
> == References ==
>
> MDN: [https://developer.mozilla.org/en-
> US/docs/Web/HTML/Reference/Elements/search HTML <search> element]
> HTML spec: [https://html.spec.whatwg.org/multipage/grouping-content.html
> #the-search-element 4.4.14 The search element]
> Baseline: [https://web.dev/baseline <search> is widely available]
> GitHub PR: [https://github.com/WordPress/wordpress-develop/pull/11913
> wordpress-develop#11913]
New description:
== Summary ==
The HTML [https://developer.mozilla.org/en-
US/docs/Web/HTML/Reference/Elements/search <search>] element is now part
of [https://web.dev/baseline Baseline] and is supported in all evergreen
browsers (Chrome 118+, Firefox 118+, Safari 17+, Edge 118+). It is a
semantic landmark element that represents a group of search/filtering
controls and has an implicit ARIA role of search.
WordPress currently produces search markup by adding `role="search"` to
the surrounding `<form>` in several places:
- `get_search_form()` in `wp-includes/general-template.php` (both the
`html5` and `xhtml` formats).
- The `core/search` block render callback in `wp-
includes/blocks/search.php`.
- Bundled classic themes that override `searchform.php` (Twenty Sixteen,
Twenty Seventeen, Twenty Twenty, Twenty Twenty-One).
This ticket proposes updating core search markup and bundled themes to use
the native `<search>` element, which removes the need for the explicit
`role="search"` attribute and brings WordPress in line with current HTML
semantics.
== Background ==
The `<search>` element was added to the HTML Living Standard to provide a
dedicated semantic container for search functionality, similar to how
`<nav>` covers navigation and `<main>` covers primary content. Per the
HTML spec:
> The search element represents a part of a document or application that
contains a set of form controls or other content related to performing a
search or filtering operation.
Today, the equivalent semantics are conveyed by adding `role="search"` to
the surrounding `<form>`. With the new element widely available, the
`role` attribute can be dropped in favor of native markup.
== Current state in core ==
`wp-includes/general-template.php` (`get_search_form()`, `html5` format):
{{{
<form role="search" aria-label="optional ARIA label" method="get" class
="search-form" action="https://example.org/">
<label>
<span class="screen-reader-text">Search for:</span>
<input type="search" class="search-field"
placeholder="Search …" value="search query" name="s" />
</label>
<input type="submit" class="search-submit" value="Search" />
</form>
}}}
`wp-includes/blocks/search.php` (`render_block_core_search()`):
{{{#!php
return sprintf(
'<form role="search" method="get" action="%1s" %2s
%3s>%4s</form>',
esc_url( home_url( '/' ) ),
$wrapper_attributes,
$form_directives,
$label . $field_markup
);
}}}
Bundled themes with their own `searchform.php` follow the same `<form
role="search">` pattern:
- `src/wp-content/themes/twentysixteen/searchform.php`
- `src/wp-content/themes/twentyseventeen/searchform.php`
- `src/wp-content/themes/twentytwenty/searchform.php`
- `src/wp-content/themes/twentytwentyone/searchform.php`
- Newer block themes (Twenty Twenty-Two through Twenty Twenty-Five)
inherit markup from the `core/search` block and need no theme-level
change.
== Proposal ==
Wrap each search form in a `<search>` element and drop the now-redundant
`role="search"` attribute on the inner `<form>`:
{{{
<search aria-label="optional ARIA label"><form method="get" class="search-
form" action="https://example.org/">
<label>
<span class="screen-reader-text">Search for:</span>
<input type="search" class="search-field"
placeholder="Search …" value="search query" name="s" />
</label>
<input type="submit" class="search-submit" value="Search" />
</form></search>
}}}
For `get_search_form()`, the optional `aria_label` argument moves from the
`<form>` to the new `<search>` landmark element, since the landmark is
what assistive technology exposes.
The `xhtml` fallback in `get_search_form()` is left unchanged because
XHTML 1.x does not include the `<search>` element.
Why drop `role="search"`? Keeping it on the inner `<form>` while the
`<search>` wrapper also carries the implicit search role would produce
nested search landmarks, which assistive technology may announce twice or
report as a structural error. The HTML spec's intent is that `<search>`
replaces the manual role.
== Patch ==
Patch and full test plan in the linked GitHub PR:
[https://github.com/WordPress/wordpress-develop/pull/11913 wordpress-
develop#11913] — General: Use the semantic `<search>` element in core
search markup
Two atomic commits:
General: `get_search_form()` (html5) + `core/search` block.
Bundled Themes: Twenty Sixteen, Twenty Seventeen, Twenty Twenty, Twenty
Twenty-One `searchform.php`.
== Backward compatibility ==
- The `<form>` element, its `class="search-form"`, and all input markup
are unchanged. Theme CSS targeting `form.search-form` or `.wp-block-
search` continues to work.
- For the `core/search` block, block wrapper attributes (block class
names, user-added classes) and Interactivity API directives remain on the
`<form>` to preserve block CSS, hydration boundaries, and event handling.
- Browsers that pre-date `<search>` support treat it as a generic inline
container with no landmark role. Forms still function and remain
accessible via the `<form>` itself; the only loss is the explicit landmark
announcement, which is no worse than the current state where
`role="search"` is unsupported.
- Custom themes that override `searchform.php` are unaffected; this change
only touches core defaults and bundled classic themes.
- The `get_search_form` and `search_form_format` filters continue to
operate on the final HTML.
== Accessibility ==
- `<search>` has the implicit ARIA role search, replacing the manual
`role="search"`.
- Screen readers that already announce the search landmark will continue
to do so via the native element on supporting UAs.
- The `aria_label` argument now labels the `<search>` landmark directly,
which is the standard pattern for distinguishing multiple search landmarks
on the same page.
== Tasks ==
- Patch `get_search_form()` (`html5` format).
- Patch `render_block_core_search()`.
- Patch bundled classic themes (Sixteen, Seventeen, Twenty, Twenty-One).
- Audit Twenty Twenty-Two through Twenty Twenty-Five for any inline search
markup outside `core/search`.
- Update unit and E2E tests if any assert on `role="search"` markup
(initial scan found none).
- Update developer documentation referencing `<form role="search">`.
- Confirm screen reader behavior across VoiceOver, NVDA, JAWS, and
TalkBack on the patched markup.
== Open questions ==
- Should we keep an explicit `role="search"` attribute on the `<search>`
element for assistive technology that doesn't yet map `<search>` to the
search landmark role? It would be redundant for compliant UAs but
defensive for older AT during a transition period.
- Should the `core/search` block bump its `apiVersion` or expose a version
flag so theme/block consumers can detect the markup change?
- Should the `searchform.php` change also be backported to Twenty Sixteen
/ Seventeen, given their long support tail, or limited to Twenty Twenty
and later?
== References ==
MDN: [https://developer.mozilla.org/en-
US/docs/Web/HTML/Reference/Elements/search HTML <search> element]
HTML spec: [https://html.spec.whatwg.org/multipage/grouping-content.html
#the-search-element 4.4.14 The search element]
Baseline: [https://web.dev/baseline <search> is widely available]
GitHub PR: [https://github.com/WordPress/wordpress-develop/pull/11913
wordpress-develop#11913]
--
--
Ticket URL: <https://core.trac.wordpress.org/ticket/65288#comment:12>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list