From 540ac7a1309b59bd41c8a54479fee9e216996566 Mon Sep 17 00:00:00 2001 From: adamsilverstein Date: Thu, 21 May 2026 16:29:53 -0700 Subject: [PATCH 1/2] General: Add opt-in `` element support to the core search form. The HTML `` element is in Baseline and carries an implicit ARIA landmark role of `search`, expressing natively what `get_search_form()` currently does with a manual `role="search"` attribute. Adopting it unconditionally is not back-compatible: wrapping the `
` in a new element breaks direct-child CSS selectors (e.g. `.search-container > form`) and reparents the form for flex/grid layouts, dropping `role="search"` breaks `form[role="search"]` selectors, and keeping the role alongside the wrapper produces nested, double-announced search landmarks. Make the wrapper opt in instead: - Add a `search-element` theme support feature. Themes that have audited their CSS declare `add_theme_support( 'search-element' )` to enable it. - Add a `wrap_in_search` argument to `get_search_form()`, defaulting to `current_theme_supports( 'search-element' )`. The `search_form_args` filter can toggle it site-wide, and a per-call value overrides both. When enabled (html5 format only), the form is wrapped in ``, `role="search"` is dropped to avoid a nested landmark, and any `aria_label` names the `` element. The default output, the xhtml fallback, and the bundled classic themes are left unchanged. Add unit tests covering the default and wrapped markup, aria-label placement, the xhtml fallback, the filter, and the theme-support default. See #65288. --- src/wp-includes/general-template.php | 41 +++- src/wp-includes/theme.php | 3 + tests/phpunit/tests/general/getSearchForm.php | 202 ++++++++++++++++++ 3 files changed, 239 insertions(+), 7 deletions(-) create mode 100644 tests/phpunit/tests/general/getSearchForm.php diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index 34233c35b0cc3..a3fafb2e11161 100644 --- a/src/wp-includes/general-template.php +++ b/src/wp-includes/general-template.php @@ -227,14 +227,21 @@ function get_template_part( $slug, $name = null, $args = array() ) { * * @since 2.7.0 * @since 5.2.0 The `$args` array parameter was added in place of an `$echo` boolean flag. + * @since 7.1.0 Added the `$wrap_in_search` argument and the `search-element` theme support + * feature to wrap the form in a `` element. * * @param array $args { * Optional. Array of display arguments. * - * @type bool $echo Whether to echo or return the form. Default true. - * @type string $aria_label ARIA label for the search form. Useful to distinguish - * multiple search forms on the same page and improve - * accessibility. Default empty. + * @type bool $echo Whether to echo or return the form. Default true. + * @type string $aria_label ARIA label for the search form. Useful to distinguish + * multiple search forms on the same page and improve + * accessibility. Default empty. + * @type bool $wrap_in_search Whether to wrap the form in a semantic HTML `` + * landmark element and drop the now-redundant `role="search"` + * attribute on the form. Only applies to the 'html5' format. + * Defaults to true when the theme declares support for the + * 'search-element' feature, false otherwise. * } * @return void|string Void if 'echo' argument is true, search form HTML if 'echo' is false. */ @@ -269,8 +276,9 @@ function get_search_form( $args = array() ) { // Defaults are to echo and to output no custom label on the form. $defaults = array( - 'echo' => $echo, - 'aria_label' => '', + 'echo' => $echo, + 'aria_label' => '', + 'wrap_in_search' => current_theme_supports( 'search-element' ), ); $args = wp_parse_args( $args, $defaults ); @@ -321,7 +329,26 @@ function get_search_form( $args = array() ) { $aria_label = ''; } - if ( 'html5' === $format ) { + if ( 'html5' === $format && $args['wrap_in_search'] ) { + /* + * Wrap the form in a landmark element. The implicit ARIA role + * of provides the search landmark, so role="search" is omitted + * from the form to avoid nesting two identical landmarks. Any aria-label + * names the landmark instead of the form. + */ + $search_label = $args['aria_label'] ? ' aria-label="' . esc_attr( $args['aria_label'] ) . '"' : ''; + + $form = ' + + + '; + } elseif ( 'html5' === $format ) { $form = '