kliping.pro
  • Docs
  • Explore
  • Builder
  • Directory
  • Colors
  • Typeset
Saved
Hooks
  • Getting Started2
  • State7
  • Advanced6
  • Lifecycle16
  • Browser21
  • useActiveElement
  • useBattery
  • useClickAnyWhere
  • useClickAway
  • useClipboard
  • useDocumentVisibility
  • useElementSize
  • useEventListener
  • useFps
  • useFullscreen
  • useHash
  • useHover
  • useInViewport
  • useIsMatchMedia
  • useIsOnline
  • useMouse
  • useNetwork
  • useOs
  • useScrollLock
  • useTextSelection
  • useTitle
  • Development1
  • Third-Party4
  • Libraries4
  1. Hooks
  2. Browser
  3. useInViewport

useInViewport

PreviousNext

Apakah sebuah elemen sedang terlihat di layar.

IntersectionObserver, bukan menghitung posisi saat scroll. Bedanya bukan gaya: menghitung posisi berarti bekerja di setiap peristiwa scroll, di utas utama, untuk setiap elemen yang dipantau. IntersectionObserver dikerjakan peramban di luar itu dan cuma memanggil balik saat keadaannya benar-benar berubah.

Ini yang dipakai untuk memuat gambar saat mendekat, menandai bagian aktif di daftar isi, dan memuat halaman berikutnya saat dasar daftar tersentuh.

Installation ​

pnpm dlx kliping@latest add use-in-viewport

Ikut terpasang sendiri: target.

Salin dulu target — masing-masing memuat sumbernya di halamannya sendiri — lalu tempel berkas ini.

ts
import { getCurrentScope, onScopeDispose, ref, watch } from 'vue'
import { getTargetElement } from '@/lib/target'
import type { BasicTarget } from '@/lib/target'

export interface UseInViewportOptions {
  /** Margin around the root, as CSS (e.g. `"0px 0px -20% 0px"`); grows or shrinks the visible area. */
  rootMargin?: string
  /** Visible fraction (0–1), or list of fractions, at which `ratio` updates. */
  threshold?: number | number[]
  /** Element treated as the "screen". Leave empty for the viewport. */
  root?: BasicTarget
  /** Called with each IntersectionObserver entry. */
  callback?: (entry: IntersectionObserverEntry) => void
}

export function useInViewport(
  target: BasicTarget | BasicTarget[],
  options: UseInViewportOptions = {},
) {
  const { rootMargin, threshold, root, callback } = options

  const inViewport = ref<boolean | undefined>(undefined)
  const ratio = ref<number | undefined>(undefined)

  let observer: IntersectionObserver | undefined

  const teardown = () => {
    observer?.disconnect()
    observer = undefined
  }

  const stopWatch = watch(
    () => {
      const targets = Array.isArray(target) ? target : [target]
      return targets.map((t) => getTargetElement(t))
    },
    (elements) => {
      teardown()

      const present = elements.filter(Boolean) as Element[]
      if (!present.length || typeof IntersectionObserver === 'undefined') return

      observer = new IntersectionObserver(
        (entries) => {
          for (const entry of entries) {
            ratio.value = entry.intersectionRatio
            inViewport.value = entry.isIntersecting
            callback?.(entry)
          }
        },
        {
          rootMargin,
          threshold,
          root: (getTargetElement(root) as Element | null) ?? null,
        },
      )

      for (const el of present) observer.observe(el)
    },
    { immediate: true, flush: 'post' },
  )

  const stop = () => {
    teardown()
    stopWatch()
  }

  if (getCurrentScope()) onScopeDispose(stop)

  return {
    /** Whether the target is in view; `undefined` until first observed. Reactive. */
    inViewport,
    /** Visible fraction of the target, 0–1. Reactive. */
    ratio,
    /** Stops observing. */
    stop: stop,
  }
}

Requirements ​

RequirementValue
ProjectVue 3.5+, alias @ — disiapkan kliping init
Kliping itemstarget
Filescomposables/use-in-viewport.ts

API Reference ​

ts
export interface UseInViewportOptions {
  /** Margin around the root, as CSS (e.g. `"0px 0px -20% 0px"`); grows or shrinks the visible area. */
  rootMargin?: string
  /** Visible fraction (0–1), or list of fractions, at which `ratio` updates. */
  threshold?: number | number[]
  /** Element treated as the "screen". Leave empty for the viewport. */
  root?: BasicTarget
  /** Called with each IntersectionObserver entry. */
  callback?: (entry: IntersectionObserverEntry) => void
}

export function useInViewport(
  target: BasicTarget | BasicTarget[],
  options: UseInViewportOptions = {},
)

Parameters ​

ParameterTypeDefaultDescription
targetBasicTarget | BasicTarget[]—Element, or list of elements, to observe.
options?UseInViewportOptions{}Observer settings.
options.rootMargin?string—Margin around the root, as CSS (e.g. "0px 0px -20% 0px"); grows or shrinks the visible area.
options.threshold?number | number[]—Visible fraction (0–1), or list of fractions, at which ratio updates.
options.root?BasicTarget—Element treated as the "screen". Leave empty for the viewport.
options.callback?((entry: IntersectionObserverEntry) => void)—Called with each IntersectionObserver entry.

Returns ​

PropertyTypeDescription
inViewportRef<boolean | undefined, boolean | undefined>Whether the target is in view; undefined until first observed. Reactive.
ratioRef<number | undefined, number | undefined>Visible fraction of the target, 0–1. Reactive.
stop() => voidStops observing.

Credits ​

Berasal dari shadcn-hooks (MIT, Copyright (c) 2025 Brendan Dash). Bentuk API-nya dari ahooks lewat shadcn-hooks. Rantai lengkapnya di Credits.

PrevioususeHoverNext useIsMatchMedia

On This Page

InstallationRequirementsAPI ReferenceParametersReturnsCredits

© 2026 Kliping. Free components are open source under the MIT License.

LicenseCreditsRoadmap