132

Like a lot of people, I'd like to customize the ugly input type=file, and I know that it can't be done without some hacks and/or javascript. But, the thing is that in my case the upload file buttons are just for uploading images (jpeg|jpg|png|gif), so I was wondering if I could use a "clickable" image which would act exactly as an input type file (show the dialog box, and same $_FILE on submitted page).
I found some workaround here, and this interesting one too (but does not work on Chrome =/).

What do you guys do when you want to add some style to your file buttons? If you have any point of view about it, just hit the answer button ;)

Jai Chauhan
  • 4,035
  • 3
  • 36
  • 62
Nicolas
  • 2,754
  • 6
  • 26
  • 41
  • 2
    For everyone landing here, http://tympanus.net/codrops/2015/09/15/styling-customizing-file-inputs-smart-way/ might also be worth a look. (Not affiliated with that site in any way, shape or form.) – CBroe Apr 20 '16 at 14:40
  • You can check [**How to make photo to work as input type file?**](https://stackoverflow.com/a/52334430/3669624). – cнŝdk Sep 19 '18 at 07:16

14 Answers14

365

This works really well for me:

.image-upload>input {
  display: none;
}
<div class="image-upload">
  <label for="file-input">
    <img src="https://icons.iconarchive.com/icons/dtafalonso/android-lollipop/128/Downloads-icon.png"/>
  </label>

  <input id="file-input" type="file" />
</div>

Basically the for attribute of the label makes it so that clicking the label is the same as clicking the specified input.

Also, the display property set to none makes it so that the file input isn't rendered at all, hiding it nice and clean.

Tested in Chrome but according to the web should work on all major browsers. :)

EDIT: Added JSFiddle here: https://jsfiddle.net/c5s42vdz/

hardsetting
  • 4,030
  • 1
  • 16
  • 10
  • i'm not sure if people still consider it a 'major browser', but this doesn't seem to work in IE7 – Hoppe Nov 13 '13 at 20:21
  • @Chet it seems to be working on the latest versions of Safari (7+) Which version are you using? – hardsetting Aug 07 '14 at 07:51
  • 1
    @Toto For me it's working in IE11, I've added a JSFiddle so you can check it as well. – hardsetting Oct 03 '15 at 18:03
  • @hardsetting You are right! Sorry (Maybe I was in a different document mode, ie8 or lower) – Toto Oct 04 '15 at 14:08
  • 2
    sorry but I think this code must be updated with the filename or at least a message that the file has been selected successfully. The user has no visual input on what happened after he selected the file. Could this be done please? Perhaps change to a different image, when a file is chosen? – JoaMika Dec 12 '15 at 22:24
  • 1
    I'm curious, how accessible is this? – Charming Robot Aug 12 '21 at 21:10
  • @hard I Want To Thank you for an elegant simple example. And you explained what makes it work. And I was just wrecking my mind about how I was going to stuff and Image as a placeholder for a input of type file. And I am a consistent user of label tag with all inputs. – IT Serenity Jan 22 '22 at 06:25
  • Dope answer and explanation. Very simple and concise – Deji James Aug 16 '22 at 22:30
69

Actually it can be done in pure css and it's pretty easy...

HTML Code

<label class="filebutton">
Browse For File!
<span><input type="file" id="myfile" name="myfile"></span>
</label>

CSS Styles

label.filebutton {
    width:120px;
    height:40px;
    overflow:hidden;
    position:relative;
    background-color:#ccc;
}

label span input {
    z-index: 999;
    line-height: 0;
    font-size: 50px;
    position: absolute;
    top: -2px;
    left: -700px;
    opacity: 0;
    filter: alpha(opacity = 0);
    -ms-filter: "alpha(opacity=0)";
    cursor: pointer;
    _cursor: hand;
    margin: 0;
    padding:0;
}

The idea is to position the input absolutely inside your label. set the font size of the input to something large, which will increase the size of the "browse" button. It then takes some trial and error using the negative left / top properties to position the input browse button behind your label.

When positioning the button, set the alpha to 1. When you've finished set it back to 0 (so you can see what you're doing!)

Make sure you test across browsers because they'll all render the input button a slightly different size.

meles
  • 315
  • 1
  • 4
  • 13
  • Thanks Toby, why is there 'left: -700px;' ? In firefox the file input field is actually floating by the left side of a page...it doesn't stick to the label span ... If I remove 'left: -700px;' it works fine – lisak May 25 '11 at 09:05
  • +1 Thanks, @Sloin left:-700px because he wanted to get the browse button to be over the button so the cursor will be a pointer and not the text cursor. – Caleb Doucet Sep 19 '12 at 18:28
22

Great solution by @hardsetting, But I made some improvements to make it work with Safari(5.1.7) in windows

.image-upload > input {
  visibility:hidden;
  width:0;
  height:0
}
<div class="image-upload">
  <label for="file-input">
    <img src="https://via.placeholder.com/300x300.png?text=UPLOAD" style="pointer-events: none"/>
  </label>

  <input id="file-input" type="file" />
</div>

I have used visibility: hidden, width:0 instead of display: none for safari issue and added pointer-events: none in img tag to make it working if input file type tag is in FORM tag.

Seems working for me in all major browsers.

Hope it helps someone.

Muhammad Atallah
  • 976
  • 2
  • 12
  • 34
rishi
  • 359
  • 2
  • 6
18

A much better way than writing JS is to use native, and it turns to be lighter than what was suggested:

<label>
  <img src="my-image.png">
  <input type="file" name="myfile" style="display:none">
</label>

This way the label is automatically connected to the input that is hidden. Clicking on the label is like clicking on the field.

vinyll
  • 11,017
  • 2
  • 48
  • 37
7

You can replace image automatically with newly selected image.

<div class="image-upload">
      <label for="file-input">
        <img id="previewImg" src="https://icon-library.net/images/upload-photo-icon/upload-photo-icon-21.jpg" style="width: 100px; height: 100px;" />
      </label>

      <input id="file-input" type="file" onchange="previewFile(this);" style="display: none;" />
    </div>




<script>
        function previewFile(input){
            var file = $("input[type=file]").get(0).files[0];

            if(file){
              var reader = new FileReader();

              reader.onload = function(){
                  $("#previewImg").attr("src", reader.result);
              }

              reader.readAsDataURL(file);
            }
        }
    </script>
Everything good
  • 321
  • 4
  • 10
6

This is my method if i got your point

HTML

<label for="FileInput">
    <img src="tools/img/upload2.png" style="cursor:pointer" onmouseover="this.src='tools/img/upload.png'" onmouseout="this.src='tools/img/upload2.png'" alt="Injaz Msila" style="float:right;margin:7px" />
</label>
<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>
SystemX
  • 481
  • 4
  • 10
6

I would use SWFUpload or Uploadify. They need Flash but do everything you want without troubles.

Any <input type="file"> based workaround that tries to trigger the "open file" dialog by means other than clicking on the actual control could be removed from browsers for security reasons at any time. (I think in the current versions of FF and IE, it is not possible any more to trigger that event programmatically.)

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • Thanks, I've seen them around too, but I think that both of them need a flash player to work, and I do not want to add another mandatory layer to users. Plus are you sure that they will send the exact same type of data as the input file ones do? I do not want to retest all my PHP done in the submit page. Cheers. – Nicolas May 18 '10 at 08:43
  • @niko no, they work differently, they are not form elements but send the file to a receiving script on their own, so you would probably have to change your script's workflow. If that's not an option, I think you can't do better than Shaun Inman did in the post you link to... – Pekka May 18 '10 at 08:45
  • I'm afraid so then, that's really a shame. Isn't there anything about it in future CSS implementation? Thanks for the replies anyway :) – Nicolas May 18 '10 at 08:47
  • @niko you're welcome. Good question about the CSS - I don't know actually, but HTML 5 may well bring new things here. Check out http://www.appelsiini.net/2009/10/html5-drag-and-drop-multiple-file-upload for example. – Pekka May 18 '10 at 08:48
  • Yeah it seems promising even if the demo http://www.appelsiini.net/demo/html5_upload/demo.html does not display with my FF 3.6.3 whereas it says I do need FF 3.6.x Anyway, to go back to my issue, currently HTML/CSS/Javscript (but no flash) only allow me to do what? Some fonts and "color" customization? Am I right then? Cheers. – Nicolas May 18 '10 at 08:57
  • @niko here's a good overview on workarounds: http://www.quirksmode.org/dom/inputfile.html with the limitation that they don't work on Chrome - I don't know what the state of things is there. – Pekka May 18 '10 at 09:01
  • Yeah I forgot to mention that page, which could be the better solution in my case, but the issue with erasing the image chosen plus some limitations on old browsers make me a little reluctant. Btw I don't see any trouble on Chrome 4.1 :) – Nicolas May 18 '10 at 09:10
5

I have had lots of issues with hidden and not visible inputs over the past decade sometimes things are way simpler than we think.

I have had a little wish with IE 5,6,7,8 and 9 for not supporting the opacity and thus the file input would cover the upload image however the following css code has resolved the issue.

-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);  

The following snipped is tested on chrome, IE 5,6,7,8,9,10 the only issue in IE 5 is that it does not support auto margin.

Run the snippet simply copy and paste the CSS and HTML modify the size as you like.

.file-upload{
 height:100px;
 width:100px;
 margin:40px auto;
 border:1px solid #f0c0d0;
 border-radius:100px;
 overflow:hidden;
 position:relative;
}
.file-upload input{
 position:absolute;
 height:400px;
 width:400px;
 left:-200px;
 top:-200px;
 background:transparent;
 opacity:0;
 -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
 filter: alpha(opacity=0);  
}
.file-upload img{
 height:70px;
 width:70px;
 margin:15px;
}
<div class="file-upload">
<!--place upload image/icon first !-->
<img src="https://i.stack.imgur.com/dy62M.png" />
<!--place input file last !-->
<input type="file" name="somename" />
</div>
codedudey
  • 369
  • 3
  • 10
4

its really simple you can try this:

$("#image id").click(function(){
    $("#input id").click();
});
Zicsus
  • 1,115
  • 1
  • 9
  • 19
3

You can put an image instead, and do it like this:

HTML:

<img src="/images/uploadButton.png" id="upfile1" style="cursor:pointer" />
<input type="file" id="file1"  name="file1" style="display:none" />

JQuery:

$("#upfile1").click(function () {
    $("#file1").trigger('click');
});

CAVEAT: In IE9 and IE10 if you trigger the onclick in a file input via javascript the form gets flagged as 'dangerous' and cannot be submmited with javascript, no sure if it can be submitted traditionaly.

ParPar
  • 7,355
  • 7
  • 43
  • 56
2

Working Code:

just hide input part and do like this.

<div class="ImageUpload">
   <label for="FileInput">
      <img src="../../img/Upload_Panel.png" style="width: 18px; margin-top: -316px; margin-left: 900px;"/>
   </label>

  <input id="FileInput" type="file" onchange="readURL(this,'Picture')" style="cursor: pointer;  display: none"/>
</div>
user3400389
  • 367
  • 1
  • 6
  • 21
2

        form input[type="file"] {
          display: none;
        }
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>

<head>
  <title>Simple File Upload</title>
  <meta name="" content="">
</head>

<body>
  <form action="upload.php" method="post" enctype="multipart/form-data">
    Select image to upload:
    <label for="fileToUpload">
      <img src="http://s3.postimg.org/mjzvuzi5b/uploader_image.png" />
    </label>
    <input type="File" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
  </form>
</body>

</html>

RUN SNIPPET or Just copy the above code and execute. You will get what you wanted. Very simple and effective without javascript. Enjoy!!!

Neocortex
  • 653
  • 9
  • 32
2

The input itself is hidden with CSS visibility:hidden.

Then you can have whatever element you whish - anchor or image.., when the anchor/image is clicked, trigger a click on the hidden input field - the dialog box for selecting a file will appear.

EDIT: Actually it works in Chrome and Safari, I just noticed that is not the case in FF4Beta

Petrunov
  • 754
  • 1
  • 8
  • 18
0
<script type="text/javascript">
function upl() {
    var fileSelector = document.createElement('input');
    fileSelector.setAttribute('type', 'file');
    fileSelector.setAttribute('name', 'uploimg');
    fileSelector.setAttribute('accept', 'image/*');
    fileSelector.click();
    fileSelector.style.display = "none";

    fileSelector.onchange = function() {
        document.getElementById("indicator").innerHTML = "Uploaded";
    };

    document.getElementById("par_form").appendChild(fileSelector);

}
</script>

<form id="par_form">
    <img src="image_url" onclick="upl()"><br>
    <span id="indicator"></span><br>
    <input type="submit">
</form>
Jigar K
  • 1
  • 4
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 08 '22 at 08:47