J'ai eu le même problème et j'ai finalement réussi à le résoudre de cette manière :
Comme d'autres l'ont expliqué, IE9+ et d'autres navigateurs reconnaissent la balise label. Vous pouvez donc régler l'opacité de l'entrée du fichier sur 0, puis avoir l'icône de l'image dans la même balise d'étiquette :
<label class="fileinput-button">
<img src="upload-icon.png" class="upload-icon"/>
<input class="file-input" type="file" name="files[]">
</label>
Voici le style CSS :
.file-input {
opacity: 0;
filter: alpha(opacity=0);
position: relative;
}
Mais dans IE8 et les versions inférieures, la balise label ne se comporte pas comme prévu. Donc, la solution dans ce cas serait de positionner votre image au dessus du bouton de saisie de fichier (assurez-vous qu'ils se chevauchent). Au début, je pensais utiliser le z-index pour positionner un élément devant l'autre. Mais j'ai lu ce blog qui est extrêmement utile pour comprendre le z-index : Ce que personne ne vous a dit sur le z-index
Vous n'avez donc pas besoin de travailler avec le z-index tant que votre icône d'image n'est pas positionnée et que l'entrée de fichier est positionnée (c'est-à-dire qu'elle a une valeur de position autre que "statique"). Ainsi, dans le style CSS .file-input, vous devriez jouer un peu avec les positions gauche et droite pour que l'image recouvre le bouton d'entrée de fichier dans une certaine mesure. Dans mon cas, l'image n'était pas positionnée et se trouvait à gauche du bouton d'entrée de fichier, j'ai donc dû déplacer le bouton d'entrée un peu plus à gauche :
.file-input {
opacity: 0;
filter: alpha(opacity=0);
position: relative;
left: -50px;
}