ProgramandooIntentándolo

Como modificar el estilo de un input file

Modificar el estilo de un input file no es tan sencillo como debiera y es necesario utilizar ademas de CSS javaScript. Vamos con ello.

En este otro post puedes ver otra forma de moficicar el estilo del input file, que es más sencilla de entender aunque es muy similar.

Puesto que el estilo del input file no se puede modificar de forma directa lo que se hace es crear un input file y ocultarlo. Y colocar un imput normal encima, que estos si que se pueden modificar a nuestro antojo mediante CSS y de esta forma conseguimos modficar la forma en la que se ve el input file, si bien es cierto, lo que vemos no es el input file.


<div class="inputFileModificado">
    <input class="inputFileOculto" name="input1" type="file">
    <div class="inputParaMostrar">
        <input>
        <img src="imagenes/button_select.gif">
    </div>
</div>

Con el codigo HTML anterior crearemos el input file modificado. La clase inputFileModificado se usa unicamente como contenedor, pudiendo usarse para tener varios tipos de input files (sustituyendo esta clase por otra). En la siguiente linea esta el input file que ocultaremos y despues otra division con un input y una imagen que cumpliran el cometido del campo y el boton del input file.

El CSS que utilizaremos para modificar el estilo será el siguiente que no tiene mucho que comentar más alla de que para ocultar el input usaremos la opacidad y no el atributo hidden pues de esta forma el input sigue siendo seleccionable aunque no se vea cosa que con hidden no ocurriria.


.inputFileModificado input {
    background: url('../imagenes/campo_texto.gif') no-repeat;
    border: none;
    width: 400px;
    height: 20px;
    padding-left: 5px;
    padding-top: 2px;
    margin-right: -95px;
}

.inputFileModificado {
    position: relative;
    margin-bottom: 20px;
}

.inputFileOculto {
    position: relative;
    text-align: right;
    -moz-opacity: 0;
    opacity: 0;
    z-index: 2;       
}

.inputParaMostrar {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 600px;
    z-index: 1;
}

Con estos sencillos pasos ya tenemos el input file modificado, pero con una gran pega. Cuando seleccionamos un archivo esto no se ve reflejado en nuestro input file modificado porque ciertamente lo que hemos hecho es ocultar el verdadero input file con otro input.

Para dejar nuestro input file totalmente modificado y funcional usaremos javaScript.


/**
 * Permite que se muestre el contenido del input file en el que se ha modificado el estilo.
 * 
 * @param nombreInput Nombre del input file que se quiere ver con un estilo modificado
 */
function mostrarInputFileModificado(nombreInput) {
    // Creamos la división para mostrar el input file con otro estilo.
    var nuevaDiv = document.createElement('div');
    nuevaDiv.className = 'inputParaMostrar';

    // Se añade el campo en el que se mostrara el nombre del archivo selecionado.
    nuevaDiv.appendChild(document.createElement('input'));

    // Almacena en arrayInptuts todos los input de la 'pagina'.
    var arrayInputs = document.getElementsByTagName('input');
    
    for (var i=0; i < arrayInputs.length; i++) {
        // Se comprueba si es el input que buscamos
        if (arrayInputs[i].name == nombreInput){
            // Se clona la division creada y se agrega el input a la lista de inputs.
            var clonado = nuevaDiv.cloneNode(true);
            arrayInputs[i].parentNode.appendChild(clonado);

            // Se obtiene el input clonado y se reflejan en el los cambios producidos en el input file original.   
            arrayInputs[i].campoClonado = clonado.getElementsByTagName('input')[0];
            arrayInputs[i].onchange = function (){
                    this.campoClonado.value = this.value;
            }
            
            // Se sale del for porque ya se ha encontrado el input que se buscaba.
            break;
        }
    }
}

Con esta función solo se actua sobre el campo que se pase, por si no se quiere que modifique todos los inputs. Pero si se quieren modificar todos mejor utilizar la siguiente:


/**
 * Permite que se muestre el contenido de todos los input file en los que se ha modificado el estilo.
 * 
 */
function mostrarInputFileModificados() {
    // Creamos la división para mostrar el input file con otro estilo.
    var nuevaDiv = document.createElement('div');
    nuevaDiv.className = 'inputParaMostrar';

    // Se añade el campo en el que se mostrara el nombre del archivo selecionado.
    nuevaDiv.appendChild(document.createElement('input'));

    // Almacena en arrayInptuts todos los input de la 'pagina'.
    var arrayInputs = document.getElementsByTagName('input');
    
    for (var i=0; i < arrayInputs.length; i++) {
        // Se comprueba si el input es de la clase inputFileOculto 
        if (arrayInputs[i].className == "inputFileOculto"){
            // Se clona la division creada y se agrega el input a la lista de inputs.
            var clonado = nuevaDiv.cloneNode(true);
            arrayInputs[i].parentNode.appendChild(clonado);

            // Se obtiene el input clonado y se reflejan en el los cambios producidos en el input file original.   
            arrayInputs[i].campoClonado = clonado.getElementsByTagName('input')[0];
            arrayInputs[i].onchange = function (){
                    this.campoClonado.value = this.value;
            }
        }
    }
}

Finalmente, creamos unos input file para comprobar el resultado de la modificación.


<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script type="text/javascript" src="js/modificarEstiloInputFile.js"></script>
        <link rel="stylesheet" type="text/css" href="css/estilo.css"/>
        <title>Modificar estilo de un input file</title>
    </head>
    <body>
        
        <br />
        <h3>Input files con estilo modificado</h3>
        <div class="inputFileModificado">
            <input class="inputFileOculto" name="input1" type="file">
            <div class="inputParaMostrar">
                <input>
                <img src="imagenes/button_select.gif">
            </div>
        </div>
        <div class="inputFileModificado">
            <input class="inputFileOculto" name="input2" type="file">
            <div class="inputParaMostrar">
                <input>
                <img src="imagenes/button_select.gif">
            </div>
        </div>
        <div class="inputFileModificado">
            <input class="inputFileOculto" name="input3" type="file">
            <div class="inputParaMostrar">
                <input>
                <img src="imagenes/button_select.gif">
            </div>
        </div>
        <div class="inputFileModificado">
            <input class="inputFileOculto" name="input4" type="file">
            <div class="inputParaMostrar">
                <input>
                <img src="imagenes/button_select.gif">
            </div>
        </div>
        <div class="inputFileModificado">
            <input class="inputFileOculto" name="input5" type="file">
            <div class="inputParaMostrar">
                <input>
                <img src="imagenes/button_select.gif">
            </div>
        </div>
        
        <br />
        <h3>Input files sin modificar</h3>
        <input name="input6" type="file">
        <br />
        <input name="input7" type="file">
        
        <!-- Muestra el estilo modificado para los input files -->
        <body onLoad="mostrarInputFileModificados();">
<!--        <body onLoad="mostrarInputFileModificado('input1');">-->

    </body>
</html>

El resultado es este:

Puedes descargarte el proyecto aquí.