Skip to content

Development notes

Escape, backdrop clicks, and focus restoration in an avatar dialog

An avatar enlargement interaction separates the responsibilities of native modality, background clicks, closing paths, and focus restoration, with browser checks to confirm that clicking the image does not dismiss it.

林予晴
Published
  • HTML
  • Dialog
  • Keyboard interaction
  • Interaction testing

Enlarging an avatar in the center of the screen is not the hardest part of this interaction. What makes it complete is where keyboard focus goes after the image appears, whether clicking the image accidentally closes it, and where focus returns after Escape.

The about page on this site uses a native <dialog> to enlarge the avatar. For this note, I examined the opening and closing paths separately and tried the interaction in a local browser. I wanted to confirm more than whether the image appeared: readers should be able to enter from the original control and return to the same place.

Opening a modal takes more than adding open

The control for enlarging the avatar is a native button with an accessible name. When activated, the script first puts the image source and alt text for the avatar shown on the page into the dialog, then calls showModal().

This has different responsibilities from simply making a block visible. MDN explains that a dialog opened with showModal() behaves as a modal and makes outside content inert. A native modal also provides default dismissal with Escape.[1]

A visual overlay alone is therefore not enough to establish that something is a modal. The overlay is a presentation choice; keyboard and focus behavior need an actual implementation behind them.

The enlarged view currently contains only an image and a close button. In the check recorded here, opening it with Enter from the avatar button placed focus on the close control. MDN also explains focus handling for showModal(), but if more focusable content is added later, the appropriate initial focus position will need to be reconsidered. This result is not a focus-order rule for every dialog.[1]

Escape and the close button should share the same closing flow

This dialog does not add a separate Escape handler that intercepts all keystrokes. It retains the native modal’s default behavior, while the visible close button calls close().[1]

The two paths take different inputs but need the same final state: the dialog is no longer open, and focus can return to the enlargement control.

That is why focus restoration belongs in the dialog’s close event rather than only in the close button’s click handler. If restoration runs only through the button, Escape or another permitted closing method may bypass that handling.

I tested Escape and the close control separately in this round. Both closed the dialog and returned focus to the original avatar enlargement button. Checking both paths tells us more about the current division of responsibilities than checking just one.

Before closing on a background click, identify what was clicked

::backdrop can add a dark background behind a modal, but that CSS does not itself implement dismissal when clicking outside. This site’s background-click handling lives in the dialog’s click listener, which first checks:

if (event.target === dialog) dialog.close()

That condition matters. The image and close button are inside the dialog, and clicks can bubble outward. If every click received by the dialog closed it, clicking the image itself would dismiss it too.

There is also a layout detail to account for: the dialog element currently fills the viewport, with the image container in the center. A “background click” in this note means a click on the empty area of the dialog element itself. It is not a claim that native ::backdrop automatically provides outside-click dismissal. The event target and the area covered by each element need to be considered together.

In the local check, I clicked both the center of the image and an empty area in a corner of the viewport. The former kept the dialog open; the latter closed it and returned focus to the avatar control. Both locations need checking. Otherwise, it is easy to confirm that the dialog can close while missing the places where it should stay open.

Restore focus to the starting point rather than guessing a destination

Before opening, the script records the current document.activeElement. When the dialog closes, it sends focus back to that recorded element.

For this interaction, opening from the avatar button means returning to the same button after closing. Readers do not have to find their previous position again from the beginning of the page.

That does not mean every complex dialog needs only the same approach. If the trigger is removed after the interaction, becomes unfocusable, or should lead into the next step of a task after closing, a separate focus destination needs to be defined. These are possible future design situations, not features this site already handles.

What the current checks establish is the case where the original control remains available. I also pressed Tab once, and focus remained inside this modal. That observation does not replace acceptance testing of every focus-cycling path, screen readers, or mobile assistive interaction.

The enlarged content should match the image on the page

The about page now keeps one avatar image, so enlarging it shows that same image.

The script copies both src and alt from that one image. The alt text is not maintained separately for the enlarged view; it reuses the description attached to the image on the page.

In this round, I enlarged the avatar and confirmed that the dialog’s image source and alt text matched the image on the page. This proves only that the two presentations used the same data in that interaction. It does not mean the image description itself has passed every accessibility review.

Image purpose, dimensions, and loading failures have separate responsibilities, discussed in Why alt text, image dimensions, loading, and failure states need to be designed together. This note focuses on entering and leaving the enlarged view once the image is already present.

Paths exercised in this round

This round used a local headless Edge browser on Windows to interact with the about page through browser input events. It did not call the product’s opening or closing handlers directly as a substitute for clicking.

Action Result confirmed in this round
Press Enter with focus on the avatar control The dialog opened, and focus moved to the close button
Press Escape The dialog closed, and focus returned to the avatar control
Click the image content The dialog stayed open
Press Tab once inside the modal Focus remained inside the dialog
Click the close button The dialog closed, and focus returned to the avatar control
Click an empty background area of the dialog The dialog closed, and focus returned to the avatar control
Enlarge the avatar The enlarged image’s source and alt text matched the image on the page
Navigate away, then return through browser history This return used BFCache; enlargement, Escape, and focus restoration still worked

This was a single local functional observation, not subjective visual acceptance. It did not cover all browsers, repeated rounds of history navigation, or assistive technology. Without JavaScript, the original avatar and introduction content remain, but this enlargement behavior requires a script. Readable static content does not establish that the interaction works without scripts too.

For a small interaction like this, I include where focus returns after closing in the completion criteria, rather than stopping at whether something appears when clicked. The image appearing is only the middle of the interaction.

Sources

[1] https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog