Skip to content

Instantly share code, notes, and snippets.

@jdfm
Last active December 25, 2015 17:59
Show Gist options
  • Save jdfm/7016851 to your computer and use it in GitHub Desktop.
Save jdfm/7016851 to your computer and use it in GitHub Desktop.
Minimal JS, crossbrowser, styled input[type="file"] with simple markup.
<!doctype html>
<!--
Minimal JS, crossbrowser, styled input[type="file"] with simple markup.
Tested working in IE[>=7], FF[24], O[16], C[30], S[6.0.5]; Should work in
all browsers that support opening a file browser via a label associated
to an input[type="file"]. Some adjustments might be necessary for IE[6]
support.
Tested using html5 doctype. Further testing is necessary to ensure proper
behaviour for others.
Initially I thought no JS was needed, but it seems that you have no way of
showing feedback when the user actually selects a file. I tried to use
this selector (with corresponding markup):
.file-input-view > input[type="file"][value=""] + label;
to change the aspect of the button somehow, but that didn't work because
the value in the document remains unchanged.
-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Styled Input[type="file"]</title>
<style>
.file-input-view {
background:gray;
color:white;
/* IE7: having a relative axis will be useful for when we shift the
input left because of the border sizes that get applied
to it's text box portion */
position:relative;
/* remove unnecessary spacing */
margin:0;
padding:0;
/* set the size of the button */
display:block;
width:228px;
height:34px;
/* we'll be using the full width and height, anything
extra should be hidden */
overflow:hidden;
}
.file-input-view:hover,
.file-input-view > label:hover {
background:silver;
color:black;
}
/* This will not work in IE7. I have no idea how to fix this. */
.file-input-view:active,
.file-input-view > label:active {
background:black;
color:white;
}
.file-input-view > input[type="file"] {
/* we're going to be using the div and the label for our visual
styling purposes, so make the actual input invisible */
-moz-opacity:0;
-o-opacity:0;
-webkit-opacity:0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
opacity:0;
/* place the input below the label */
position:absolute;
z-index:1;
/* make the button look clickable */
cursor:pointer;
/* IE7/8 specific styles */
/* IE7: removes the width from the text box.
IE8: The label was being pushed upwards, by the input,
after clicking on it once. Setting width to
zero corrects this. */
width:0\9;
/* IE7 specific styles */
/* this will size both the text box and the button */
*border-width:17px 114px;
/* place the input above the label */
*z-index:2;
/* border-left + border-right + some little extra bit, which is the
spacing between the textbox and the button */
*left:-233px;
}
.file-input-view > label {
/* place the label above the input */
position:absolute;
z-index:2;
/* align label text to the horizontal center */
text-align:center;
/* make the label look clickable */
cursor:pointer;
/* remove any extra unnecessary spacing */
margin:0;
padding:0;
/* setting the line-height to the same height as the container
will vertically align the text to the middle of the
container's vertical space */
line-height:34px;
/* use the parent element's width and height */
width:100%;
height:100%;
/* IE7: the default activated area when clicking the label is the
text box, which does not open the file dialog. Place the
label under the input. */
*z-index:1;
}
.file-input-view.file-selected {
background:green;
}
</style>
</head>
<body>
<!-- Associated markup -->
<div class="file-input-view">
<label for="file_input">Upload File</label>
<input type="file" id="file_input" name="file_input">
</div>
<!-- simple script to change the visual style when a file is selected -->
<script>
// get the input
var fileInput = document.getElementById('file_input');
// get it's parent
var fileInputView = fileInput.parentNode;
// IE7 uses a different event naming scheme, get the appropriate one
var eventType = 'addEventListener' in fileInput? 'change': 'onchange';
// IE7 uses a different event attaching mechanism, get the appropriate one
var attacher = 'addEventListener' in fileInput? 'addEventListener': 'attachEvent';
// cache the regexp we'll be using later on
var fileSelectedRE = /(?:^|\s+)file-selected(?:$|\s+)/;
// create the event
fileInput[attacher](eventType, function(e){
// IE places the event object in the window
e = e || window.event;
// add or remove the file-selected class to the input view for visual feedback
if(!fileInput.value){
fileInputView.className.replace(fileSelectedRE, ' ');
} else if(!fileInputView.className.match(fileSelectedRE)){
fileInputView.className += ' file-selected';
}
}, false);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment