# How to Check the State of an Element in Ego-Browser: Visibility, Enabled, and Checked Status

> Learn how to check element state like visibility, enabled, and checked status in Ego-Browser using simple helper functions. Query DOM state effortlessly with Ego-Lite.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-21

---

**Ego-Browser provides high-level helper functions `isVisible`, `isEnabled`, and `isChecked` that query DOM state through the Chrome DevTools Protocol without requiring raw CDP commands.**

When automating browser interactions with `citrolabs/ego-lite`, you frequently need to verify that elements are ready for interaction. The library exposes a set of purpose-built helpers in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) that allow you to check the state of an element—whether it is visible, enabled, or checked—using a unified resolution pipeline that handles retries and error classification automatically.

## Checking Element Visibility

To determine if an element is actually rendered and visible to the user, Ego-Browser offers two complementary approaches. The `waitForSelector` method in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) accepts an `options.state` parameter that you can set to `"visible"` to block until the element enters the viewport and is not hidden by CSS.

Internally, this visibility check relies on the element resolution logic in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts). The engine attempts to extract the box model of the node; if the element lacks a box model (indicating it is not yet rendered or is hidden), the system throws a transient `ElementResolutionError` and retries according to the configured timeout.

For immediate queries without waiting, use the `isVisible` helper:

```typescript
// Wait until the button is actually visible
await page.waitForSelector('button.submit', { state: 'visible' });

// Or check visibility state immediately
const visible = await page.isVisible('button.submit');

```

## Verifying Enabled and Disabled States

Once an element is located, you can verify whether it is interactive using the `isEnabled` helper defined in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts). This function evaluates the `disabled` property of the underlying DOM node via a JavaScript snippet executed through `Runtime.evaluate`.

If the `disabled` property exists and is truthy, `isEnabled` returns `false`; otherwise, it returns `true`. This works consistently for form controls like inputs, buttons, and select elements.

```typescript
const enabled = await page.isEnabled('#username');
if (!enabled) {
  throw new Error('Username field is disabled');
}

```

## Checking Checked State for Checkboxes and Radio Buttons

For toggle controls such as checkboxes and radio buttons, the `isChecked` helper (also located in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts)) reads the `checked` property of the element. The helper accepts any selector that resolves to an `<input type="checkbox">` or `<input type="radio">` and returns a boolean indicating the current state.

```typescript
const checked = await page.isChecked('input[name="agree"]');
console.log('Agree checkbox is', checked ? 'checked' : 'unchecked');

```

## Understanding the Shared Resolution Pipeline

All state-checking helpers share a common execution path defined in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts). First, `parseLocator` parses the selector string. Then, `resolveElementObjectId` converts the node reference into a Chrome DevTools Protocol (CDP) `objectId`. Finally, the helper executes a targeted JavaScript snippet via `Runtime.evaluate` to read the specific property (`disabled`, `checked`, or box model data).

This architecture ensures that all queries respect the single-source-of-truth ref map and automatically retry when encountering temporary conditions, such as an element that has not yet finished rendering.

## Summary

- **Visibility**: Use `waitForSelector` with `{ state: 'visible' }` or the `isVisible` helper, which validates the box model via [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) to confirm the element is rendered and not CSS-hidden.
- **Enabled State**: Call `isEnabled` from [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) to evaluate the `disabled` property of the DOM node.
- **Checked State**: Call `isChecked` from [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) to read the `checked` property on checkbox and radio inputs.
- **Unified Pipeline**: All helpers rely on `parseLocator` and `resolveElementObjectId` in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) to translate selectors into CDP object IDs before querying state.

## Frequently Asked Questions

### How does Ego-Browser determine if an element is visible?

Ego-Browser checks visibility by attempting to extract the element's box model through the CDP. If [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) cannot retrieve a box model for the node, the element is considered not visible and the system may throw an `ElementResolutionError` for retry logic, or return `false` for immediate checks.

### Can I check the state of an element that was previously stored as a reference?

Yes. All helpers accept ref identifiers (such as `@N`) in addition to CSS selectors. The resolution pipeline in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) looks up the ref in the internal map before querying the browser, allowing you to check state on cached element references efficiently.

### What happens if I call `isEnabled` on a non-form element?

The `isEnabled` helper evaluates the `disabled` property regardless of tag name. For elements that do not support the `disabled` attribute (like a `<div>`), the property will be undefined or falsy, causing the helper to return `true` by default.

### Is there a performance difference between `waitForSelector` and `isVisible`?

Yes. `waitForSelector` in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) implements a polling mechanism with configurable timeouts, making it suitable for waiting on dynamic content. `isVisible` performs a single immediate check via `Runtime.evaluate`, which is faster but does not wait for the element to appear.