4

I want to change the style of my input and browse button for uploading files on my website, and have been reading how this is virtually impossible to do. There are apparently a couple of hacks that may work (not tested) but before I waste time on them I have questions on why professional sites seem to have no problems with it.

When I say professional, I mean job hunting sites where you can upload your resume, programming sites where you can upload your scripts, my colleges website where I could upload test papers, government, doctors, etc. etc.

I can't see them using a hack from some random programmer that may or may not work, so what are they doing as their websites seem to work and look good?

Any input on this would be appreciated.

Thanks

Beauford


Follow up:

Thanks for the input, but just a note to Yi Jiang - the ones you have posted certainly look styled in some way. I have one on my site and have looked at it in 5 browsers and all I get is the basic square grey browse button and square input field with no space between the two, and the browse button is just a tad bit taller than the input field, so it looks really shabby. If I could get it to look like your examples I would be ecstatic.

Thanks

Aiden Bell
  • 28,212
  • 4
  • 75
  • 119
Beauford
  • 81
  • 1
  • 4
  • They are using hacks too, nothing special. – NullUserException Oct 09 '10 at 01:09
  • 2
    step 1. Find said site with customized input filetype. Step 2. Inspect the source code. If you don't understand, post the site's link on SO and ask how it's done. Generally though, any of the solutions will be "dirty". – meder omuraliev Oct 09 '10 at 01:10
  • A lot of websites use flash for file uploading, so they can style it however they want and so they can have a progress bar. HTML5 has support for progress bars now though. – Telanor Oct 09 '10 at 01:12
  • What NullUserException said; just (hopefully) well-tested hacks. You can find, for example, some jQuery plugins and the line. Also, some will use Flash/Java. – Andrew Barber Oct 09 '10 at 01:12
  • This plugin hides the fileupload box, and it also lets the user drag and drop files into the browser if it works: http://github.com/valums/file-uploader You could look at how it is done there. – SeanJA Oct 09 '10 at 01:21
  • @Beauford Yi Jiang is using Ubuntu. Those are the system's default upload controls. – NullUserException Oct 10 '10 at 07:43
  • 1
    possible duplicate of [Styling an input type="file" button](http://stackoverflow.com/questions/572768/styling-an-input-type-file-button) – Shadow The GPT Wizard Sep 03 '13 at 14:19

3 Answers3

4

The file upload field cannot be styled (very much) in CSS, and cannot be scripted from JS (enough to make a surrogate control actually work). There are somewhat-sensible security reasons why this is the case, though you might argue they have been taken a bit too far.

More generally, it's difficult to style a file upload field anyway, because you don't know what a file upload field looks like. It's all up to the browser. Maybe you'll get a text field on the left and a ‘Browse’ button/popup on the right (in that case, which part does the border apply to? Or around both?); maybe you'll get just a popup on the left and a status icon/label on the right (like in Safari); maybe you'll just get a drag-and-drop field. Or something else. It's totally out of your control.

Most ‘professional’ sites do one of two things:

  1. Don't care about it, just use a plain unstyled file upload field. Perhaps in a pop-up div when you request to upload (so at least it's not being inconsistent on-screen at all times).

  2. Use a progressive-enhancement technique to replace the HTML file upload with an alternative uploader based around Flash (or less commonly Java or Silverlight; in the future we'll have more browsers with support for HTML5 drag-and-drop).

There is a hack detailed here that works by making the real file upload control invisible and positioning it over the top of a stylable display control. But it's really pretty unreliable, depending on a guess of what size the browser's file upload control will be and what bits will respond to a click. It's bad for accessibility (doesn't respond to keyboard correctly), bad for usability (it doesn't even line up on my perfectly normal Firefox) and I wouldn't recommend using it at all.

bobince
  • 528,062
  • 107
  • 651
  • 834
3

Well, first of all these hacks arn't just from any 'ol random programmer. This one from quirksmode, for instance, is from a well respected source and, as far as I can tell, widely used (It's used here for the image upload dialog). Another example is this one created for the ajax upload script. Ignoring the Javascript completely, you can see that the button is purely a input type="file" stuck inside a div.

It's worth noting, however, that there's nothing there that you can't live with. Even large sites use plain, unstyled file inputs. This is from Hotmail

alt text

And this is from GMail

alt text

Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
0

Posting in this thread because it's old, outdated and because others (like me) may find it from Google and wonder what they can do to create better looking input[type=file] boxes!

The short answer is still: You can't.

However, you CAN actually make a pretty good stab at making something you can style, and then controlling the file input appropriately, if you're prepared to use a little JavaScript.

First up, HTML along these lines:

<a href="#" class="btn btn-upload">Choose your photo</a>
<div class="fileupload">
    <label for="picture">Your Image:</label>
    <input type='file' name="picture" id="picture" enctype = "multipart/form-data" runat="server" required />
</div>

This allows you to use the fileupload div to 'hide' the real control - However, you SHOULD NOT use display:none - Many browsers will see this as a security risk. Instead, try position:relative with left:-99999px, or a height:0px with overflow:hidden. If you need to turn this off for any reason (Such as needing to support really old IE) then you can use an IE stylesheet or Modernizr and reverse the css to show the normal upload and hide your 'fake'.

Now, style your btn-upload appropriately. However you want it.

Use JavaScript to click the input file for you, when someone clicks your 'fake' (The following assumes you use jQuery):

    $(".btn-upload").click(function () {
        $(".fileupload input").trigger('click');
        return false;
    });

What's more, if you want to alter the appearance of your styled file input fake, or have your page react in any way when a user has selected a file, you can do so by using the change event. The following example will display the image a user is about to upload, in an img tag with an id of image-preview (This won't work in IE below 10):

    $('input[type=file]').change(function () {
        var input = $(this);
        if (input[0].files && input[0].files[0]) {
            var reader = new FileReader();

            reader.onload = function (e) {
                $('#image-preview')
                       .attr('src', e.target.result);
            };

            reader.readAsDataURL(input[0].files[0]);
        }
    });

You can also get access to the filename if you want to use javascript to display it somewhere:

$('input[type=file]').change(function () {
    var input = $(this);
    if (input[0].files && input[0].files[0]) {
        var file = input[0].files[0]
        if (file) {
           //Put the file name into a div with the id of 'filename'
           $('#filename').html(file.name);
        }

    }
});

Using all of this, you can make a pretty good upload button which looks really nice and still works. I also recommend using feature detection and hiding all of this on browsers where file uploading is not supported (LOOKING AT YOU, OLD IOS!)

Example of file upload function detection:

function checkForInputFile() {
    var elem = document.createElement("input");
    elem.type = "file";
    if (elem.disabled) return false;
    try {
        elem.value = "Test"; // Throws error if type=file is implemented
        return elem.value != "Test";
    } catch(e) {
        return elem.type == "file";
    }
}

if(checkForInputFile()){
    console.log('i support file input type!');
} else {
    console.log('i dont :(');
}

( The above is based on the correct answer here: Detect if <input type="file" /> is supported )

Finally, what if we want a button to CLEAR a file type input? Well, again, for security reasons, this isn't easy. But it is possible! This solution is my favourite: Clearing <input type='file' /> using jQuery

And if you're too lazy to open the link, here's an example of that approach, using my example html, assuming we add a link with the id remove-file somewhere on the page:

function resetFormInputElement(e){
    e.wrap('<form>').closest('form').get(0).reset();
    e.unwrap();
}
$('a#remove-file').click(function () {
    //Clear input file
    resetFormInputElement($('.fileupload input'));
    return false;
});
Community
  • 1
  • 1
Newnab
  • 811
  • 1
  • 7
  • 7
  • Nice, but there's already many answers [here](http://stackoverflow.com/q/572768/447356), this question should have been closed as duplicate of that other question. :) – Shadow The GPT Wizard Sep 03 '13 at 14:22