Show the value of a field when onMouseOver? - html

I have several inputs on the same row of a table. some of them eventually are "small" (or short).
Particularly the INPUT DATE field value is very difficult to see because the allowed is shorter than the "10 characters + the calendar icon".
So, I would like to do a onMouseOver display the current value of the field. After user changes, it shows the newest value user selected.
How can I do that?

Save the date into javascript variable as datetime format.
If you are using hardcode HTML and CSS you can use tooltip.
Refer here :https://www.w3schools.com/css/css_tooltip.asp
If you are using frameworks such as Angular. Just use MatTooltip

Try to use it.
<input type="text" id="userType" title="title show while hovering the field" />

You can add events to the input by using JavaSCript. In this solution, I used two events: mouseover and mouseout to display/hide a tooltip.
So basically the input value is hidden until the mouseover event is trigged.
The CSS styles are available on W3School
const input = document.getElementById("input")
const output = document.getElementById("output")
input.addEventListener("mouseover", () => {
output.innerHTML = input.value
output.classList.add("active")
})
input.addEventListener("mouseout", () => {
output.classList.remove("active")
})
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
min-height: 10px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
bottom: 125%;
left: 50%;
margin-left: -60px;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.tooltip .tooltiptext.active {
visibility: visible;
opacity: 1;
}
<h1>Your inputs below</h1>
<div class="tooltip">
<input id="input" type="date"></input>
<span class="tooltiptext" id="output"></span>
</div>

Related

CSS Custom checkboxes in grid - can't remove original checkbox

I have some checkboxes in a grid and want to use vanilla-css and html to make a custom checkbox. That works fine. The problem is the remaining box of the original checkbox, that stays in my grid and makes it behave in strange ways as it takes a cell. Even when I make it transparent or deactivate it, as it is often suggested.
In the original example they moved it out of the screen area, but I can make it escape the grid.
I think this is the part where it fails to behave like I want to:
[type="checkbox"]:not(:checked),
[type="checkbox"]:checked {
position: absolute;
left: -9999px;
}
Here is a minimal example: https://jsfiddle.net/3mzsLj1v/14/
Here is the example I used: https://css-tricks.com/the-checkbox-hack/
Here is the real code I work on: https://codepen.io/vaeng/pen/XWXKoMb
Thanks for your help. I am sure this is very common, but being a beginner, I might not use css in the correct way?
In both your "minimal" and "real code" examples, your "New Checkboxes" comments are not properly opened.
In minimal example:
Line 23: *New Checkboxes*/ s/b /*New Checkboxes*/
In real code example:
Line 123: * New Checkboxes and radio buttons*/ s/b /* New Checkboxes and radio buttons*/
If you fix these lines, your code should work as intended.
Also, I noticed in line 102 that you put // before visibility: hidden;. If you want to comment this line, this syntax is not valid in CSS.
You see, your label and input element are on the same level, and even with position: absolute; your input still a part of the grid. Replaced your input inside the label, added span element and rewrited CSS.
Although in your code was
* New Checkboxes*/
/* Base for label styling */
[type="checkbox"]:not(:checked),
[type="checkbox"]:checked {
position: absolute;
left: -9999px;
}
The first comment was closed incorrect, so next statement didn't work.
.body {
height: 100%;
}
.outer-box {
display: grid;
margin: auto;
background-color: green;
width: 300px;
align-self: center;
grid-gap: 10px;
}
.inner-box {
display: grid;
width: 80%;
background-color: red;
align-self: center;
margin: 5px 5px 5px 5px;
}
/* New Checkboxes*/
/* Base for label styling */
[type="checkbox"] {
position: absolute;
left: -9999px;
}
[type="checkbox"]:not(:checked)+span,
[type="checkbox"]:checked+span {
position: relative;
padding-left: 1.95em;
cursor: pointer;
}
/* checkbox aspect */
[type="checkbox"]:not(:checked)+span:before,
[type="checkbox"]:checked+span:before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 1em;
height: 1em;
border: 1px solid grey;
background: transparent;
}
/* checked mark aspect */
[type="checkbox"]:not(:checked)+span:after,
[type="checkbox"]:checked+span:after {
content: '\2713\0020';
position: absolute;
top: .05em;
left: .2em;
font-size: 1.3em;
line-height: 0.8;
color: whitesmoke;
transition: all .2s;
font-family: Arial;
}
/* checked mark aspect changes */
[type="checkbox"]:not(:checked)+span:after {
opacity: 0;
transform: scale(0);
}
[type="checkbox"]:checked+span:after {
opacity: 1;
transform: scale(1);
}
<div class="outer-box">
<div class="inner-box">
Some text
</div>
<div class="inner-box">
<label for="box1" class="container">
<input type="checkbox" id="box1"><span>Selectbox1</span>
</label>
<label for="box2" class="container">
<input type="checkbox" id="box2"><span>Selectbox2</span>
</label>
</div>
</div>
And please, don't use display: grid; for every element. It's very specific setting only for cases, when you really need you use grid.

Custom checkbox wont toggle when click and drag on label

I have a problem with my custom checkbox.
If you click on a checkbox element, move the mouse cursor and then release the click inside the checkbox area, the checkbox is checked.
However, if you do the same on a custom checkbox (here, a div inside a label), the checkbox isn't checked.
It's a problem because if you want to quickly check a checkbox, you may move the mouse after pressing the button of the mouse and before releasing it, thus not toggling the checkbox.
The user is obligated to click without moving the mouse.
I know I can use JS to emulate a checkbox with a div, but I want the HTML to be semantically correct, so: Is it possible to fix it without js?
Here's the code :
/* 1. Hide the checkbox */
.hidden {
/* https://zellwk.com/blog/hide-content-accessibly/ */
border: 0;
clip: rect(0, 0, 0, 0);
height: auto;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}
/* 2. Use a label to retrieve the click event */
label {
/* not used directly to prevent the bug in firefox https://bugzilla.mozilla.org/show_bug.cgi?id=608180 */
pointer-events: none;
display: inline-flex;
}
label > input {
/*usefull for testing only*/
pointer-events : all;
}
label > .customCheckbox {
cursor: pointer;
display: inline-flex;
justify-content: center;
align-items: center;
position: relative;
--size:200px;
width: var(--size);
height: var(--size);
font-size: calc(var(--size)/2);
pointer-events: all;
}
label > .customCheckbox::selection{
/* prevent highliting the text within the custom checkbox */
background: none;
}
label > .customCheckbox:after {
z-index: -1;
content: "✔";
display: inline-flex;
justify-content: center;
align-items: center;
position: absolute;
width: 100%;
height: 100%;
box-sizing: border-box;
border-radius: calc(var(--size)/4);
border: solid black calc(var(--size)/10);
}
label > input:not(:checked) + div.customCheckbox:after {
background:#0000;
content: "\a0";
}
<input type="checkbox"/>
<label >
<input type="checkbox" class="hidden"/>
<div class="customCheckbox"></div>
</label >
I need the checkbox to be inside the label because I can't use the "for" attribute.
Thanks a lot for your help!
EDIT: for those wondering, here's the js solution (not ideal but since I can't do it in CSS, it's better than nothing) :
let checkboxes = document.getElementsByClassName("customCheckbox");
for(let i=0; i<checkboxes.length; i++){
checkboxes[i].addEventListener('mouseover', (e)=>{handleMouseOverCheckbox(e)})
checkboxes[i].addEventListener('mousedown', (e)=>{handleMouseOverCheckbox(e)})
}
function handleMouseOverCheckbox(e) {
e.srcElement.previousElementSibling.disabled = "true";
if (e.buttons == 1) {
e.srcElement.previousElementSibling.checked= !e.srcElement.previousElementSibling.checked;
}}
EDIT 2 : Here's the best solution I could come up with, thanks to
#zer00ne
codepen.io/DesignThinkerer/pen/bGVBLjM
A checkbox within a label is no problem. The problem arises when that checkbox is altered for the sake of accessibility instead of complete removal using display: none. When an interactive element like an input or button exists in the DOM, it will still be a factor no matter how its hidden unless display: none is applied.
In the Original Post the checkbox is almost impossible to click due to its 0px height and 1px width and yet when the div is clicked, the checkbox is clicked... sometimes not. Normally if the label was able to detect a click, that click would trigger a click event to the nested checkbox as well. In the OP code that's not happening because the label has pointer-events: none.
So the div is getting clicked and by some magical miracle this gains features that would not normally be attributed to it? Divs are not interactive they cannot affect elements that are not nested within themselves (i.e. like the checkbox that sits before the div). Nope, the div is useless, its the checkbox itself that's getting clicked due to the fact it is the only element within the inert label that gains focus by default. Gaining focus on an input doesn't necessarily guarantee a click event -- matter of fact a focus event selects an element and a click event sets an element as active. So what happens when a user double-clicks or moves the mouse quickly before the next click clears a label? Undesirable behavior as described in OP.
In the following demo, the checkboxes are hidden as per OP (also set width and height to 0) and removed pointer-events: none from the label and added it to the checkboxes. In this setup the label gains focus and click events and the click event will trigger the checkbox. The checkbox having been isolated from any extra clicks due to pointer-events: none and z-index: -1 should behave as expected.
As proof of concept I have added some JavaScript to demonstrate said code stability. The two event handlers are for demonstration purposes. The JS does not facilitate, stabilize, or modify performance of the HTML/CSS behavior.
On any change event on a checkbox (via label) will trigger function changeHandler() to gather all the values of the checked checkboxes and display them in an output.
If there's a checkmark in a box and there's a value displayed that corresponds to said checked checkbox, then it successfully passes as valid behavior.
Clicking button.show will trigger function clickHandler() to toggle the .reveal class to each checkbox.
While clicking rapidly observe that the revealed checkboxes are checked and its corresponding custom label is checked as well. Also notice that the value should also be displayed as well.
BTW
"....target doesn't work in IE IIRC"
event.target is the standard property to use in every modern browser. event.srcElement is a deprecated property used by IE which is almost entirely unsupported.
pointer-events: all assigned to input and .customCheckbox
The value all applies to SVG only. Only the values of none and auto are relevant to HTML. auto is default.
Demo
I cannot reproduce the described behavior except in the code provided in OP. If you can reproduce that behavior on my demo, please record a short video of it and post that and the machine/device, OS, and browsers (I will assume everything is reasonably up to date).
const main = document.forms.main;
main.onchange = checkHandler;
function checkHandler(e) {
const fc = this.elements;
const chx = [...fc.hidden];
const ui = e.target;
if (ui.matches('.hidden')) {
let text = chx.flatMap(c => c.checked ? [c.value] : []);
fc.view.value = '';
fc.view.value = text.join(', ');
}
}
main.onclick = clickHandler
function clickHandler(e) {
const fc = this.elements;
const chx = [...fc.hidden];
const ui = e.target;
if (ui.matches('button.show')) {
chx.forEach(c => c.classList.toggle('reveal'));
}
}
:root,
body {
--size: 10rem;
font: 400 small-caps 2vw/1.5 Times;
width: 100%;
height: 100%;
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
font: inherit;
}
.display {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
width: max-content;
max-height: min-content;
margin: 10px;
border: calc(var(--size) / 20) solid #000;
border-radius: 24px;
}
.view {
display: inline-block;
min-width: 35ch;
font-size: 1.5rem;
height: 1.5rem;
line-height: 1;
}
.show {
display: inline-block;
width: 12ch;
padding: 1px 3px;
margin: 4px;
border: 2px solid #000;
border-radius: 8px;
background: none;
text-align: center;
font-size: 1.25rem;
cursor: pointer;
}
.mask {
position: relative;
z-index: 2;
display: block;
width: var(--size);
height: var(--size);
padding: 0;
margin: 0 5px;
border: solid black calc(var(--size) / 10);
border-radius: calc(var(--size) / 4);
font-size: calc(var(--size) * 0.8);
background: none;
cursor: pointer;
}
.icon {
position: absolute;
z-index: 1;
top: -1.5rem;
right: 1rem;
display: inline-block;
margin: 0;
padding: 0;
border: 0;
}
.hidden {
position: relative;
z-index: -1;
display: inline-block;
width: 0;
height: 0;
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
pointer-events: none;
opacity: 0;
}
.reveal {
z-index: 0;
top: -24px;
left: 4px;
width: 1px;
height: 1px;
opacity: 1;
}
.icon::after {
content: attr(data-blank);
}
.hidden:checked+.icon::after {
content: attr(data-check);
}
<!DOCTYPE html>
<html>
<head lang='en'>
<meta charset='utf-8'>
<style></style>
</head>
<body>
<form name='main'>
<fieldset name='display' class='display'>
<output name='view' class='view'></output>
<button name='show' class='show' type='button'>Show</button>
</fieldset>
<fieldset name='display' class='display'>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check I'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check II'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check III'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check IV'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
</fieldset>
</form>
<script></script>
</body>
</html>

Why is my drop down CSS disappearing, and how can I fix it?

This is a really strange problem which only affects Google Chrome.
If I have 299 rows in a drop down list, it keeps my custom CSS. However, the second I reach 300 rows all my styling is removed and seems to be set to a default by Google Chrome.
In the JSFiddle page, it has 300 rows, if you view the result, it will have default styling. But if you remove one row, my custom styling will be applied. Why is this?
JSFiddle: https://jsfiddle.net/s7opd7dm/
Simple drop down element:
#Html.DropDownListFor(m => m.SupplierID, new SelectList(Model.Suppliers, "SupplierID", "DisplayName"), "Select Supplier Name", new { #id = "SuppNameDD", #class = "GRDropDown", disabled = true })
I had the same problem. I found out that they disabled it at 300 options or more.
We intentionally disabled styling for 300+ options because of a
performance issue (crbug.com/500401).
Read about it here
Chrome Intentionally did disabled styling for 300+ options, so we can't reach the answer that way.
In short i would like to say that you should use any custom drop down.
As you are requesting for a solution to achieve, here's the fix
In that case i would prefer you to create a customized drop-down using other html elements like divs and list and take the selected list value. Here i am going to show a demonstration of how to create a customized div. The code has been tested in ASP.NET MVC5 C# and works fine. Post this demonstration here to promote this idea, as this might help anyone like you searching for what to do on cases like this.
in your some_view.cshtml add the following to include jquery and styles
<script src="#Url.Content("~/Scripts/jquery-1.10.2.min.js")"></script>
<!--<script src="#Url.Content("~/Scripts/myjquery.js")"></script> in case want this jquery to be external-->
<script>
function my_dd(el) {
this.dd = el;
this.initEvents();
}
my_dd.prototype = {
initEvents : function() {
var obj = this;
obj.dd.on('click', function(event){
$(this).toggleClass('active');
event.stopPropagation();
});
}
}
$(function() {
var dd = new my_dd( $('#dd') );
$(document).click(function() {
$('.wrapping').removeClass('active');
});
});
/** on select take the value to hidden text field**/
$(document).ready(function()
{
$('ul.my_dd li').click(function(e)
{
var selected=$(this).text();
/**change label to selected**/
$('.label').text(selected);
$('#selected-value').val(selected);
});
});
</script>
<!--<link href="#Url.Content("~/Content/my.css")" rel="stylesheet" type="text/css" />
in case want the css to be external-->
</script>
<style>
*,*:after,*:before {
box-sizing: border-box;
}
.wrapping {
position: relative;
width: 200px;
margin: 0 auto;
padding: 10px 15px;
cursor: pointer;
outline: none;
}
.wrapping:after {
width: 0;
height: 0;
position: absolute;
right: 16px;
top: 50%;
margin-top: -3px;
border-width: 1px solid red;
border-style: solid;
border-color: #366;
}
.wrapping .my_dd {
position: absolute;
top: 60%;
left: -45px;
right: 0px;
background: white;
transition: all 0.1s ease-out;
list-style: none;
opacity: 0;
pointer-events: none;
}
.wrapping .my_dd li a {
display: block;
text-decoration: none;
border: 1px solid;
padding: 10px;
transition: all 0.1s ease-out;
}
.wrapping .my_dd li i {
margin-right: 5px;
color: inherit;
vertical-align: middle;
}
.wrapping .my_dd li:hover a {
color: grey;
background-color: darkgrey;
max-height:300px;
}
.wrapping.active:after {
border-width: 0 6px 6px 6px;
}
.wrapping.active .my_dd {
opacity: 1;
pointer-events: auto;
height:300px;
overflow-y:scroll;
}
</style>
</style>
<div id="dd" class="wrapping">Test Drop Down
<ul class="my_dd">
<!-- use list or a foreach or for loop to push content to list
example
#foreach(var productId in Model.FailedProductIdsList)
{
<li>#Convert.ToString(productId);</li>
}-->
<li><i></i>Select 0</li>
...............
<li><i></i>Select 300+</li>
</ul>
</div>
<!-- #Html.TextBoxFor(c => c.Propertyname, new { #Value = "selected" })-->

Issue with CSS Transition and the Label of a Checkbox

I want to change the position of my label when the checkbox is checked. This works fine if I don't transition the top offset property of my label. However, if I add a transition to this value (see the commented code), click on the label and don't move the cursor of my mouse the label seems that is still on hover state. That means, even though I don't hover on it, the cursor is a pointer and the background-color green (hover state of label).
If you see the demo, you'll understand what I mean.
My HTML code is the following:
<section>
<input type="checkbox" id="checkbox_id">
<label for="checkbox_id">Click me</label>
<div>
This is the first link
This is the second link
</div>
</section>
My CSS:
* {
margin: 0;
}
section {
position: relative;
padding: 20px;
background: yellow;
}
input[type="checkbox"] {
display: none;
}
label, a {
height: 30px;
padding: 10px 0;
margin: 10px;
}
label {
display: block;
background: tomato;
cursor: pointer;
width: 100%;
position: absolute;
top: 0;
/*transition: top .3s ease;*/
}
label:hover {
background: green;
}
input[type="checkbox"]:checked + label {
top: 100%;
}
a {
display: block;
background: tomato;
}
a:first-child {
margin-top: 50px;
}
Any idea why that's happening?
So, a little bit of jQuery might help us out here. Take a look at this jsFiddle.
CSS change:
.label--hovered { background: green; }
instead of:
label:hover { background: green; }
i.e. converted it to a class.
JavaScript:
$(document).ready(function(){
$('label').hover(function(){
$(this).removeAttr('style').addClass('label--hovered');
}, function(){
$(this).css('cursor', 'default').removeClass('label--hovered');
}).click(function(){
$(this).trigger('mouseleave');
});
});
Does this help?
You are using the syntax for the transition property but on transform. Additionally, transform doesn't take a top value. It takes scale, rotation, skew etc. You probably want this:
transition: top .3s ease;
Also don't forget to add vendor prefixes. (ie. webkit).

Cross-browser custom styling for file upload button [duplicate]

This question already has answers here:
How to customize <input type="file">?
(18 answers)
Closed 6 years ago.
I'm trying to style a file upload button to my personal preferences, but I couldn't find any really solid ways to do this without JS. I did find two other questions about this subject, but the answers there either involved JavaScript, or suggested Quirksmode's approach.
My major issue with this Quirksmode's approach is that the file button will still have the browser-defined dimensions, so it won't automatically adjust to whatever's used as button that's placed below it. I've made some code, based on it, but it will just take up the space the file button would normally take up, so it won't at all fill the parent div like I want it to.
HTML:
<div class="myLabel">
<input type="file"/>
<span>My Label</span>
</div>
CSS:
.myLabel {
position: relative;
}
.myLabel input {
position: absolute;
z-index: 2;
opacity: 0;
width: 100%;
height: 100%;
}
This fiddle demonstrates how this approach is quite flawed. In Chrome, clicking the !! below the second demo button will open the file dialog anyway, but also in all other browsers, the file button doesn't take up the correct areas of the button.
Is there any more solid way to style the file upload button, without any JavaScript, and preferably using as little 'hacky' coding as possible (since hacking usually brings other problems along with it, such as the ones in the fiddle)?
I'm posting this because (to my surprise) there was no other place I could find that recommended this.
There's a really easy way to do this, without restricting you to browser-defined input dimensions. Just use the <label> tag around a hidden file upload button. This allows for even more freedom in styling than the styling allowed via webkit's built-in styling[1].
The label tag was made for the exact purpose of directing any click events on it to the child inputs[2], so using that, you won't require any JavaScript to direct the click event to the input button for you anymore. You'd to use something like the following:
label.myLabel input[type="file"] {
position:absolute;
top: -1000px;
}
/***** Example custom styling *****/
.myLabel {
border: 2px solid #AAA;
border-radius: 4px;
padding: 2px 5px;
margin: 2px;
background: #DDD;
display: inline-block;
}
.myLabel:hover {
background: #CCC;
}
.myLabel:active {
background: #CCF;
}
.myLabel :invalid + span {
color: #A44;
}
.myLabel :valid + span {
color: #4A4;
}
<label class="myLabel">
<input type="file" required/>
<span>My Label</span>
</label>
I've used a fixed position to hide the input, to make it work even in ancient versions of Internet Explorer (emulated IE8- refused to work on a visibility:hidden or display:none file-input). I've tested in emulated IE7 and up, and it worked perfectly.
You can't use <button>s inside <label> tags unfortunately, so you'll have to define the styles for the buttons yourself. To me, this is the only downside to this approach.
If the for attribute is defined, its value is used to trigger the input with the same id as the for attribute on the <label>.
Please find below a way that works on all browsers. Basically I put the input on top the image.
I make it huge using font-size so the user is always clicking the upload button.
.myFile {
position: relative;
overflow: hidden;
float: left;
clear: left;
}
.myFile input[type="file"] {
display: block;
position: absolute;
top: 0;
right: 0;
opacity: 0;
font-size: 100px;
filter: alpha(opacity=0);
cursor: pointer;
}
<label class="myFile">
<img src="http://wscont1.apps.microsoft.com/winstore/1x/c37a9d99-6698-4339-acf3-c01daa75fb65/Icon.13385.png" alt="" />
<input type="file" />
</label>
The best example is this one, No hiding, No jQuery, It's completely pure CSS
http://css-tricks.com/snippets/css/custom-file-input-styling-webkitblink/
.custom-file-input::-webkit-file-upload-button {
visibility: hidden;
}
.custom-file-input::before {
content: 'Select some files';
display: inline-block;
background: -webkit-linear-gradient(top, #f9f9f9, #e3e3e3);
border: 1px solid #999;
border-radius: 3px;
padding: 5px 8px;
outline: none;
white-space: nowrap;
-webkit-user-select: none;
cursor: pointer;
text-shadow: 1px 1px #fff;
font-weight: 700;
font-size: 10pt;
}
.custom-file-input:hover::before {
border-color: black;
}
.custom-file-input:active::before {
background: -webkit-linear-gradient(top, #e3e3e3, #f9f9f9);
}
<input type="file" class="custom-file-input">
This seems to take care of business pretty well. A fidde is here:
HTML
<label for="upload-file">A proper input label</label>
<div class="upload-button">
<div class="upload-cover">
Upload text or whatevers
</div>
<!-- this is later in the source so it'll be "on top" -->
<input name="upload-file" type="file" />
</div> <!-- .upload-button -->
CSS
/* first things first - get your box-model straight*/
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
label {
/* just positioning */
float: left;
margin-bottom: .5em;
}
.upload-button {
/* key */
position: relative;
overflow: hidden;
/* just positioning */
float: left;
clear: left;
}
.upload-cover {
/* basically just style this however you want - the overlaying file upload should spread out and fill whatever you turn this into */
background-color: gray;
text-align: center;
padding: .5em 1em;
border-radius: 2em;
border: 5px solid rgba(0,0,0,.1);
cursor: pointer;
}
.upload-button input[type="file"] {
display: block;
position: absolute;
top: 0; left: 0;
margin-left: -75px; /* gets that button with no-pointer-cursor off to the left and out of the way */
width: 200%; /* over compensates for the above - I would use calc or sass math if not here*/
height: 100%;
opacity: .2; /* left this here so you could see. Make it 0 */
cursor: pointer;
border: 1px solid red;
}
.upload-button:hover .upload-cover {
background-color: #f06;
}
Any easy way to cover ALL file inputs is to just style your input[type=button] and drop this in globally to turn file inputs into buttons:
$(document).ready(function() {
$("input[type=file]").each(function () {
var thisInput$ = $(this);
var newElement = $("<input type='button' value='Choose File' />");
newElement.click(function() {
thisInput$.click();
});
thisInput$.after(newElement);
thisInput$.hide();
});
});
Here's some sample button CSS that I got from http://cssdeck.com/labs/beautiful-flat-buttons:
input[type=button] {
position: relative;
vertical-align: top;
width: 100%;
height: 60px;
padding: 0;
font-size: 22px;
color:white;
text-align: center;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
background: #454545;
border: 0;
border-bottom: 2px solid #2f2e2e;
cursor: pointer;
-webkit-box-shadow: inset 0 -2px #2f2e2e;
box-shadow: inset 0 -2px #2f2e2e;
}
input[type=button]:active {
top: 1px;
outline: none;
-webkit-box-shadow: none;
box-shadow: none;
}
I just came across this problem and have written a solution for those of you who are using Angular. You can write a custom directive composed of a container, a button, and an input element with type file. With CSS you then place the input over the custom button but with opacity 0. You set the containers height and width to exactly the offset width and height of the button and the input's height and width to 100% of the container.
the directive
angular.module('myCoolApp')
.directive('fileButton', function () {
return {
templateUrl: 'components/directives/fileButton/fileButton.html',
restrict: 'E',
link: function (scope, element, attributes) {
var container = angular.element('.file-upload-container');
var button = angular.element('.file-upload-button');
container.css({
position: 'relative',
overflow: 'hidden',
width: button.offsetWidth,
height: button.offsetHeight
})
}
};
});
a jade template if you are using jade
div(class="file-upload-container")
button(class="file-upload-button") +
input#file-upload(class="file-upload-input", type='file', onchange="doSomethingWhenFileIsSelected()")
the same template in html if you are using html
<div class="file-upload-container">
<button class="file-upload-button"></button>
<input class="file-upload-input" id="file-upload" type="file" onchange="doSomethingWhenFileIsSelected()" />
</div>
the css
.file-upload-button {
margin-top: 40px;
padding: 30px;
border: 1px solid black;
height: 100px;
width: 100px;
background: transparent;
font-size: 66px;
padding-top: 0px;
border-radius: 5px;
border: 2px solid rgb(255, 228, 0);
color: rgb(255, 228, 0);
}
.file-upload-input {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
It's also easy to style the label if you are working with Bootstrap and LESS:
label {
.btn();
.btn-primary();
> input[type="file"] {
display: none;
}
}