15 de enero de 2012

Personalizar INPUT FILE solamente con CSS, Custom Input File!!!

Muchos diseñadores web, hemos tenido el problema de personalizar al 100% un botón tipo archivo de HTML, es decir, <input type="file" />.
En internet podemos encontrar posibles formas de hacerlo, pero la mayoría de ellas requieren utilizar API’s de flash o de librerías como jQuery y Mootools. Puede ser una buena opción pero solomente deseamos un simple botón que tenga la funcionalidad para subir archivos sin tanto código. También hay códigos creados por usuarios en foros o blogs, pero lamentablemente la mayoría usan Javascript y/o CSS y no suelen funcionar bien en los principales navegadores: Firefox, IE, Chrome, Safari y Opera.
Bueno, pues logré crear un custom input file mediante un par de lineas usando solamente CSS y sus respectivas etiquetas HTML.


El código CSS es:
.custom-input-file {
    overflow: hidden;
    position: relative;
    cursor: pointer;
}
.custom-input-file .input-file {
    margin: 0;
    padding: 0;
    outline: 0;
    font-size: 10000px;
    border: 10000px solid transparent;
    opacity: 0;
    filter: alpha(opacity=0);
    position: absolute;
    right: -1000px;
    top: -1000px;
    cursor: pointer;
}
EL código HTML es:
<div class="custom-input-file"><input type="file" size="1" class="input-file" />
    Subir archivo
</div>
Con este par de lineas de código pueden personalizar un input file a su gusto, como agregar imagen de fondo, efectos visuales al pasar el mouse, bordes, etc. Es compatible con todos los principales navegadores.
Ahora, ¿cómo personalizar un input file usando este código?
Muy fácil, pueden modificar o agregar estilos a su gusto a excepción de lo siguiente:
  • No modificar nada en .custom-input-file .input-file a excepción del cursor.
  • No modificar overflow: hidden; position: relative; en .custom-input-file, pueden agregar más estilos.
  • Todo el contenido que agreguen dentro del div custom-input-file, debe ir despues de la etiqueta <input type="file">, no antes.
  • Cuando cambien el cursor, deben cambiarlo en .custom-input-file y .custom-input-file .input-file.
Eso es todo, un ejemplo usando este código es el siguiente:

Pueden ver el ejemplo más detallado aquí:
http://jsfiddle.net/angelfcm/nETSD/
Publiquen sus comentarios, gracias.

28 comentarios:

  1. Me fascina la idea de este blog, La recomiendo ampliamente. +1

    ResponderEliminar
  2. genial, no había encontrado cómo hacerlo de una forma tan sencilla... gracias.

    ResponderEliminar
  3. Comparada con las otras que he encontrado es realmente sencilla y elegante...muchas gracias

    ResponderEliminar
  4. Muchas gracias por sus excelentes comentarios, me alegra que les haya servido.

    ResponderEliminar
    Respuestas
    1. en qué parte del código debo de meter lo de java? no encuentro dónde y ya poniéndolo a funcionar no me muestra el nombre del archivo se queda en ...

      Eliminar
    2. La parte del javascript utiliza jquery, por lo que tendrás que descargar el plugin de jquery. Una vez que lo integres a la página, el código lo cargas en la cabecera de la misma o bien, lo llamas desde un archivo .js externo; para cualquiera de las dos opciones, debe ir después de haber llamado el archivo de jquery.

      Eliminar
  5. Me encanto funciono de maravilla felicidades y muchas gracias por este aporte excelente (Y)

    ResponderEliminar
  6. Muy buen articulo, pero estoy teniendo un problema con IE 9 y tambien con Firefox, si por ejemplo selecciono un archivo a subir y sin enviarlo y apreto F5 se actualiza el navegador y en el caso de IE queda en blanco, en firefox queda el campo archivo sin el texto pero si apreto subir lo sube

    ResponderEliminar
    Respuestas
    1. Hola Laura, mucha gracias por tu comentario. He revisado lo que mencionas y es cierto, pero a mi me sucede en Chrome e IE (en Firefox no). Lo que sucede en realidad es que el texto desaparece como un display:none, el motivo es que si aplicas la fuente Calibri a casi cualquier elemento con un valor de la propiedad display distinto a "inline" por alguna extraña razón sucede este problema.

      No solo pasa con mi código para el input file sino que es igual con cualquier elemento que cumpla las condiciones que acabo de mencionar.

      Por ejemplo:

      <div style="font-family: calibri">Esto no se ve.</div> <a style="font-family: calibri; display: block">Esto no se ve.</a> <div style="font-family: calibri; display: inline">Esto si se ve.</div> <br /> <a style="font-family: calibri;">Esto si se ve.</a>

      Como ves la fuente calibri y display != "inline" causan el problema.

      Probablemente eso se deba al estándar del documento, hay que evitar utilizar la fuente calibri y siempre estandarizar con HTML, es decir, poner al principio de todo documento .

      Ya he actualizado el ejemplo del input file, prueba de nuevo y coméntame como te fue.

      Saludos!

      Eliminar
    2. Angel, gracias por tu respuesta!!

      Te cuento que con el cambio en la funcion se soluciono el problema en IE, tambien funciona bien en chrome, en Firefox graficamente se ve bien pero existe un problema, me pasa lo siguiente:

      Si selecciono un archivo y apreto F5 sin subirlo, se recarga la
      pagina con todo ok! pero si apreto enviar archivo sin haber seleccionado antes me envia igual el archivo que habia cargado en un inicio...

      Eliminar
  7. Hola buenas,
    Antes de nada mil gracias por compartirlo, pero...
    Lo he copiado tal y como está y no me funciona :(
    Los estilos y demás están bien, me lo pone todo correctamente, pero al hacer click en el botón, no hace nada. Creo que algún fallo tengo en la función:


    $(document).ready(function(){
    $(".custom-input-file input:file").change(function(){ $(this).parent().find(".archivo").html($(this).val());
    }).css('border-width',function(){
    if(navigator.appName == "Microsoft Internet Explorer")
    return 0;
    });
    });


    Si alguien puede ayudarme...
    Muchas gracias de antemano.
    ¡Un saludo!

    ResponderEliminar
  8. ¡Solucionado!
    He tenido que modificar el script a:
    $(document).ready(function(){
    $(function(){
    $('.custom-input-file input:file').change(function(){
    $('.archivo').html($(this).val());
    });
    });
    });

    Por si a alguien le sirve ahí lo tiene.
    Lo único que al cargar el PATH donde se aloja el archivo, me aparece el "FakePath"...
    No sé si alguno de vosotros sabe cómo cargar la URL correcta en vez de esa.

    Un saludo ;)

    ResponderEliminar
    Respuestas
    1. que tal pues yo cambie el fakepath asi, no me parecio conveniente el mostrar toda la ruta, por lo largo que puede llegar a ser, espero te pueda servir

      $(function(){
      $(".custom-input-file input:file").change(function(){
      $(this).parent().find(".archivo").html($(this).val().replace("fakepath", "..."));
      }).css('border-width',function(){
      if(navigator.appName == "Microsoft Internet Explorer")
      return 0;
      });
      });

      Eliminar
    2. Hola. ¿Podéis decirme dónde hay que añadir este trozo de código?

      Eliminar
  9. De verdad, un trabajo genial, adoro que no se necesite java script (bueno o casi).

    Estoy tratando de hacer mi página con html4.x, css2.x, php4.x y Mysql (jquery solo para las animaciones, transiciones y efectos secundarios no imprescindibles para la correcta navegación)

    Y dejándola preparada para sacar con facilidad una versión HTML5 + css3 + (php + mysql).

    Un aporte genial, muchísimas gracias.

    Sé que no es mucho, pero tengo algunos botones (type='submit') hechos con divs animables, compatibles con los principales navegadores. Es un código sencillito (solo css y html) pero se consiguen iconos sorprendentes con 4 radious y un par de :hover bien posicionados. Si te pica la curiosidad en dos o tres meses publicaré mi página y por supuesto todo el código. ^_^

    Gracias de verdad.

    ResponderEliminar
    Respuestas
    1. Gracias a ti, es bueno saber que le encuentres utilidad y me gustaría ver tu página cuando esté terminada, saludos.

      Eliminar
  10. Hola! la idea me parece muy buena, pero no acaba de funcionar bien, estoy en firefox y sale activo para la subida de archivos prácticamente todo el espacio que tengo vacío, es decir, allí donde no hay una capa con contenido, es activo el input, y la web es muy minimalista y muy limpia, de modo que pinche donde pinche, se abre la ventana de "examinar".
    He probado con los z-index, pero nada...si lo bajo mucho no es accesible, y si no lo bajo tanto está sobre todas las capas.
    Alguna idea?

    ResponderEliminar
  11. Arreglado tío, he modificado lo que dices que no se modifique, pero así he conseguido que sólo esté activo el botón que yo he hecho, (en mi caso de 200 px)
    Te paso el código por si te sirve, y por cierto, mil gracias, es una pasada lo que has hecho. Mil gracias por compartir!!
    .custom-input-file {
    border: 1px solid #FFFFFF;
    border-radius: 3px;
    color: #FFFFFF;
    cursor: pointer;
    margin-left: 20px;
    overflow: hidden;
    padding: 5px;
    position: relative;
    text-align: center;
    width: 200px;
    }
    .custom-input-file .input-file {
    border-top: 27px solid transparent;
    cursor: pointer;
    font-size: 0;
    left: -5px;
    margin: 0;
    opacity: 0;
    outline: 0 none;
    padding: 0;
    position: absolute;
    top: -5px;
    width: 77px;
    }
    Puedes verlo en mgspain.com/contacto aún está en desarrollo pero bueno.
    ;-)

    ResponderEliminar
  12. Hola! Felicitarte por tu web y por la ayuda que prestas...
    Yo tengo un problema para incluir el el archivo php en envio de la imagen... podrías ayudarme?

    te dejo el codigo php que tengo hasta el momento:
    $from = $_POST['email'];

    $subject = 'formulario consulta web';

    $message = 'From: ' . $_POST['name'] . "\n". 'Mensaje:' . $_POST['data'];

    $headers = "From: ". $from . "\n";

    mail ('info@catalunya1.info', $subject, $message, $headers);

    header('Location: thanks.html');


    podrías ayudarme a incluir el código que necesito para que el archivo llegue adjunto al mensaje?

    ResponderEliminar
    Respuestas
    1. Hola Yolanda, muchas gracias!,

      Mira para enviar un archivo adjunto, necesitas mucho más, ahorita no tengo contenido acerca de eso pero puedes buscar en google "Cómo enviar mail con archivos en PHP", saludos!

      Eliminar
  13. Muchas gracias por el aporte. Muy utlil.

    ResponderEliminar
  14. Según veo funciona super bien, pero en mi caso no logro hacer que me funcione bien, logra cargar el archivo pero no me muestra la ruta, como puedo solucionarlo?. gracias.

    ResponderEliminar
  15. En el IE 11 no funciona correctamente. Desaparece el texto "Examinar"

    ResponderEliminar
    Respuestas
    1. Hola Tocayo,

      Para que no se borre la palabra Examinar en IE >= 11, dentro del $(function(){... habría que agregar las siguientes líneas de código:

      //Begin: Bug fix IE >= 11
      $(".custom-input-file input:file").focus(function(){
      if(navigator.appName == "Netscape") {
      $(this).css('position','relative');
      setTimeout(function(){ $(".custom-input-file input.input-file").css('position','absolute'); }, 0);
      }
      });
      //End: Bug fix IE >= 11

      Eliminar
  16. Este comentario ha sido eliminado por el autor.

    ResponderEliminar