96

Simple question... How do I change the cursor type on a file input type?

I've tried the following:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
    <head>
        <style>
            input[type="file"] {
              cursor: pointer;
            }
        </style>
    </head>
    <body>
        <input type="file">
    </body>
</html>

For some reason, it won't play ball.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tisch
  • 2,598
  • 4
  • 27
  • 34
  • 2
    This answer works: http://stackoverflow.com/a/8667296/123545 – ErJab Jan 13 '12 at 23:17
  • 1
    [This answer](http://stackoverflow.com/a/9182787/109392) works perfectly for all major browsers. – awe Mar 07 '12 at 14:32
  • 1
    [this answer](http://stackoverflow.com/a/21842275/1256925) explains how to apply any kind of custom styling to file inputs, without having to use 'hacky' CSS. – Joeytje50 May 25 '14 at 21:52
  • accepted answer changed to reflect modern techniques – Tisch Feb 29 '16 at 16:51
  • `.file-label{ left:0px; position:relative; cursor: pointer; }` ` ` works like a charm on chrome and ie – jsPlayer Aug 11 '17 at 17:27
  • As detailed below, `font-size: 0;` was all I needed. – pjdavis Jun 29 '19 at 20:56

14 Answers14

69

Know this a old thread. But the google results brings this up... I Just found a partial solution to chrome (not invalving flash, javascript, extra DOM manipulation with overflow hidden)

  • firefox has fixed this bug
  • safari (7 at this moment) and chrome dosen't have identical behavior
  • safari (7, mac) dosen't work at all for me
  • chrome (and maybe opera now when it's webkit) can use ::webkit-file-upload-button pseudo-class

.

input[type=file], /* FF, IE7+, chrome (except button) */
input[type=file]::-webkit-file-upload-button { /* chromes and blink button */
    cursor: pointer; 
}

The problem is that button's doesn't inherit the cursor property in general(?) but the rest of the input[type=file] field dose. Thats why chrome get the pointer except the button

Community
  • 1
  • 1
Endless
  • 34,080
  • 13
  • 108
  • 131
58

cursor:pointer does not work on input file just because of the default button. No special reason here. You need to remove its appearance via this code, pay attention with font-size:0.

input[type='file']{
    opacity: 0;
    cursor: pointer;
    width: 24px;
    height: 24px;
    font-size: 0;
    position: absolute;
}
<input type="file">
<img width="24" height="24" title="" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAADs0lEQVR42rWVa2iOYRjH9+zd+dw2oWaGwkjzRY5flDC1nBaxsTnVYkaWc8oHoZalETWHsVGkZo0yIyEmGzkWpZhDbBhmxE7v63fp/0j7YGq89e/+XfdzuJ7/dV/3/Tp+//nndHdD2o4RIQHBnilgIPL3+XytjuO0MkZ4O3zllevve3uUYMaulDxeePL0mruNXeaTmJ/IfMlfJZhekBLv+PuNBEPRq8427wN/jxPmeJxM4seoAH0yF+g9WonmVOTfK+o2weTNyZ6w2KC9fNFuQtz7AuF0+DV8Ft4GZ6OvxPXE7xlLGZ8wF4CLK39MMLNwZDoPJPPAHcJwOAiOhp/Ct+Ba3d9J/I3YEjUzTmNuNuwHd8DtcAg8FK4ica2jeuYyFKM4cyB1aGEz0BoUYw6QLWoEakLLUY25UOl+foSubaB8O1wHmWS+R+YadUojbEmi4WjYo4Rv5SCWMdic2LzYEjfBAXAynImDI78nqOXCWcIk2KsHgmB/+ARs6/BE8UDGuYw5KmkbfA5O1QckwfNJUOqWaCnDdVRuL5WsXO1oobrIXpYgJ9W6N9VKgdZRjmreUwqPReYgg7mjroMlZL5K5v2E8XA/2JKshc9okfui78QNxLaYdxgteQkcCVfCW+HX8LiuDqwFr6Ey1B/1Rm/QMJSP8lCkus4cNNheQbt032G5s4+qR8PRIhwccB1kk/kmmSsIB8GdcDVfkEbyU/B45ntZt3Ctg9icfGQ8zdwW+AY8WG36UA7m8XyZm2CxbrqkElmC2/AE+DKcCMeaC/W8nUUtWthVcJ0WtlXNMhmeS4LjXbvoolmF22ErwSh4BTzTuguFaRPadm9iXG0NAFfA1hQvtEaT4CwSHHLXYBHDLWQJ4lXnp2ifuuUYStRC2zPB6LwdYagQzdImeydNtaOFNTjoOsiSTXuot3q9BW6Bc+E62Hb7EOJQ4irGYsY5zO2E4+FmrYE5GA0vsJPWTbBMtbZWG6AyeJXgkxbTDsKXWoPBKp3tn2DY0c5vhp/BY7TIv9p0idrUNlAfnS3uUW6J3uqsaZM8OnPsQAyRfLr3g1rd2rTYdZAjB0WyGadzphHuBQfqhd+I39jX6p5OObCjIspaWQ7NQQ4OitwEm7hQRMYvfv/gx/vM2UIS7HFLtFG7tUUd1C67Udqdn63HVYpoufmuebtuR/kXlS9cu3w7H3zBTWB/laOxlqDNlABbu37VUWw9bn+lIdrBnxljbMPpno/6w7Hj/B383E4GEjzq9k+/p78fan0xNyGwEGgAAAAASUVORK5CYII=" />

It works perpectly on Chrome, Firefox and IE.

Lewis
  • 14,132
  • 12
  • 66
  • 87
  • At the time the question was posted, this did not work in FireFox (version 3.5). It works now, as they have fixed it at some point. I don't know which version this changed. – awe Jul 16 '14 at 09:27
  • 1
    This doesn't work for me on Chrome, version 37.0.2062.94 – dshap Aug 27 '14 at 21:09
  • 3
    This doesn't really solves the problem as the input button is still present on the top left of the image and the cursor still changes back to the default when hovering. You can confirm this by deactivating the opacity styling via the dev tools. – Emile Bergeron May 08 '15 at 21:49
  • 1
    Add text-indent: -100px; to properly hide the cursor on top left part of the button as well. – Gimi Jan 28 '19 at 16:53
  • YOU ARE AWESOME!!!! IT WORKS LIKE CHARM, THANK YOU. SPECIALLY FONT-SIZE:0PX; – Kamlesh Sep 27 '19 at 09:43
  • Almighty God @Lewis – Ishan Patel May 05 '21 at 22:41
  • This actually works! Especially, the `font-size: 0`. If that is not the case, other solution is to hide the file input from the view & click it through javascript, on button click. – Tamil Vendhan Kanagarasu Dec 30 '21 at 08:40
40

It works differently in different browsers. I guess it's because the file input type is quite special.

What browser/version do you use?

I know that IE6 does not support to specify the type in the style.

How it works in the different browsers

IE7+

Works perfectly.

FireFox

Issue is fixed, so now it works perfectly. See bug report on this issue.
In version 3.5 it did not work at all.

Chrome and Safari (identical behavior)

Uses arrow over the button, but your defined cursor over the rest.

Opera

Works perfectly.


Note that there are several workarounds using different techniques that will come around this problem. The answer by BjarkeCK is one elegant solution that I like, and it works on all major browsers.

Community
  • 1
  • 1
awe
  • 21,938
  • 6
  • 78
  • 91
  • 1
    the problem does not only come from [type] behavior. – enguerran Oct 08 '09 at 12:59
  • @enguerran: You are right. It is only IE6 that has problem with that. The issues for the others are only related to setting the cursor style for the ´` element, regardless of setting it in a global style section/file, or in a style parameter directly on the html tag. – awe Oct 09 '09 at 05:29
  • 1
    uggg it seems like there should be some fancy webkit css3 rule to override chrome not doing this.....it would be really sad if your first experience with css had IE do something chrome didn't.... – Rooster Apr 27 '12 at 14:06
  • This answer is not so right. Take a look at my answer down here http://stackoverflow.com/a/24488438/3247703. – Lewis Jun 30 '14 at 11:02
  • I've changed the accepted answer to more closely reflect solutions that are available at this time. Things have moved on quite a bit since then. – Tisch Feb 29 '16 at 16:51
33

I met this issue today and with:

/* Chrome/Safari and web-kit-based browsers 
   (if it doesn't work, try maybe also on the parent/wrapper)
*/
::-webkit-file-upload-button {
    cursor:pointer;
}

/* IE11 (if it doesn't work, try maybe also on the parent/wrapper) */
input[type=file] {
    cursor:pointer;
}

It seems to do fine :-)

madtyn
  • 1,469
  • 27
  • 55
12

If you want to force the cursor to be hand in order to put it on an image, here is a

SIMPLE WAY AND HOW IT WORKS IN ALL BROWSERS:

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');
});

Then you can press on any button to upload file, and you have a pointer cursor .


In Chrome and Opera the cursor becomes a pointer on the padding only and if display:block; , that's why for those browsers you should do this:

<input type="file" id="file1"  name="file1" style="display:block; padding:29px 0 0 0;" />
ParPar
  • 7,355
  • 7
  • 43
  • 56
  • 2
    doesn't work in chrome and Opera: http://jsfiddle.net/LWHbs/1/ . Really shouldn't work in any browser for security reasons, but there we go. – ThatGuy Jan 16 '12 at 07:02
  • @nix Thanks, I will update it. – ParPar Jan 16 '12 at 15:20
  • 8
    Since this does NOT work in Chrome and Opera, you should remove "WORKS IN ALL BROWSERS" from your header text! – awe Mar 06 '12 at 09:16
  • @awe Now, When it fixed, can you please undo the vote down ? Thanks – ParPar Mar 07 '12 at 08:58
  • When proposing a sollution that is different html for different browsers, you should also propose what's needed to implement it including check for which version to use. Ideally it should not be a simple check on browser identification, because that might not be good enough. Some browsers have an option to identify itself as another browser, and the behaviour might change in later versions. This means you have to check for the behavior of required functionality. Then it seems that this method might not be a "simple way" after all... – awe Mar 07 '12 at 10:18
  • 2
    @awe This is the most simple way in the subject and obviously better than "FIREFOX - Does not work at all." – ParPar Mar 07 '12 at 12:23
  • 1
    i have tried this in chrome on mac and it works WITHOUT the padding display:block move. Just use the jQuery and display:none is sufficient for Chrome on Mac v22. You should update it if it also works for Chrome in Windows. – Kim Stacks Oct 03 '12 at 02:06
  • -1: See [this link](https://github.com/blueimp/jQuery-File-Upload/wiki/Style-Guide#why-isnt-it-possible-to-programmatically-trigger-the-file-input-selection) for why. – Chris Pfohl May 17 '13 at 17:07
  • @ParPar: I just explained how the CSS style is implemented in the different browsers. I did not say that it is not possible to come up with alternative solutions using workarounds. It is not my fault that my answer is heavily up-voted and selected as the accepted answer... I up-voted the [answer by BjarkeCK](http://stackoverflow.com/a/9182787/109392) that actually works in all browsers with same code for all. – awe Jul 30 '13 at 13:18
  • this does not work in IE9- I get a security error. – chovy Aug 07 '14 at 22:18
7

I made the following:

<li>file<input id="file_inp" type="file" /></li>

for li:

li { /*...*/ position:relative; overflow:hidden; /*...*/ }

for input:

input#file_inp { 
    /*...*/ 
    position: absolute; 
    width: 400px; 
    left: -200px; 
    top:0; 
    cursor: pointer; 
    /*...*/ 
}

As it was mentioned before, cursor becomes "pointer" on the whole input, excluding the button. In most browsers the button is on the left side or on the right side. Ok! Lets give the input a huge width and show only the middle... Button will be hidden. And clickable is the whole input.

That works for me.

oporkov
  • 71
  • 1
  • 2
  • This was almost the same solution I came up with. Instead, I set `width: 100%`, `height: 300%` and `top: -200%`. That way no matter what size the parent li is, the button will be above the container, and the entire container will still be covered by the input element. – Jargs Jul 11 '16 at 18:36
3

I found out that there's another approach to make it. Works perfectly in Opera New, FF, Chrome and Safari. Unfortunately it doesn't work perfect in IE (but good enough for my case).

The idea is to wrap input=file element with fixed size div and hidden overflow and set cursor: pointer;. Than we move button outside of the div using left padding.

<div class="input-file-wrap">
    <input class="file-input" type="file" />
</div>

and sample styles

.input-file-wrap {
    background: red;
    height: 33px;
    width: 240px;
    overflow: hidden;
    position: relative;
    cursor: pointer;
}

.file-input {
    width: 100%;
    height: 100%;
    opacity: 0;
    padding-left: 240px;
    margin-right: -240px;
    cursor: pointer;
}

Here you can find live example: http://jsfiddle.net/5c5RH/2/

pawelkmpt
  • 71
  • 3
2

If you're trying to do Ajax uploader, you might try another technique for compatible browsers such as FireFox and Chrome. They support triggering a click event on totally invisible file input. You can hide file input in any way you want except setting it's display property to none. Setting { height: 0; overflow: hidden } on parent form will do the trick. I use separate forms for each uploader.

Redirect your custom button click event to hidden file input and you're done.

To use this technique you must perform navigator.userAgent check for Gecko or WebKit engine. For other engines you have to use old transparent file input method.

Harry
  • 4,524
  • 4
  • 42
  • 81
1

First of all, your code works on Internet Explorer, but doesn't on Firefox.

Second, W3C Css standard doesn't allow styling complex tags like <input />. Even for cursor property.

Endly, see this page. I did not try his solution, so tell us if it works and how.

knittl
  • 246,190
  • 53
  • 318
  • 364
enguerran
  • 3,193
  • 3
  • 26
  • 42
  • 1
    The solution you point to does a trick to hide the file input so you can display your own look, but keep the mouse interactive stuff provided by the file input control. That means that the mouse pointer still is affected by the file input, and it doesn't help a bit. I also tried the other way around, and used onclick event on a div that covered the file input. This solved the cursor issue, but in FireFox the fileInput.click() method didn't work. It actually works in IE but that doesn't help us here... – awe Oct 14 '09 at 08:47
  • is this still the case? i cannot for the life of me figure out how to set a custom cursor on `input` elements :/ – oldboy Oct 14 '20 at 08:44
  • I found this https://css-tricks.com/snippets/css/custom-file-input-styling-webkitblink/ and http://wtfforms.com/ ("the times they are a-changin'.") – enguerran Oct 22 '20 at 11:27
1

Chrome was giving me this problem too. I tried to set all sorts of CSS selectors, but nothing seemed to work well. However, I did find a solution by using the FORM element.

  1. name your input[type=file] element.
  2. name your form element and put the input[type=file] in it.
  3. make a span and place it below the input in the form. This will be your label.
  4. use CSS to set the input's height to 0px and opacity to 0, this will make it invisible.
  5. make the span positioned absolutely and to the left 0px.
<style>
    #file {
        height:0px;
        opacity:0;
    }  
    #span {
        left:0px;
        position:absolute;
        cursor: pointer;
    }
</style>

<form name="form">
    <input type="file" id="file" name="file"/>
    <span id="span">My File label!!!!</span>
</form>

<script>
    var span = document.getElementById("span");
    span.onclick = function(event) {
        document.form.file.click(event);
    };
</script>

I tested this in Chrome and FF, not ie, but I hope this helps. jsfiddle http://jsfiddle.net/aressler38/L5r8L/1/

Kerem
  • 11,377
  • 5
  • 59
  • 58
alex
  • 756
  • 4
  • 12
0

Try using:

input[type=file] {
  cursor: pointer; cursor: hand;
}

See if that works. I've had to put pointer + hand in mine to make it work in FF/Chrome/etc. Also, I'm not sure if it matters but I don't think there are quotes around 'file' in the css.

Jesse O'Brien
  • 614
  • 1
  • 5
  • 8
  • 2
    This is not right. `cursor:hand` is supported only by some browsers (not including Firefox). `cursor: pointer` is the official standard, and is supported by all browsers. – awe Oct 08 '09 at 12:53
  • @awe: "cursor: hand" is supported on firefox, but maybe not on input tag which does not allow any style on firefox. @Jesse O'Brien: what a strange idea to have a doublon here. Any explanation about this magical instruction? – enguerran Oct 08 '09 at 12:57
  • Quotes around "file" is optional. It works either way. The problem is that Firefox does not support setting cursor on the input file element. – awe Oct 08 '09 at 13:05
  • @enguerran: I said this based on testing in **Firefox** version 3.5.3: I tried to set `cursor:pointer` on a div tag, and it worked. Then I tried to set `cursor:hand` and it didn't work. – awe Oct 08 '09 at 13:09
  • @enguerran Not sure, I just stumbled upon it one day, I'm pretty sure I forgot to delete the pointer and added the hand line and it started working. @awe try using the cursor: pointer; cursor: hand; – Jesse O'Brien Oct 08 '09 at 13:23
  • 1
    @Jesse O'Brien: The issue here is that Firefox does not support setting cursor at all on the `input[type=file]` element. It has nothing to do with using `pointer` and/or `hand`. It works for input buttons by setting the cursor for `input[type=button]`. And yes, for others than `input[type=file]`, it works with setting `cursor: pointer; cursor: hand;`, but that is because Firefox ignores the invalid `cursor: hand;` and falls back to the previous set `cursor: pointer;`. If you set **only** `cursor: pointer;', it also works, and if you set **only** `cursor: hand;` it does not work. – awe Oct 09 '09 at 05:42
  • Thanks for clearing that up awe! :o) – Tisch Oct 10 '09 at 15:57
0

Based on https://stackoverflow.com/a/3030174/2325676 - Hide the input using opacity 0.

The key to getting the cursor to work on the entire area is setting the font-size to a value greater than the height of the button so that the file input button is pushed below the visible area and the mouse hover is on the text part of the file input:

<div style="display: block; width: 100px; height: 50px; overflow: hidden">
    <button style="width: 110px; height: 50px; position: relative; top: -5px; left: -5px;" ><a href="javascript: void(0)">Upload File</a></button>
    <input type="file" id="upload_input" name="upload" style="height:50px; width: 120px; opacity: 0; filter:alpha(opacity: 0);  font-size: 70px; position: relative; top: -50px; left: -20px; cursor:pointer" />
</div>
Community
  • 1
  • 1
Daniel Flippance
  • 7,734
  • 5
  • 42
  • 55
0

How I did it:

    /* Upoload */
#upload-profile-file {
    z-index: 1;
}
.uploadButton input[type="file"] {
    cursor:pointer;
    position:absolute;
    top:0px;
    opacity:0;
}
#upload-profile-file:hover ~ #upload-profile-pic-btn
{
    text-decoration:underline;
}

#upload-profile-pic-btn {
    z-index:-1;
}

And then on my view page:

  <form id="upload-profile-pic-form">
                                                <div class="uploadButton">
                                                    <input type="file" id="upload-profile-file" name="upload" style="width: 88px; opacity:0.0; filter:alpha(opacity=0); " onchange='upload()'/>
                                                    <a id="upload-profile-pic-btn" href="#" class="expand">Upload</a>
                                                </div>
                                            </form>

And then I simply submit my form via AJAX to the server and handle the rest there.

So tl;dr -> I relay the click of the visible link (with all styles and bells and whistles) and I actually click the file input. :)

Hope this helps someone.

Martin
  • 1
0
            <span class="btn btn-success fileinput-button">
                <span><i class="icon-plus icon-white"></i> Select Image</span>
                <input type="file" name="files[]">
            </span>

css:

.btn{cursor:pointer;}

You can see it in action here: http://blueimp.github.com/jQuery-File-Upload/

It's not the jquery doing it. It's the http://blueimp.github.com/cdn/css/bootstrap-responsive.min.css file. I've just grabbed what I needed out of it and it works great without any of the jquery.

Christina
  • 34,296
  • 17
  • 83
  • 119