Dar estilo a un botón input file

en css  jquery  publicado el 10 de Febrero de 2009

Dar estilo a un botón input file para seleccionar un archivo no es tan sencillo como puede ser hacerlo con cualquier otro tipo de botón. La razón es que los navegadores no lo permiten, así que cualquier intento de cambiar la fuente, el color, etc. no funcionará.

Para solucionarlo existe una técnica conocida desde hace tiempo que consiste en reemplazar el control por una imagen. Está documentada en styling an input type="file" o en styling file inputs with css and the dom. Yo prefiero la segunda opción. Shaun Inman escribió un javascript que lo que hace es desplazar el control por debajo de la imagen para que en todo momento el botón del control esté donde se encuentra el puntero del ratón. Al hacer clic lo que realmente está pasando es que se está apretando el botón del control y provoca que se abra la ventana de selección de archivo.

He encontrado un par de cosas que funcionan mal para Internet Explorer así que las he corregido, de paso he añadido una funcionalidad que creo que es importante, y finalmente lo he convertido en un plugin para jQuery. La funcionalidad extra es añadir un campo que muestra el nombre del fichero seleccionado, ya que al no mostrar el campo de texto del control se pierde esta información.

DemoDescargar

HTML

Para estilizar un control de selección de archivo lo único que hay que hacer es asignarle una clase o un id para posteriormente poder seleccionarlo. Por ejemplo:

<input type="file" class="file" name="file" />

En la cabecera del fichero HTML hay que indicar dónde se encuentra la librería jQuery, el plugin y la hoja de estilos. Por ejemplo:

<link href="jquery.si.css" rel="stylesheet" type="text/css" />
<script src="http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js" type="text/javascript"></script>
<script src="jquery.si.js" type="text/javascript"></script>

CSS

El plugin jQuery se encarga de transformar el código

<input type="file" class="file" name="file" />

por

<div class="si">
   <label id="cabinet0" class="cabinet">
      <input type="file" name="file" class="file" />
   </label>
   <div class="uploadButton"></div>
   <div></div>
   <label class="selectedFile"/>
</div>

La hoja de estilos:

div.si label.cabinet {
   width: 156px;
   height: 34px;
   display: block;
   overflow: hidden;
   position: relative;
   z-index: 3;
   float: left;
}
div.si label.cabinet input {
   position: relative;
   left: -140px;
   top: 0;
   height: 100%;
   width: auto !important;
   z-index: 2;
   opacity: 0;
   -moz-opacity: 0;
   filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);
}
div.si div.uploadButton {
   position: relative;
   float: left;
}
div.si div.uploadButton div {
   width: 156px;
   height: 34px;
   background: url(examinar.png) 0 0 no-repeat;
   left: -156px;
   position: absolute;
   z-index: 1;
}
div.si label.selectedFile {
   margin-left: 5px;
   line-height: 34px;
}

Los estilos aplicados son similares a los de Shaun. Básicamente las diferencias son para corregir los pequeños problemas que he encontrado:

  • para evitar un bug conocido de Internet Explorer con el overflow: hidden hay que añadir position: relative. Esto provocaba que una vez pasado el puntero del ratón por encima del botón, en cualquier lugar de la ventana que se hiciese clic, se abriera el seleccionador de archivos.
  • en vez de utilizar una imagen de fondo para el label.cabinet, utilizo una capa que posiciono relativamente encima del label. La razón es porque cuando recibía el foco en Internet Explorer la imagen se desplazaba un poco.
  • desplazo el control de -140px hacia la izquierda para evitar que en Internet Explorer se vea el cursor del campo de texto del control parpadear

Para la demo utilizo la imagen examinar.png de tamaño 156px por 34px. Las dos primeras líneas de la definición de label.cabinet y las cuatro primeras de div.uploadButton div se deberán modificar para adaptar el plugin a otra imagen. Para centrar verticalmente el texto con el nombre del fichero seleccionado, le aplico el mismo line-height que el height de la imagen.

Javascript

Una vez incluidas las librerías en la cabecera del fichero HTML, para que el plugin actúe hay que hacer la siguiente llamada:

$(document).ready(function() {
   $("input.file").si();
});

Esto significa que todos los input de tipo file con la clase file se estilizarán. Para más detalles, ver cómo funcionan los selectores de jQuery.

Compatibilidad

Funciona con cualquier navegador que soporta opacidad. Esto significa que para versiones anteriores a la 5.5 de Internet Explorer o anteriores a la 9 de Opera el plugin no actuará y se mostrará el control por defecto.

Si javascript no está activado, se mostrará el control por defecto.

Sin comentarios

Publicar comentario