react-lazy-img-observer
Version:
A React component for lazy loading images with Intersection Observer
421 lines (304 loc) • 16.3 kB
Markdown
# 📷 ImageLazy (v1.5.0)



**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 / Sí | ❌ No (más pesado y con múltiples componentes) |
| SSR Friendly (Next.js compatible) | ✅ Yes / Sí | ✅ Yes / Sí |
| Custom transitions via CSS (`custom`) | ✅ Yes / Sí | ❌ No |
| Native spinner support (`loadingComponent`) | ✅ Yes / Sí | ❌ No (solo con workarounds) |
| Fallback support (`fallbackSrc`) | ✅ Yes / Sí | ✅ Yes / Sí |
| Responsive images (`srcSet` and `sizes`) | ✅ Yes / Sí | ✅ Yes / Sí |
| 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! 🎉