Skip to main content

Installation

npx shadcn-svelte@latest add lens

Usage

<script lang="ts">
  import Lens from "$lib/components/magic/lens/lens.svelte";
</script>

<Lens>
  <img src="/image.jpg" alt="Zoomable image" />
</Lens>

Props

children
Snippet
required
The content to be zoomed. Typically an image, video, or any HTML element.
class
string
Additional CSS classes to apply to the container.
zoomFactor
number
default:"1.3"
The magnification factor for the zoomed area. Must be greater than 1.
lensSize
number
default:"170"
Diameter of the lens in pixels. Must be greater than 0.
position
Position
Controlled position of the lens. Used for external position control.
interface Position {
  x: number;
  y: number;
}
defaultPosition
Position
Default position where the lens appears when not hovering. When set, the lens is always visible.
isStatic
boolean
default:"false"
When true, the lens remains at a fixed position and doesn’t follow the mouse.
duration
number
default:"0.1"
Duration of the lens entrance/exit animation in seconds.
lensColor
string
default:"'black'"
Color of the lens mask. Can be any valid CSS color.
ariaLabel
string
default:"'Zoom Area'"
Accessible label for the lens region.

Examples

Basic Image Zoom

<Lens>
  <img 
    src="/product.jpg" 
    alt="Product" 
    class="w-full h-auto"
  />
</Lens>

Higher Zoom Factor

<Lens zoomFactor={2.5} lensSize={200}>
  <img src="/detailed-artwork.jpg" alt="Artwork" />
</Lens>

Static Lens Position

<Lens 
  isStatic 
  position={{ x: 200, y: 150 }}
  zoomFactor={2}
>
  <img src="/map.jpg" alt="Map" />
</Lens>

Default Position (Always Visible)

<Lens 
  defaultPosition={{ x: 150, y: 150 }}
  lensSize={120}
>
  <img src="/diagram.jpg" alt="Diagram" />
</Lens>

Custom Lens Color

<Lens lensColor="white" zoomFactor={1.8}>
  <img src="/dark-image.jpg" alt="Dark image" />
</Lens>

With Video Content

<Lens zoomFactor={1.5}>
  <video controls autoplay muted loop>
    <source src="/video.mp4" type="video/mp4" />
  </video>
</Lens>

Custom Animation Duration

<Lens duration={0.3} zoomFactor={2}>
  <img src="/photo.jpg" alt="Photo" />
</Lens>

Keyboard Support

  • Escape: Hides the lens when hovering

How It Works

  1. The component creates a masked overlay layer
  2. The overlay contains a scaled copy of the children
  3. The mask follows the mouse cursor (or stays at a fixed position)
  4. CSS transforms handle the zoom effect
  5. AnimatePresence provides smooth entrance/exit animations

Features

  • Smooth mouse-following lens effect
  • Customizable zoom level and lens size
  • Static and dynamic positioning modes
  • Default position for always-visible lens
  • Keyboard accessibility (Escape to dismiss)
  • Works with images, videos, and any HTML content
  • Smooth animations with configurable duration
  • Proper focus management
  • Validates props to prevent invalid configurations

Accessibility

  • The container has role="region" for semantic structure
  • Custom aria-label support for better screen reader experience
  • Keyboard navigation with Escape key
  • Focusable with tabindex="0"

Performance Tips

  • For large images, consider using optimized image formats (WebP, AVIF)
  • Use appropriate zoomFactor values (1.3-2.5 is typically sufficient)
  • Keep lensSize reasonable (100-300px) for best performance
  • The component uses CSS transforms for GPU-accelerated rendering

Build docs developers (and LLMs) love