Element Visibility
useElementVisibility(target, options?) — reactive IntersectionObserver-backed visibility of an element. SSR-safe: observation starts once target resolves to a real element on the client.
function useElementVisibility(
target: MaybeRefOrGetter<HTMLElement | null | undefined>,
options?: UseElementVisibilityOptions,
): UseElementVisibilityReturnEvery call shares one module-level createVisibilityEngine() instance — consistent with the engine's own pooled-observer design.
Options
threshold
number | number[] · default: viewportDefaults.threshold (0 unless overridden)
rootMargin
string · default: viewportDefaults.rootMargin ('0px' unless overridden)
root
MaybeRefOrGetter<HTMLElement | null | undefined> · default: null
once
boolean · default: false
onEnter
(info: IntersectionInfo) => void · default: —
onLeave
(info: IntersectionInfo) => void · default: —
threshold/rootMargin fall back to the package-wide viewportDefaults object rather than a hardcoded 0/'0px' — see setViewportDefaults() below, and Nuxt Module for how it's typically set at the app level.
Return value
isVisible
Ref<boolean>
ratio
Ref<number>
The element's current intersectionRatio.
Example:
<script setup lang="ts">
import { ref } from 'vue'
import { useElementVisibility } from '@macrulez/inview-vue'
const card = ref<HTMLElement | null>(null)
const { isVisible } = useElementVisibility(card, { threshold: 0.5, once: true })
</script>
<template>
<div ref="card" :class="{ 'is-visible': isVisible }">...</div>
</template>Re-observes automatically whenever target or options.root change.
Global Defaults
setViewportDefaults() / viewportDefaults — package-wide defaults for this composable's threshold/rootMargin, overridable once at the app level instead of passing the same options to every call site.
interface ViewportDefaults {
threshold: number | number[]
rootMargin: string
}
const viewportDefaults: ViewportDefaults // { threshold: 0, rootMargin: '0px' }
function setViewportDefaults(overrides: Partial<ViewportDefaults>): voidsetViewportDefaults() only overwrites the fields you actually pass — it merges into the shared viewportDefaults object rather than replacing it. This is exactly what @macrulez/inview-nuxt calls under the hood from its module options.