Docs/Primitives/createInView

createInView

Returns a boolean accessor that changes when the target enters or leaves the viewport or a custom root. Use whileInView for visual state on a motion.* element; use createInView when the visibility state needs to drive other logic.

import { createInView } from 'motion-solidjs'
import { createSignal, createEffect } from 'solid-js'

function Section() {
  const [el, setEl] = createSignal<HTMLElement | null>(null)
  const inView = createInView(el, { amount: 0.5, once: true })

  createEffect(() => {
    if (inView()) trackImpression()
  })

  return <section ref={setEl}>{/* content */}</section>
}
createInView
↓ keep scrolling
out of view
↑ keep scrolling
scroll to test
create-in-view.tsxOpen ↗
import { createInView } from 'motion-solidjs'
import { createSignal } from 'solid-js'

export const meta = {
  slug: 'create-in-view',
  title: 'createInView',
  category: 'scroll',
  description:
    'A boolean accessor — flip any UI from the imperative IntersectionObserver primitive.',
  tag: 'createInView',
} as const

export default function UseInViewExample() {
  const [container, setContainer] = createSignal<HTMLDivElement | null>(null)
  const [target, setTarget] = createSignal<HTMLDivElement | null>(null)

  const isInView = createInView(target, () => ({
    root: container() ?? undefined,
    amount: 0.6,
  }))

  return (
    <div class="flex flex-col items-center gap-3">
      <div
        ref={setContainer}
        class="scrollbar-thin relative h-56 w-52 overflow-y-scroll rounded-2xl border border-border-strong bg-white shadow-soft"
      >
        <div class="flex h-72 items-end justify-center pb-3 font-mono text-[10px] text-fg-dim">
          ↓ keep scrolling
        </div>
        <div class="px-3">
          <div
            ref={setTarget}
            class="grid h-24 place-items-center rounded-xl text-xs font-semibold text-white shadow-glow transition-colors duration-300"
            classList={{
              'bg-grad-mint': isInView(),
              'bg-grad-rose': !isInView(),
            }}
          >
            {isInView() ? 'in view' : 'out of view'}
          </div>
        </div>
        <div class="flex h-72 items-start justify-center pt-3 font-mono text-[10px] text-fg-dim">
          ↑ keep scrolling
        </div>
      </div>
      <span class="rounded-full border border-border bg-white px-3 py-1 text-[10px] font-mono text-fg-dim">
        scroll to test
      </span>
    </div>
  )
}

Options

  • root - accessor returning the scroll root
  • margin - IntersectionObserver root margin
  • amount - 'some' | 'all' | number (0-1), controlling how much must be visible
  • once - stop observing after the first entry