Make WordPress Core

Opened 5 weeks ago

Closed 4 weeks ago

#65660 closed defect (bug) (fixed)

Tooltip is in a `div`, but inserted inside a `p` on the login screen

Reported by: joedolson Owned by: joedolson
Priority: normal Milestone: 7.1
Component: General Version:
Severity: normal Keywords: tooltips has-patch has-unit-tests commit
Cc: Focuses: ui, javascript

Description

The div element is not permitted inside a p, and browser rendering breaks the layout, causing an extra gap under the paragraph before the login button.

In the original output, this div was a span, which was allowed here; but adding the toggletip support changed the allowed nesting for tooltips.

This means that toggletips can't be nested inside paragraphs, which could be a problem down the line, and may need to be adjusted in the function.

Attachments (1)

Screenshot 2026-07-17 152030.png (11.4 KB ) - added by joedolson 5 weeks ago.
Login screenshot excess gap

Download all attachments as: .zip

Change History (5)

@joedolson
5 weeks ago

Login screenshot excess gap

#1 @solankisoftware
5 weeks ago

I checked the current login page markup and couldn't reproduce the reported issue. The #caps-warning element is rendered inside the .wp-pwd <div>, not inside a <p> element, so the HTML appears to be valid.

<div class="wp-pwd">
    ...
    <div id="caps-warning" class="caps-warning">...</div>
</div>

I don't see any <div> being inserted inside a <p> on the login screen. Could you please share the steps to reproduce this issue or indicate which branch/changeset the invalid markup is occurring on?

This ticket was mentioned in PR #12592 on WordPress/wordpress-develop by @khokansardar.


4 weeks ago
#2

  • Keywords has-patch has-unit-tests added; needs-patch removed

## Problem

wp_get_tooltip_helper() (added in 7.1.0, powering wp_get_tooltip() and wp_get_toggletip()) wraps its output in a <div>, and for toggletips uses a <dialog> element. Both are *flow content*, not *phrasing content*.

When that markup is placed inside a <p> — as it is for the "Remember Me" field on the login form (wp_get_toggletip() inside <p class="forgetmenot">) — the HTML parser applies its "close a p element" rule on the <div>/<dialog> start tag. This:

  1. Auto-closes the paragraph, moving the tooltip out to become a sibling of the <form>, and
  2. Leaves a stray empty <p></p> behind (from the literal </p> in the source), whose default margins produce the extra gap reported under the Remember Me row.

Before the toggletip feature landed the wrapper was a <span> (valid phrasing content), so this is a 7.1-only regression.

### Reproduction
Load wp-login.php. Inspect the DOM around p.forgetmenot: it contains only the checkbox + label, the .wp-tooltip element is a direct child of <form>, and an empty <p></p> sits between it and p.submit, adding a visible gap before the Log In button.

## Fix

Build the markup from phrasing content only so it is valid wherever it's used, including inside a paragraph:

  • <div> wrapper → <span> for both tooltips and toggletips (the CSS is already display: inline-flex).
  • Toggletip <dialog popover="auto" autofocus><span popover="auto" role="dialog" aria-label="…" tabindex="-1" autofocus>. The Popover API works on any element; role="dialog" + tabindex="-1" + autofocus reproduce the native dialog's accessible name and "focus moves into the popover on open" behavior. Escape / light-dismiss / the close button are all driven by popover="auto" and are unchanged.

Also updates the wp-tooltip.js JSDoc type (HTMLDivElementHTMLSpanElement) to match the new wrapper.

## Testing

Verified on the local Docker environment (wp-login.php):

  • p.forgetmenot now contains the toggletip; zero empty paragraphs; Remember Me and Log In align on one row.
  • Toggletip opens, is anchored above its toggle with the arrow, shows the close button, and dismisses correctly.
  • On open, focus moves onto the bubble — identical to the previous native <dialog autofocus>.
  • Escape/light-dismiss behavior confirmed equivalent to a native <dialog popover="auto"> (differential check).

Automated:

  • Tests_General_wpGetTooltipOK (9 tests, 27 assertions), including new @ticket 65660 regression tests asserting the output contains no <div>/<dialog> and that the toggletip bubble uses role="dialog" with tabindex="-1" autofocus.
  • PHPCS (phpcs.xml.dist) → 0 errors on the changed files.

## Notes for reviewers

  • The second commit removes an unused attributes default from wp_get_tooltip_helper() (never read, undocumented, no caller passes it). It's isolated so it can be dropped independently if you'd prefer to keep this PR strictly scoped to the layout bug.

Trac ticket: https://core.trac.wordpress.org/ticket/65660

## Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 4.8
Used for: Generate test cases and all implementation and tests were reviewed and edited by me.

#3 @joedolson
4 weeks ago

  • Keywords commit added

#4 @joedolson
4 weeks ago

  • Resolutionfixed
  • Status assignedclosed

In 62800:

Administration: Update tooltip markup with phrasing elements.

Using sectioning elements (div and dialog) inside the generated markup meant that the function couldn't be used inside a p element, because sectioning elements aren't valid HTML inside p. To make the function more useful as a general utility, use only span and button elements to build the content, avoiding browser parser breaking behavior.

Developed in https://github.com/WordPress/wordpress-develop/pull/12592

Props joedolson, khokansardar.
Fixes #65660.

Note: See TracTickets for help on using tickets.