Skip to content

Visibility

Track whether the host element is visible in the viewport using the Intersection Observer API.

Why use this atom?

  • Reactive isVisible and ratio signals powered by signality's elementVisibility()
  • Exposes data-visible and data-hidden attributes for CSS-only styling
  • Configurable threshold and root margin
  • SSR-safe with automatic cleanup
  • No manual IntersectionObserver boilerplate

Import

ts
import {AtomVisibility} from '@terse-ui/atoms/visibility';

Usage

html
<img atomVisibility (atomVisibility)="loadImage()">

When the element enters the viewport, data-visible is set and data-hidden is removed. When it leaves, the reverse happens.

Lazy loading

html
<div atomVisibility #vis="atomVisibility">
  @if (vis.isVisible()) {
    <heavy-component />
  }
</div>

Scroll-triggered animations

css
[atomVisibility][data-visible] {
  animation: fadeIn 0.3s ease-out;
}

[atomVisibility][data-hidden] {
  opacity: 0;
}

Threshold and root margin

html
<!-- Trigger when 50% visible -->
<div atomVisibility [atomVisibilityThreshold]="0.5">...</div>

<!-- Expand detection area by 100px -->
<div atomVisibility atomVisibilityRootMargin="100px">...</div>

As a host directive

ts
@Directive({
  selector: '[lazyLoad]',
  hostDirectives: [AtomVisibility],
})
export class LazyLoad {
  readonly #vis = inject(AtomVisibility);
  readonly shouldLoad = computed(() => this.#vis.isVisible());
}

API Reference

AtomVisibility

Selector[atomVisibility]
Exported asatomVisibility
Data attributesdata-visible, data-hidden

Inputs

InputTypeDefaultDescription
atomVisibilityThresholdnumber | number[]Intersection threshold(s). Read once at initialization.
atomVisibilityRootMarginstringRoot margin for the observer. Read once at initialization.
atomVisibilityDisabledbooleanDisables visibility observation and data attributes.

Outputs

OutputTypeDescription
atomVisibilityDisabledChangebooleanDisables visibility observation and data attributes.

Properties

PropertyTypeDescription
visibilitySignal<ElementVisibilityValue> (readonly)Raw signality visibility signal.
isVisibleSignal<boolean> (readonly)Whether the element is currently visible in the viewport.
ratioSignal<number> (readonly)Intersection ratio of the element within the viewport.

Released under the MIT License.