Icono de input type="date" pegado al borde: solución CSS

En Chrome y Edge, el icono del calendario de un campo de fecha se ve pegado al borde derecho, sin el espacio que esperarías por el padding. Pasa igual con los campos time y datetime-local. Un campo como este puede mostrarlo:

<input type="datetime-local" class="flex h-9 w-64 rounded-md border px-3 py-1" />

El icono no es un elemento de tu HTML, así que no puedes darle una clase. Este artículo explica qué es, en qué condiciones queda pegado o recortado, y cómo darle espacio con una regla de CSS global. También cubre los límites de la solución: es específica de los navegadores basados en Chromium.

Por qué pasa

El icono lo genera el navegador dentro del propio campo. En Chrome y Edge solo es accesible desde CSS mediante el pseudoelemento ::-webkit-calendar-picker-indicator. Es un selector con prefijo de proveedor y no estándar: una incidencia del grupo de trabajo de CSS (csswg-drafts, número 8359) lo describe así y recoge que, cuando se abrió en enero de 2023, Firefox no tenía un elemento equivalente. MDN, por su parte, indica que la apariencia del selector de fecha varía según el navegador y el sistema operativo.

En una prueba con Chrome 155 en Windows se observó lo siguiente:

  • Campo con display por defecto (o block) y padding simétrico: el padding sí se respeta. Con 12 px de padding y 1 px de borde, el icono quedó a unos 16 px del borde, y aumentar padding-right lo desplazó hacia dentro.
  • Campo con display: flex: el icono se coloca justo a continuación del texto, no en el extremo derecho. La clase flex formaba parte del Input de versiones anteriores de shadcn/ui; la versión actual del registro ya no la incluye.
  • Valor que no cabe en el campo: con display: flex y un datetime-local de 224 a 256 px, el icono quedó tocando el borde o recortado por él. Es coherente con que el contenido interno (texto más icono) no cabe en la caja de contenido del campo.

Es decir, "pegado al borde" suele indicar que el campo es demasiado estrecho para su contenido o que el display del campo altera la colocación interna. Una regla de margen mejora el aspecto en el primer caso, pero no sustituye a dar espacio suficiente.

Solución

  1. Comprueba el display y el ancho del campo. En la consola del navegador:

    const campo = document.querySelector('input[type="datetime-local"]')
    const { display, width, paddingRight } = getComputedStyle(campo)
    console.log({ display, width, paddingRight })

    Si display es flex, cámbialo a block (en Tailwind, sustituye flex por block en las clases del campo; si usas el Input de shadcn/ui, edita components/ui/input.tsx).

  2. Da ancho suficiente al campo. Usa w-full dentro de una columna o una rejilla en lugar de anchos fijos pequeños. Como referencia orientativa, en la prueba (texto de 16 px, formato de fecha en español) un datetime-local con display: block mostró texto e icono completos con 224 px (w-56), y un date con 160 px (w-40). El ancho necesario depende de la fuente, el tamaño de texto y la configuración regional.

  3. Agrega la regla global que separa el icono. En tu CSS global (en Next.js, el archivo que importa el layout raíz, normalmente app/globals.css):

    input[type="date"]::-webkit-calendar-picker-indicator,
    input[type="time"]::-webkit-calendar-picker-indicator,
    input[type="datetime-local"]::-webkit-calendar-picker-indicator {
      margin-inline: 4px;
      opacity: 0.55;
    }

    margin-inline es la abreviatura de los márgenes de inicio y fin en el eje de lectura; con un valor, se aplica a ambos lados. En la prueba, con 4px el icono se desplazó 4 px hacia el interior de un campo de 260 px. opacity: 0.55 es solo estético: atenúa el icono para que pese menos que el texto; ajusta el valor o quítalo.

  4. Revisa el tema oscuro. El icono nativo es oscuro por defecto: con fondo oscuro y la opacidad reducida casi desaparece. Según MDN, color-scheme hace que el navegador adapte los controles de formulario al esquema indicado. Declara el esquema oscuro en tu tema:

    .dark {
      color-scheme: dark;
    }

    En la prueba, el icono pasó de casi invisible a gris claro sobre fondo oscuro al activar color-scheme: dark.

Cómo verificar que quedó resuelto

  1. Abre la pantalla en Chrome o Edge y revisa los campos date, time y datetime-local: el icono debe verse completo y con espacio hasta el borde.
  2. Reduce el ancho de la ventana (por ejemplo a 320 px) y vuelve a mirar: el icono no debe quedar recortado. Si lo hace, el campo sigue siendo demasiado estrecho.
  3. Para inspeccionar el icono, activa en las herramientas de desarrollo de Chrome la opción "Show user agent shadow DOM" (Settings, Preferences, sección Elements). Con ella puedes expandir el campo y seleccionar el elemento interno del icono para ver los estilos que recibe.
  4. Confirma que tu navegador reconoce el selector:
CSS.supports("selector(::-webkit-calendar-picker-indicator)")

Devolvió true en Chrome 155. En un navegador que no lo reconozca devolverá false.

Variantes y errores relacionados

En Firefox la regla no tiene efecto

Como el pseudoelemento no existe en Firefox (según la incidencia citada, no había un equivalente cuando se abrió), la regla se ignora y el icono se dibuja como lo hace ese navegador. No es un error de tu CSS. Prueba el formulario en cada navegador que soportes y no dependas de este ajuste para la usabilidad.

No mezcles este selector con otros en la misma regla

Según MDN, si una lista de selectores contiene uno inválido, se ignora el bloque completo (salvo dentro de :is() y :where()). Mantén la regla del icono separada de cualquier otra para que un navegador que no entienda el prefijo no descarte estilos que sí necesitas.

Los campos time y datetime-local

Usan el mismo pseudoelemento, por eso la regla los lista a los tres. En la prueba, los tres iconos se desplazaron igual.

Aumentar el padding del campo

Con display por defecto, subir padding-right también aleja el icono del borde. La regla global tiene la ventaja de aplicarse a todos los campos de fecha sin tocar cada uno.

Resumen

  • El icono del calendario lo genera Chromium dentro del campo y solo se estiliza con ::-webkit-calendar-picker-indicator, un selector con prefijo y no estándar.
  • En la prueba, el icono quedó pegado o recortado con display: flex en el campo cuando el valor no cabía en el ancho disponible; con display por defecto el padding se respetó.
  • Revisa primero el display y el ancho; después agrega margin-inline: 4px (y, si quieres, una opacidad menor) en el CSS global para date, time y datetime-local.
  • En tema oscuro, declara color-scheme: dark para que el icono siga siendo visible.
  • En Firefox la regla se ignora; verifica el aspecto en cada navegador que soportes.

Referencias

Comentarios