# Convertir una imagen a Base64 y usarla como data URI en CSS

Incrustar una imagen pequeña directamente en el CSS o en el HTML ahorra una petición al servidor y evita que un icono "parpadee" mientras carga. La técnica se llama **data URI**: en lugar de una ruta como `icono.png`, escribes la imagen codificada en Base64 dentro de la propia hoja de estilos.

En este artículo vamos a hacerlo con un ejemplo real y comprobable: crearemos una imagen diminuta, la convertiremos a Base64, la usaremos en CSS y en HTML, y verificaremos que al decodificarla obtenemos exactamente los mismos bytes.

> **Divulgación:** la herramienta que enlazo, [Convertir Imagen a Base64](https://base64decodetool.com/es/image/), la creó Nagesh, el autor de este blog.

## Qué es un data URI

Un data URI tiene esta forma:

```
data:[tipo MIME];base64,[datos codificados]
```

Para un PNG sería `data:image/png;base64,` seguido de la cadena Base64. El navegador lo trata como si fuera un archivo: puedes ponerlo en `src` de una etiqueta `<img>` o dentro de `url()` en CSS.

## Ejemplo práctico: un PNG de 2×2 píxeles

*Los datos de este ejemplo son ilustrativos: la imagen la generé yo mismo para el artículo, no proviene de ningún proyecto real.*

Creé con Python (sin librerías externas, solo `zlib` y `struct`) un PNG de 2×2 píxeles con un patrón de tablero: rojo `(255, 0, 0)` y azul `(0, 128, 255)` alternados. El archivo resultante, `punto.png`, ocupa **75 bytes**.

Para codificarlo, basta con la biblioteca estándar:

```python
import base64

with open("punto.png", "rb") as f:
    datos = f.read()

b64 = base64.b64encode(datos).decode("ascii")
print(len(datos), len(b64))   # 75 100
print("data:image/png;base64," + b64)
```

La salida Base64 real es (100 caracteres):

```
iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAEklEQVR42mP4z8DA0PAfhIEEACLyBP2KEV+xAAAAAElFTkSuQmCC
```

Y el data URI completo (122 caracteres):

```
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAEklEQVR42mP4z8DA0PAfhIEEACLyBP2KEV+xAAAAAElFTkSuQmCC
```

Fíjate en que todos los PNG empiezan por `iVBORw0KGgo`: es la firma binaria del formato (`89 50 4E 47 0D 0A 1A 0A`) vista en Base64. Si una cadena que dice ser PNG no empieza así, algo está mal.

### Usarlo en CSS

```css
.patron {
  width: 40px;
  height: 40px;
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAEklEQVR42mP4z8DA0PAfhIEEACLyBP2KEV+xAAAAAElFTkSuQmCC");
  background-size: 8px 8px;
  image-rendering: pixelated; /* para que se vean los píxeles nítidos al ampliar */
}
```

Con `background-size` y la repetición por defecto, el PNG de 2×2 se convierte en un fondo de tablero rojo y azul.

### Usarlo en HTML

```html
<img
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAEklEQVR42mP4z8DA0PAfhIEEACLyBP2KEV+xAAAAAElFTkSuQmCC"
  width="40" height="40"
  alt="Patrón de tablero rojo y azul"
  style="image-rendering: pixelated">
```

Escribe siempre un `alt` descriptivo: que la imagen esté incrustada no cambia nada en accesibilidad.

## Comprobación: ida y vuelta

Una codificación correcta debe ser reversible sin pérdidas:

```python
assert base64.b64decode(b64) == datos   # True
```

En mi prueba, decodificar la cadena devolvió exactamente los mismos 75 bytes (huella SHA-256 `34391be6…77ba00` en ambos casos). Además descargué el JavaScript público de la página de la herramienta y ejecuté con Node.js sus funciones de codificación y decodificación sobre el mismo archivo: produjeron la misma cadena de 100 caracteres que Python, y la decodificación devolvió los 75 bytes idénticos. Para la lectura del archivo, la página usa el `FileReader.readAsDataURL()` estándar del navegador, que genera el mismo formato `data:image/png;base64,…`.

## El coste: aproximadamente un 33 % más

Base64 representa cada 3 bytes con 4 caracteres, así que el tamaño crece en un factor de **4/3** (más el relleno `=` cuando la longitud no es múltiplo de 3):

| Concepto | Tamaño |
|---|---|
| PNG original | 75 bytes |
| Base64 | 100 caracteres (75 ÷ 3 × 4 = 100, sin relleno) |
| Prefijo `data:image/png;base64,` | 22 caracteres |
| Data URI completo | 122 caracteres |

En nuestro ejemplo el aumento es exactamente del 33,3 %; con el prefijo, el texto final ocupa un 63 % más que el archivo. En un icono de 75 bytes da igual, pero en una foto de 300 KB serían unos 400 KB de texto (cálculo ilustrativo) metidos dentro de tu CSS. La compresión gzip o Brotli del servidor reduce parte de esa diferencia, pero no toda.

## Base64 no es cifrado

Base64 es solo una **codificación**: cualquiera puede revertirla en un segundo, sin clave. No sirve para ocultar ni proteger una imagen. Si incrustas algo en tu CSS, es tan público como un archivo enlazado.

## ¿Cuándo usar data URIs y cuándo no?

**Úsalos para:**

- Iconos y patrones muy pequeños (unos pocos KB como máximo).
- Imágenes críticas para el primer pintado que no quieres que dependan de otra petición.
- Correos HTML, prototipos o archivos HTML autocontenidos.

**Evítalos para:**

- Fotos o imágenes grandes: inflan el CSS/HTML y retrasan el renderizado de toda la página.
- Imágenes que se reutilizan en varias páginas: un archivo aparte se guarda en la **caché** del navegador una sola vez; un data URI se vuelve a descargar cada vez que cambia el CSS o el HTML que lo contiene.
- Iconos SVG: muchas veces es mejor incrustar el SVG como texto (codificado para URL) que en Base64.

**Nota sobre CSP:** si tu sitio usa *Content Security Policy*, las imágenes con `data:` solo se cargarán si la directiva lo permite, por ejemplo `img-src 'self' data:`. Si un icono incrustado no aparece, revisa la consola del navegador antes de culpar a la cadena Base64.

## Cómo usar la herramienta

La página [base64decodetool.com/es/image/](https://base64decodetool.com/es/image/) está en español, pero algunos botones aparecen en inglés (comprobado el 10 de noviembre de 2026):

1. Pulsa **Select Image** o arrastra el archivo a la zona "Arrastre y suelte la imagen aquí o haga clic para buscar" (admite PNG, JPG, WEBP, GIF y SVG de hasta 50 MB; todo se procesa en el navegador).
2. Elige el formato de salida en las pestañas **DataURL**, **HTML**, **CSS** o **Raw** (la pestaña CSS genera la línea `background-image: url("…");`).
3. Pulsa **Copiar** y pega el resultado en tu código. Si usas la pestaña HTML, cambia el texto `alt` genérico por uno descriptivo.
4. Para el proceso inverso, pega la cadena en **Paste Image Base64 String**, pulsa **Decode & Preview** y luego **Download Image**.

## Resumen

Un data URI es simplemente el archivo en Base64 con el prefijo `data:tipo/mime;base64,`. Es ideal para iconos diminutos, cuesta alrededor de un 33 % más de tamaño, no protege nada y conviene comprobarlo siempre con una decodificación de ida y vuelta. Con imágenes pequeñas, la ganancia de una petición menos compensa; con imágenes grandes, casi nunca.
