stivlo
stivlo

Reputation: 85496

Styling an upload field

I'm trying to style an upload field, and I've already spent many hours trying to fix it without success. I've created a simple jsfiddle to demonstrate the problems (if you're into fast-reading read only the bold bullet points).

Firefox 7:

IE 8:

Anyone has ideas?

UPDATE: Based on input received, here is another approach in jsfiddle: I build a button and I bind the click event of the button to send a click event to the file upload input.

Here is some compatibility testing:

UPDATE 2: Getting closer, in this jsfiddle I threw in some browser testing, in case of MSIE or Mozilla I use the new approach, otherwise the old one.

So I guess Opera doesn't work because of the z-index, going to fix that in the next version.

UPDATE 3: new version that works in Opera too. Opera label height is reduced, so all area of the label is clickable. So now it works in all browsers I care about, and it's acceptable in the look. Problem solved.

Upvotes: 2

Views: 1339

Answers (3)

stivlo
stivlo

Reputation: 85496

I've to answer my question, because other answers are partial solutions that don't work in all browsers. Particularly I'm supporting IE 6, IE 7, IE 8, Chrome 15, Opera 11, FF 7, FF 8, Safari 3.1 on MacOSX. Most likely it will work on other browsers too, but this are the ones I could test with, since I've on my computers and VMs.

In the end my customer opted for a smaller and more sober version. The new version comes also with shorter HTML, JavaScript and CSS.

HTML

<form enctype="multipart/form-data" method="POST" action="">
    <div class="fileupload-buttonbar">       
    </div>
</form>

CSS

.file-upload {
    overflow: hidden;
    display: inline-block;
    position: relative;    
    vertical-align: middle;
    text-align: center;
    color: #fff;
    background: #5A5A5A;
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    cursor:pointer;
    font-size: 8.5px;
    font-family: Arial;
}

.file-upload:hover {
    background: #808080;
}

.file-upload input {
    position: absolute;
    top: 0;
    left: 0;
    margin: 0;
    opacity: 0;
    filter: alpha(opacity=0);
    z-index:2;
}

.file-upload { height: 14px; width: 115px; }    

JavaScript

var html = '';
if ($.browser.mozilla || $.browser.msie) {
    html = '<input type="button" class="file-upload" '
        + 'value="SCEGLI FOTO..."/><input id="uploadfile" '
        + 'name="uploadfile" multiple="" type="file"/>';
    $('.fileupload-buttonbar').html(html);
    $('#uploadfile').hide();
    $('.file-upload').click(function () {
        $('#uploadfile').click();
    });
} else {
    html = '<label class="file-upload"><span>SCEGLI FOTO...</span> '
        + '<input name="uploadfile" multiple="" type="file"/></label>';
    $('.fileupload-buttonbar').html(html);
}

Upvotes: 1

user898741
user898741

Reputation:

So, my suggestion is that you hide your input file and use another object such as an image or an stylized input text to get what you want, right? This very simple code explains what I'm saying:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Teste</title>

    <script type="text/javascript">
    function File()
    {
        var f = document.getElementById("file");
        f.click();
        document.getElementById("file_path").value = f.value; 
    }

    function ReturnFile(f)
    {
        document.getElementById("file_path").value = f.value;
    }
    </script>
</head>

<body>

<input type="file" id="file" onchange="ReturnFile(this)" /><br /><br />

<input type="button" onclick="File()" value="Send a file..." />
<div onclick="File()">Send a file...</div>
<a href="javascript: void(0)" onclick="File()">Send a file...</a><br />
<img src="your_image.png" onclick="File()" alt="Send a file..." /><br /><br />

<input type="text" id="file_path" />

</body>
</html>

Note that the objects with the click event is your button and the text input with id 'file_path' returns the same value of the file input. So when hide the file, you use the text input or whatelse to show the file to user.

Another important thing is that on the third line of File function it's set the value of file input to the text input. But it works only in IE cause it stops and waits user return when click event is fired. Other browsers doens't waits and pass through it. So I put an onchange event on file input to do the same job to work on other browsers.

Hope it can help you...

Upvotes: 0

mothmonsterman
mothmonsterman

Reputation: 2491

IE 8:

add z-index to your input rule.. voila

.file-upload input {
    position: absolute;
    top: 0;
    left: 0;
    margin: 0;
    font-size: 12px;
    opacity: 0;
    filter: alpha(opacity=0.0);
    z-index:-1;
}

Edit: it is easier to see what is happening in FF with the following css...

.file-upload {
    overflow: hidden;
    display: inline-block;
    position: relative;    
    vertical-align: middle;
    text-align: center;
    color: #fff;
    border: 2px solid #707070;
    background: #A0A0A0;
    -moz-border-radius: 8px;
    -webkit-border-radius: 8px;
    border-radius: 8px;
    text-shadow: #000 1px 1px 4px;
    cursor:pointer;
}

.file-upload:hover {
    background: #2FA2FF;
}
.file-upload.focus {
    outline: 2px solid yellow;
}

.file-upload input {
    position: absolute;
    top: 0;
    left: 0;
    margin: 0;
    height: 38px;
    font-size: 12px;
    -moz-opacity:50;
    filter: alpha(opacity=0);
    opacity: 50;
    z-index:2;
    cursor:pointer;
}

.file-upload span {
    position: absolute;
    top: 0;
    left: 0;
    display: inline-block;
    padding-top: .45em;
    z-index:1;
}

.file-upload { height: 38px; }
.file-upload,
.file-upload span { width: 160px; }    

.file-upload-status {
    margin-left: 10px;
    vertical-align: middle;
    padding: 7px 11px;
    font-weight: bold;    
    font-size: 16px;
    color: #888;
    background: #f8f8f8;
    border: 3px solid #ddd;
}

Upvotes: 1

Related Questions