[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