web-dev-qa-db-fra.com

Comment styliser "fichier d'entrée" avec CSS3 / Javascript?

Je voudrais styliser <input type="file" /> en utilisant CSS3.

Alternativement, je voudrais que l'utilisateur appuie sur un div (que je styliserai) et cela ouvrira la fenêtre Parcourir.

Est-il possible de le faire en utilisant uniquement HTML, CSS3 et Javascript/jQuery?

35
Misha Moroshko

J'ai cet exemple approximatif que vous voudrez peut-être avoir une idée ...

html

<div id="file">Chose file</div>
<input type="file" name="file" />​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

CSS

#file {
    display:none;
}​

jQuery

var wrapper = $('<div/>').css({height:0,width:0,'overflow':'hidden'});
var fileInput = $(':file').wrap(wrapper);

fileInput.change(function(){
    $this = $(this);
    $('#file').text($this.val());
})

$('#file').click(function(){
    fileInput.click();
}).show();

démo

La

51
Reigel

Après avoir vérifié l'idée de Reigels, et celle-ci , j'ai écrit cette solution simple au problème courant de styliser un type="file" champ de saisie (testé sur Firefox, Safari et Chrome).

<div style="position:relative;">
<div id="file" style="position:absolute;">Click here to select a file</div>
<input type="file" name="file" style="opacity:0; z-index:1;" onchange="document.getElementById('file').innerHTML = this.value;">
</div>

Ensuite, vous pouvez bien sûr styliser le div "fichier" comme vous le souhaitez.

Et si vous souhaitez utiliser un type="text" entrée au lieu d'un div, changez simplement innerHTML pour value:

<div style="position:relative;">
<input type="text" id="file" style="position:absolute;" placeholder="Click here to select a file">
<input type="file" name="file" style="opacity:0; z-index:1;" onchange="document.getElementById('file').value = this.value;">
</div>

Voici ma réponse originale en utilisant jQuery:

<div style="position:relative;">
<div id="file" style="position:absolute;">Click here to select a file</div>
<input type="file" name="file" style="opacity:0; z-index:1;" onchange="$('#file').text($(this).val());">
</div>
19
Sophivorus

Voici comment le faire en utilisant HTML, CSS et Javascript (sans aucun framework):

L'idée est d'avoir le <input type='file'> bouton caché et utiliser un mannequin <div> que vous définissez comme un bouton de téléchargement de fichier. En cliquant sur ce <div>, nous appelons le caché <input type='file'>.

Démo:

// comments inline
document.getElementById("customButton").addEventListener("click", function(){
  document.getElementById("fileUpload").click();  // trigger the click of actual file upload button
});

document.getElementById("fileUpload").addEventListener("change", function(){
  var fullPath = document.getElementById('fileUpload').value;
  var fileName = fullPath.split(/(\\|\/)/g).pop();  // fetch the file name
  document.getElementById("fileName").innerHTML = fileName;  // display the file name
}, false);
body{
  font-family: Arial;
}

#fileUpload{
  display: none; /* do not display the actual file upload button */
}

#customButton{  /* style the dummy upload button */
  background: yellow;
  border: 1px solid red;
  border-radius: 5px;
  padding: 5px;
  display: inline-block;
  cursor: pointer;
  color: red;
}
<input type="file" id="fileUpload"> <!-- actual file upload button -->
<div id="customButton">Browse</div>  <!-- dummy file upload button which can be used for styling ;) -->
<span id="fileName"></span> <!-- the file name of the selected file will be shown here -->
6
Rahul Desai

J'ai également créé un style personnalisé pour cela. Vérifiez-le

JS Fiddle Demo - Type d'entrée personnalisé = "fichier"

[~ # ~] html [~ # ~]

<input type="file" id="test">
<div class="button-group"> 
<a href="#" id="browse" class="button primary">Browse</a>
<a href="#" id="save" class="button">Save</a>
<a href="#" id="clear" class="button danger">Clear</a>
</div>
<input type="text" id="testfile"></input>

[~ # ~] css [~ # ~]

body {
padding:100px;
}
input[type="file"] {
position:absolute;
display:none;
}
#testfile {
height: 26px;
text-decoration: none;
background-color: #eee;
border:1px solid #ccc;
border-radius:3px;
float:left;
margin-right:5px;
overflow:hidden;
text-overflow:Ellipsis;
color:#aaa;
text-indent:5px;
}
#actionbtnBrowse, #actionbtnSave {
margin:0 !important;
width:60px;
}

JQuery

$("#browse").click(function () {
$("#test").click();
})

$("#save").click(function () {
alert('Run a save function');
})

$("#clear").click(function () {
$('#testfile').val('');
})

$('#test').change(function () {
$('#testfile').val($(this).val());
})

Ajoutez également à l'onglet des ressources externes:

https://github.com/necolas/css3-github-buttons/blob/master/gh-buttons.css

6
andibra

Le faux div n'est pas nécessaire! Pas de Js pas de html supplémentaire. L'utilisation de css uniquement est possible.

La meilleure façon est d'utiliser le pseudo-élément: après ou: avant comme élément sur l'entrée de dé. Stylisez ensuite ce pseudo-élément comme vous le souhaitez. Je vous recommande de faire comme un style général pour tous les fichiers d'entrée comme suit:

input[type="file"]:before {
  content: 'Browse';
  background: #FFF;
  width: 100%;
  height: 35px;
  display: block;
  text-align: left;
  position: relative;
  margin: 0;
  margin: 0 5px;
  left: -6px;
  border: 1px solid #E0E0E0;
  top: -1px;
  line-height: 35px;
  color: #B6B6B6;
  padding-left: 5px;
  display: block;
}

-> DÉMO

4
Despertaweb

En plus de Reigel,

voici une implémentation plus simple. Vous pouvez également utiliser cette solution sur plusieurs champs de saisie de fichier. J'espère que cela aide certaines personnes ;-)

HTML (entrée unique)

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

HTML (entrée multiple)

<!-- div is important to separate correctly or work with jQuery's .closest() -->
<div>
  <input type="file" name="file[]" />
</div>

<div>
  <input type="file" name="file[]" />
</div>

<div>
  <input type="file" name="file[]" />
</div>

Javascript

// make all input fields with type 'file' invisible
$(':file').css({
  'visibility': 'hidden',
  'display': 'none'
});

// add a textbox after *each* file input
$(':file').after('<input type="text" readonly="readonly" value="" class="fileChooserText" /> <input type="button" value="Choose file ..." class="fileChooserButton" />');

// add *click* event to *each* pseudo file button
// to link the click to the *closest* original file input
$('.fileChooserButton').click(function() {
    $(this).parent().find(':file').click();
}).show();

// add *change* event to *each* file input
// to copy the name of the file in the read-only text input field
$(':file').change(function() {
    $(this).parent().find('.fileChooserText').val($(this).val());
});
4
Patrick Hillert

Ran dans le même problème aujourd'hui, mais il semble qu'il existe un moyen facile d'avoir vos propres styles - masquer l'entrée et le style de l'étiquette associée:

<div class="upload">
  <label for="my-input"> Upload stuff </label>
  <input type="file" id="my-input" name="files[]" />
</div>

CSS:

.upload input{
  display: none;
}

.upload label{
  background: DarkSlateBlue;
  color: white;
  padding: 5px 10px;
}

Fonctionne dans les derniers Chrome, Firefox et IE 10. N'a pas testé les autres

2
nice ass

Bien que la réponse de Reigel transmette l'idée, elle n'a pas vraiment de style. J'ai rencontré ce problème récemment et malgré la pléthore de réponses sur Stack Overflow, aucune ne semblait vraiment correspondre à la facture. Au final, j'ai fini par le personnaliser afin d'avoir une solution simple et élégante.

J'ai également testé cela sur Firefox, IE (11, 10 & 9), Chrome et Opera, iPad et quelques Android appareils.

Voici le lien JSFiddle -> http://jsfiddle.net/umhva747/

$('input[type=file]').change(function(e) {
    $in = $(this);
    $in.next().html($in.val());
    
});

$('.uploadButton').click(function() {
    var fileName = $("#fileUpload").val();
    if (fileName) {
        alert(fileName + " can be uploaded.");
    }
    else {
        alert("Please select a file to upload");
    }
});
body {
    background-color:Black;
}

div.upload {
    background-color:#fff;
    border: 1px solid #ddd;
    border-radius:5px;
    display:inline-block;
    height: 30px;
    padding:3px 40px 3px 3px;
    position:relative;
    width: auto;
}

div.upload:hover {
    opacity:0.95;
}

div.upload input[type="file"] {
    display: input-block;
    width: 100%;
    height: 30px;
    opacity: 0;
    cursor:pointer;
    position:absolute;
    left:0;
}
.uploadButton {
    background-color: #425F9C;
    border: none;
    border-radius: 3px;
    color: #FFF;
    cursor:pointer;
    display: inline-block;
    height: 30px;
    margin-right:15px;
    width: auto;
    padding:0 20px;
    box-sizing: content-box;
}

.fileName {
    font-family: Arial;
    font-size:14px;
}

.upload + .uploadButton {
    height:38px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form action="" method="post" enctype="multipart/form-data">
    <div class="upload">
        <input type="button" class="uploadButton" value="Browse" />
        <input type="file" name="upload" accept="image/*" id="fileUpload" />
        <span class="fileName">Select file..</span>
    </div>
    <input type="button" class="uploadButton" value="Upload File" />
</form>

J'espère que cela t'aides!!!

2
Satwik Nadkarny

Voici un exemple que j'utilise qui utilise jQuery, j'ai testé contre Firefox 11 et Chrome 18, ainsi que IE9. Donc, il est assez compatible avec les navigateurs de mon livre, bien que je ne fonctionne qu'avec ces trois-là.

HTML

Voici une structure HTML de base "personnalisable".

<span>
    File to Upload<br />
    <label class="smallInput" style="float:left;">
        <input type="file" name="file" class="smallInput" />
    </label>
    <input type="button" class="upload" value="Upload" style="float:left;margin-top:6px;margin-left:10px;" />
</span>

CSS

Voici un échantillon de mon CSS

label.smallInput {
    background:url(images/bg_s_input.gif) no-repeat;
    width:168px;
}

Javascript

Ceci est le lève-personne lourd.

/* File upload magic form?? */
$("input.smallInput[type=file]").each(function(i){
    var id      = "__d_file_upload_"+i;
    var d_wrap  = $('<div/>').attr('id',id).css({'position':'relative','cursor':'text'});

    $(this).wrap(d_wrap).bind('change blur focus keyup click',function(){
        $("#"+id+" input[type=text]").val($(this).val());
    }).css({'opacity':0,'zIndex':9999,'position':'absolute'}).removeClass('smallInput');

    obj = $(this);

    $("#"+id).append($("<input/>").addClass('smallInput').attr('type','text').css({'zIndex':9998,'position':'absolute'}).bind('click',function(e){obj.trigger('click');$(this).blur();}));
    obj.closest('span').children('input.upload[type=button]').bind('click',function(e){
        obj.trigger('click');
        $(this).blur();
    });
});
/* ************************ */

Explication

Le HTML est assez simple, juste un élément simple, j'inclus le bouton pour qu'il puisse être nommé indépendamment des autres, bien sûr, cela pourrait être inclus dans le JavaScript, mais simplement, je suis un peu paresseux. Le code recherche tous entrées avec une classe smallInput qui ont le type de fichier ceci vous permet de définir la structure par défaut du HTML et du formulaire de secours dans cas où un navigateur décide d'être une douleur.

Cette méthode utilise uniquement JavaScript pour garantir la livraison, elle ne modifie aucun comportement du navigateur en ce qui concerne l'entrée du fichier.

Vous pouvez modifier le HTML et le JavaScript pour le rendre très robuste, ce code suffit à mon projet actuel, donc je doute que je vais y apporter des modifications.

Avertissements

  • Différents navigateurs traitent la valeur de l'entrée de fichier différemment, ce qui en chrome résulte en c:\fakeroot\sur les machines Windows.
  • Utilise des fonctions anonymes, (faute d'un meilleur mot), ce qui signifie que si vous avez trop d'entrées de fichiers, vous pouvez faire en sorte que le navigateur se comporte lentement lors du traitement.
2
Destreyf

C'est ma méthode si j'ai compris

[~ # ~] html [~ # ~]

<form action="upload.php">
    <input type="file" id="FileInput" style="cursor: pointer;  display: none"/>
    <input type="submit" id="Up" style="display: none;" />
</form>

jQuery

<script type="text/javascript">
    $( "#FileInput" ).change(function() {
      $( "#Up" ).click();
    });
</script>
1
SystemDZ

Voici une solution avec un champ de texte où l'utilisateur tape le chemin d'accès (relatif) de la copie de fichier sur le serveur (si autorisé) et un bouton d'envoi pour parcourir le système local pour un fichier et envoyer le formulaire:

<form enctype="multipart/form-data" action="" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
<p><input type="file" name="upload_file" id="upload_file" size="40"/></p>
<p><input type="text" id="upload_filename" name="upload_filename" size="30" maxlength="100" value="<?php echo htmlspecialchars($filename, ENT_COMPAT, 'UTF-8'); ?>"/>
<input type="submit" class="submit submit_upload" id="upload_upload" name="upload_upload" value="Upload"/></p>
</form>

La partie de script masque l'entrée du fichier, clique dessus si l'utilisateur clique sur le bouton soumettre, soumet le formulaire si l'utilisateur a récupéré un fichier. Si l'utilisateur essaie de télécharger un fichier sans entrer de nom de fichier, le focus est d'abord déplacé vers le champ de texte du nom de fichier.

<script type="text/javascript">
var file=$('#upload_file');
var filename=$('#upload_filename');
var upload=$('#upload_upload');

file.hide().change(function() {if (file.val()) {upload.unbind('click').click();}});

upload.click(function(event) {event.preventDefault();if (!filename.val()) {filename.focus();} else {file.click();}});
</script>

Stylisez simplement le bouton de soumission pour un résultat parfait:

.submit {padding:0;margin:0;border:none;vertical-align:middle;text-indent:-1000em;cursor:pointer;}
.submit_upload {width:100px;height:30px;background:transparent url(../images/theme/upload.png) no-repeat;}
1
frasq