Personalizar el aspecto del elemento input de tipo file
Uno de los problemas con el elemento de formulario input de tipo file, es que en cada navegador se muestra de forma diferente, y que darle aspecto con CSS no resulta fácil.
En el siguiente artículo veremos como darle el aspecto que queramos mediante un truco con el CSS position.
Para ello, lo primero que vamos a necesitar es colocar nuestro input de tipo file dentro de un elemento div. Para que todo quede lo más claro posible, vamos a modificar el aspecto de dos elementos input a la vez.
<div class="file-select" id="src-file1" > <input type="file" name="src-file1" aria-label="Archivo"> </div> <div class="file-select" id="src-file2" > <input type="file" name="src-file2" aria-label="Archivo"> </div>
Después, vamos a aplicar el siguiente código CSS
.file-select { position: relative; display: inline-block; } .file-select::before { background-color: #5678EF; color: white; display: flex; justify-content: center; align-items: center; border-radius: 3px; content: 'Seleccionar'; /* testo por defecto */ position: absolute; left: 0; right: 0; top: 0; bottom: 0; } .file-select input[type="file"] { opacity: 0; width: 200px; height: 32px; display: inline-block; } #src-file1::before { content: 'Seleccionar Archivo 1'; } #src-file2::before { content: 'Seleccionar Archivo 2'; }
El resultado es el siguiente.
Y ahora viene la explicación.
Lo que realmente estamos haciendo, no es darle aspecto al elemento input. En realidad estamos dándole aspecto a un elemento que se encuentra justo encima, tapando el input. Para ello hemos usado position: absolute; El elemento que estamos colocando encima del input en realidad no existe en el código HTML. Este elemento lo estamos creando mediante CSS con el pseudoselector ::before.
Este pseudoselector nos permite añadir un hijo al principio del elemento en cuestión (en nuestro ejemplo, al principio de cada div de la clase file-select). Es como si dentro de esos elementos div tuviéramos un elemento span con el texto que indicamos en la propiedad CSS content dentro de dicho span imaginario. Obviamente, nada nos impide usar elementos span en lugar del pseudoselector ::before.
Ese span imaginario, lo colocamos encima del input gracias al position: absolute; Por eso en el div tenemos el correspondiente position: relative; necesario para poder usar el position: absolute; correctamente.
Finalmente, para asegurarnos de que el input no molesta, le ponemos un opacity: 0; para volverlo totalmente transparente.
Y ya está. Con este sencillo ejemplo hemos visto como darle un aspecto de botón uniforme entre diferentes navegadores a un elemento input de tipo file. Espero que os haya resultado interesante y nos vemos en el próximo artículo.
Ricardo
Me fue muy útil. Muchas gracias.
Kengya
me fué muy útil, ésta info gracias!!!
Emanuel
Hola a los dos les traigo aqui la solucion para lo de el nombre de el archivo revisen bien el codigo para que sea acorde con su css
jQuery(‘input[type=file]’).change(function(){
var filename = jQuery(this).val().split(‘\\’).pop();
var idname = jQuery(this).attr(‘id’);
console.log(jQuery(this));
console.log(filename);
console.log(idname);
jQuery(‘span.’+idname).next().find(‘span’).html(filename);
});
sergio gonzalez gonzalez
Hola. Lo primero, gracias. Veo una pega a tu solución y es que si se oculta el botón, también se oculta el nombre del archivo seleccionado y el usuario no sabe bien qué archivo es sobre el que va a operar. No sé si me explico…
Abel Camarena
Hola Sergio,
Efectivamente, eso se pierde. Pero si el usuario está inseguro siempre puede volver a elegir el archivo.
Una solución que muestre el nombre del archivo seleccionado, requiere del uso de JavaScript, y en este artículo quería limitarme a HTML y CSS.
Habría que eliminar este código CSS
#src-file1::before {
content: 'Seleccionar Archivo 1';
}
#src-file2::before {
content: 'Seleccionar Archivo 2';
}
Añadir este:
:root {
--fn: 'Seleccionar Archivo';
}
.file-select::before {
white-space: nowrap;
content: var(--fn);
}
Y después este código javascript
function actualizarInputFile() {
var filename = "'" + this.value.replace(/^.*[\\\/]/, '') + "'";
this.parentElement.style.setProperty('--fn', filename);
}
document.querySelectorAll(".file-select input").forEach((ele)=>ele.addEventListener('change', actualizarInputFile));