UNPKG

react-lazy-img-observer

Version:

A React component for lazy loading images with Intersection Observer

421 lines (304 loc) 16.3 kB
# 📷 ImageLazy (v1.5.0) ![npm](https://img.shields.io/npm/v/react-lazy-img-observer) ![downloads](https://img.shields.io/npm/dw/react-lazy-img-observer) ![license](https://img.shields.io/npm/l/react-lazy-img-observer) --- **ImageLazy** is a lightweight and customizable React component for lazy loading images using the Intersection Observer API. It includes fallback handling, visual effects, and support for custom loaders and transitions perfect for performance-oriented applications. **ImageLazy** es un componente liviano y personalizable de React para cargar imágenes perezosamente (lazy load) usando la API de Intersection Observer. Incluye manejo de errores, efectos visuales, y soporte para spinners personalizados y transiciones ideal para aplicaciones optimizadas. --- ## 📚 Contenido - [📦 Instalación](#-installation--instalación) - [ Características Nuevas](#-new-features--características-nuevas) - [🚀 Uso Básico](#-usage--uso-básico) - [📃 Tabla de Props](#-props-table--tabla-de-props) - [🎨 Ejemplos Avanzados](#-advanced-example-with-spinner-and-fallback--ejemplo-avanzado-con-spinner-y-fallback) - [💡 Uso de Props](#-prop-usage-with-examples--uso-de-props-con-ejemplos) - [🔁 Efectos Visuales](#-effects--efectos-visuales) - [🔧 Cómo funciona](#-how-it-works--cómo-funciona) - [ FAQ](#-faq) - [📊 Comparación](#-comparison-with-react-lazy-load-image-component--comparación-con-react-lazy-load-image-component) - [📄 Licencia](#-license--licencia) - [👤 Autor](#-author--autor) --- ## 📦 Installation / Instalación ```bash npm install react-lazy-img-observer ``` ## ✨ New Features / Características Nuevas - **Next.js 13+ Ready**: Full support for App Router with `"use client"` directive. - **SSR Optimized**: Zero hydration mismatches or server warnings. - **TypeScript Native**: Written in TS for perfect autocompletion. - **Performance**: Improved threshold defaults and memoized styles. --- ## 📃 Props Table / Tabla de Props | Prop | Tipo | Por Defecto | Descripción (ES) / Description (EN) | | -------------------- | ----------------------------------------- | ----------- | --------------------------------------------------------------- | | `src` | `string` | | URL de la imagen / Image URL | | `alt` | `string` | | Texto alternativo / Alt text | | `srcSet` | `string` | | Set de imágenes responsive / Responsive image set | | `sizes` | `string` | | Tamaños para srcSet / Responsive sizes | | `width` | `number` | | Ancho fijo / Fixed width | | `height` | `number` | | Alto fijo / Fixed height | | `id` | `string \| number` | | ID del elemento / Element ID | | `className` | `string` | | Clase CSS personalizada / Custom CSS class | | `title` | `string` | | Atributo title del tag img / Tooltip text | | `useTitleFromAlt` | `boolean` | `false` | Usa el alt como title / Use `alt` value as `title` | | `extraData` | `ImgHTMLAttributes<HTMLImageElement>` | | Props adicionales para img / Extra native props | | `viewTransitionName` | `string` | | Nombre para View Transitions API | | `style` | `CSSProperties` | | Estilos inline / Inline styles | | `backgroundColor` | `string` | | Color de fondo mientras carga / Background while loading | | `animationDuration` | `string` | `0.9s` | Duración de la transición / Animation duration | | `blurAmount` | `string` | `20px` | Desenfoque inicial / Initial blur effect | | `fallbackSrc` | `string` | | Imagen fallback si falla / Fallback image if loading fails | | `threshold` | `number` | `0.5` | Umbral de visibilidad / Intersection threshold | | `transitionType` | `'blur' \| 'fade' \| 'scale' \| 'custom'` | `'blur'` | Tipo de transición visual / Type of transition | | `onLoadComplete` | `() => void` | | Callback al cargar / Callback after image is fully loaded | | `visibleByDefault` | `boolean` | `false` | Cargar sin lazy / Load immediately without waiting for viewport | | `loadingComponent` | `ReactNode` | | Componente mientras carga / Custom loader component | --- --- ## 🔁 Effects / Efectos Visuales | Effect | Description | | -------- | ----------------------------------------------------------------------------------------- | | `blur` | Apply blur and remove it after load / Aplicar desenfoque y eliminarlo después de cargar | | `fade` | Fade in the image / Desvanecimiento de la imagen | | `scale` | Slight zoom effect / Ligero efecto de zoom | | `custom` | Use your own CSS (add class to image) / Utilice su propio CSS (agregue clase a la imagen) | --- --- ## 🚀 Usage / Uso Básico ```tsx import ImageLazy from "react-lazy-img-observer"; function App() { return ( <ImageLazy src="https://example.com/photo.jpg" alt="Example image" width={400} height={300} /> ); } ``` ### ✅ Explicación: - `src`: URL de la imagen / Image URL. - `alt`: Texto descriptivo para accesibilidad y SEO / Descriptive text for accessibility and SEO. - `width` / `height`: Definen tamaño fijo (opcional pero recomendable para evitar reflow / Define fixed size (optional but recommended to avoid reflow). --- ## 🎨 Advanced Example with Spinner and Fallback / Ejemplo Avanzado con Spinner y Fallback ```tsx import ImageLazy from "react-lazy-img-observer"; const Spinner = () => <div className="spinner">Loading...</div>; function GalleryImage() { return ( <ImageLazy src="/img/cat.webp" alt="Cute Cat" width={300} height={200} fallbackSrc="/img/fallback.webp" backgroundColor="#eee" animationDuration="1s" blurAmount="8px" transitionType="fade" loadingComponent={<Spinner />} /> ); } ``` --- ## 💡 Prop Usage with Examples / Uso de Props con Ejemplos ### 📍 `fallbackSrc` ```tsx <ImageLazy src="/img/main.jpg" fallbackSrc="/img/fallback.jpg" alt="Imagen principal" /> ``` 👉 Si la imagen original falla, se muestra automáticamente la alternativa / If the original image fails, the alternative is automatically displayed. --- ### 🎨 `backgroundColor` ```tsx <ImageLazy src="/img/pic.jpg" alt="Imagen con fondo gris" backgroundColor="#f0f0f0" /> ``` 👉 Color visible mientras la imagen carga (mejora UX) / Color visible while image loads (UX improvement). --- ### 💫 `blurAmount` y `animationDuration` ```tsx <ImageLazy src="/img/blurred.jpg" alt="Efecto blur personalizado" blurAmount="5px" animationDuration="2s" /> ``` 👉 Controla el desenfoque inicial y duración del efecto / Controls the initial blur and duration of the effect. --- ### 🌀 `transitionType` ```tsx <ImageLazy src="/img/pic.jpg" alt="Fade in" transitionType="fade" /> <ImageLazy src="/img/pic.jpg" alt="Scale in" transitionType="scale" /> <ImageLazy src="/img/pic.jpg" alt="Custom CSS" transitionType="custom" className="img-fx" /> ``` **CSS (ejemplo avanzado):** ```css .img-fx { opacity: 0; transform: scale(0.8) rotate(-2deg); transition: all 0.8s ease; } .img-fx.loaded { opacity: 1; transform: scale(1) rotate(0deg); } ``` 👉 Usa `custom` para controlar completamente la animación con tu propio CSS / Use `custom` to fully control the animation with your own CSS. --- ### 🔁 `visibleByDefault` ```tsx <ImageLazy src="/img/pic.jpg" alt="Carga inmediata" visibleByDefault={true} /> ``` 👉 Útil cuando no deseas esperar a que la imagen entre al viewport (ej: SSR o cuando ya está precargada / Useful when you don't want to wait for the image to enter the viewport (e.g. SSR or when it is already pre-loaded). --- ## 🔧 How it works / ¿Cómo funciona? - When `visibleByDefault` is `false` (default), the image loads only when it's in the viewport (IntersectionObserver)/Cuando `visibleByDefault` es `false` (predeterminado), la imagen se carga solo cuando está en la ventana gráfica (IntersectionObserver). - If `visibleByDefault` is `true`, the image is loaded immediately (useful for SSR or cached images)/Si `visibleByDefault` es `true`, la imagen se carga inmediatamente (útil para SSR o imágenes almacenadas en caché). - You can add a custom CSS transition, fallback, background color, and even a loading spinner/Puede agregar una transición CSS personalizada, una alternativa, un color de fondo e incluso un indicador de carga. --- ### 🧭 `loadingComponent` ```tsx <ImageLazy src="/img/loading.jpg" alt="Con spinner" loadingComponent={<div className="spinner">Cargando...</div>} /> ``` 👉 Muestra un componente personalizado mientras se carga la imagen / Display a custom component while the image is loading. --- ### 🧪 `onLoadComplete` ```tsx function handleLoad() { console.log("¡Imagen completamente cargada!"); } <ImageLazy src="/img/event.jpg" alt="Imagen con evento" onLoadComplete={handleLoad} />; ``` ### 🔁 `onLoadComplete` con lógica avanzada / with advanced logic ```tsx const [estado, setEstado] = useState("cargando"); <ImageLazy src="/img/camara.jpg" alt="Avanzado" onLoadComplete={() => setEstado("cargada")} /> <p>Estado de imagen: {estado}</p> ``` ### ✅ `onLoadComplete` con múltiples imágenes / with multiple images ```tsx const [cargas, setCargas] = useState(0); const incrementar = () => setCargas((prev) => prev + 1); <ImageLazy src="/img/uno.jpg" alt="uno" onLoadComplete={incrementar} /> <ImageLazy src="/img/dos.jpg" alt="dos" onLoadComplete={incrementar} /> <p>Imágenes cargadas: {cargas}</p> ``` --- ### 🧷 `useTitleFromAlt` ```tsx <ImageLazy src="/img/title.jpg" alt="Una imagen informativa" useTitleFromAlt={true} /> ``` 👉 Usa el valor de `alt` también como atributo `title` automáticamente. Útil para tooltips nativos / Automatically uses the `alt` value as the `title` attribute as well. Useful for native tooltips.. --- ### 🖼 `viewTransitionName` ```tsx <ImageLazy src="/img/view.jpg" alt="Transición de vista" viewTransitionName="fade-image" /> ``` 👉 Para integrar con la API de `view-transition` (Chrome 111) y hacer animaciones entre páginas con `<ViewTransition>` / To integrate with the `view-transition` API (Chrome 111) and make animations between pages with `<ViewTransition>`. --- ### 🏷️ `id` (uso en scroll o testing) ```tsx <ImageLazy src="/img/anchor.jpg" alt="Imagen anclada" id="fotoPrincipal" /> <a href="#fotoPrincipal">Ir a la imagen</a> ``` 👉 Permite identificar la imagen fácilmente para navegación, testing u operaciones DOM / Allows you to easily identify the image for navigation, testing, or DOM operations.. --- ### 📐 `srcSet` y `sizes` ```tsx <ImageLazy src="/img/400.jpg" srcSet="/img/400.jpg 400w, /img/800.jpg 800w" sizes="(max-width: 600px) 400px, 800px" alt="Imagen responsive" /> ``` 👉 Mejora el rendimiento en dispositivos móviles cargando imágenes más ligeras según el ancho de pantalla / Improves performance on mobile devices by loading images smaller based on screen width. --- ### 🧩 `extraData`, `className`, `style` ```tsx <ImageLazy src="/img/extra.jpg" alt="Con extras" className="rounded shadow" style={{ objectFit: "cover" }} extraData={{ draggable: false, crossOrigin: "anonymous" }} /> ``` 👉 Puedes personalizar todo el comportamiento nativo de `<img>` sin limitaciones / You can customize all native behavior of `<img>` without limitations. --- ## 🌐 SSR Compatible / Compatible con SSR ImageLazy is safe to use in SSR environments (like Next.js). It checks for `window` and disables IntersectionObserver logic when rendering on the server. ImageLazy es seguro para entornos con renderizado del lado del servidor como Next.js. Detecta si `window` está disponible antes de usar IntersectionObserver. --- ## 📊 Comparison with react-lazy-load-image-component / Comparación con react-lazy-load-image-component | Feature / Característica | `ImageLazy` | `react-lazy-load-image-component` | | ------------------------------------------- | ---------------------------------- | ---------------------------------------------- | | Lightweight & no external dependencies | Yes / | No (más pesado y con múltiples componentes) | | SSR Friendly (Next.js compatible) | Yes / | Yes / | | Custom transitions via CSS (`custom`) | Yes / | No | | Native spinner support (`loadingComponent`) | Yes / | No (solo con workarounds) | | Fallback support (`fallbackSrc`) | Yes / | Yes / | | Responsive images (`srcSet` and `sizes`) | Yes / | Yes / | | Load other elements lazily | Images only / Solo imágenes | Yes (via `LazyLoadComponent`) | | Built-in effects | `blur`, `fade`, `scale`, custom | `blur`, `opacity`, `bw` | | Transition customization | Total freedom with CSS | Limited | --- ## ❓ FAQ **¿Por qué mi imagen no se muestra?** / **Why isn't my image showing?** Asegúrate de que `src` no sea `null`, y revisa si `visibleByDefault` está en `true` / Make sure `src` is not `null`, and check if `visibleByDefault` is set to `true`.. **¿Puedo usarlo en SSR como Next.js?** / **Can I use it in SSR like Next.js?** Sí. Internamente revisa si `window` existe antes de ejecutar el observer / Yes. Internally it checks if `window` exists before running the observer. **¿Cómo puedo aplicar una animación personalizada?** / **How ​​can I apply a custom animation?** Usa `transitionType="custom"` y define tu clase con efectos CSS / Use `transitionType="custom"` and define your class with CSS effects. --- ## 📄 License / Licencia [MIT License](./LICENSE) --- ## 👤 Author / Autor **Percy Chuzon** 📧 [contacto@percychuzon.com](mailto:contacto@percychuzon.com) 🌐 [https://percychuzon.com](https://percychuzon.com) --- ## 💡 Tip If you want more control, just set `transitionType="custom"` and style the image with CSS. It’s that simple. Si deseas más control, usa `transitionType="custom"` y aplica tus estilos con CSS. Así de simple. --- Happy loading! 🎉 / ¡Carga feliz! 🎉