Available since v0.1.0

fs-assert-visible

Stable

Resolves when an element matching the selector exists in the DOM AND has non-zero layout dimensions. Query-based — runs a point-in-time querySelector and layout check, not a mutation watch.

Syntax

fs-assert-visible="<selector>"
fs-assert-visible="<selector>[modifier=value]..."

When to use it

  • The target element exists in the DOM but is currently hidden (modal overlay, tab panel, collapsed drawer) and the action should reveal it
  • Verifying a mount-triggered element has layout
  • Invariant-triggered "should always be visible" contracts

If the element doesn't exist yet and will be created, use added. If you need to catch the exact moment of a state change (rather than the current state), use updated.

Example

<button
  fs-assert="tabs/switch-settings"
  fs-trigger="click"
  fs-assert-visible=".tab-content[data-tab='settings']">
  Settings
</button>

Passes when the settings panel has non-zero layout dimensions after the click.

Resolves immediately on current state

visible passes as soon as the query returns a match AND the match has dimensions. If the current state already satisfies the assertion at trigger time, it passes immediately — unlike added, which waits for a mutation.

This makes visible a good fit for OOB and invariant: both evaluate against the current DOM and don't need to witness a new mutation.

What "has layout dimensions" means

The agent checks offsetWidth > 0 && offsetHeight > 0. This catches:

  • display: none (fails)
  • visibility: hidden (fails — dimensions are 0)
  • Element detached from DOM (fails — query doesn't match)
  • Zero-size element via CSS (fails)

It does not check:

  • opacity: 0 (still has dimensions — passes)
  • Off-screen positioning (still has dimensions — passes)
  • Occluded by another element (still has dimensions — passes)

For precise visibility semantics, layer a [classlist=visible:true] or [data-state=open] check on top.

Pairs well with

Gotchas

  • Short-lived elements. If the element is created AND destroyed within the timeout window, visible can miss it — the query only runs at creation time and in response to mutation batches. Use added for elements with short lifetimes.
  • Using visible when added is correct. If the element is conditionally rendered (not in the DOM until the action), visible will pass as soon as the query matches, but the timing may be fragile. added is more precise.
  • CSS animations and transitions. An element that animates from opacity: 0 to opacity: 1 is "visible" the whole time — it had dimensions throughout the transition. Use a [classlist=...] or [aria-hidden=false] modifier if you need the animation endpoint.

See also