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;
}
}
Related
I'm still a novice at webdev and this is my first question here so please bare with me. I'm currently working on a website for my school and I'm trying to add a search box like this(with the search icon inside the box): click this
I'm following the search bar tutorial from w3schools, but their version is a bit different(search icon on the outside): click this
This is the html code for the search bar:
<input type="text" placeholder="Search..">
I want to put the search icon inside the box like the first picture, but the input tag is a empty tag, so I don't know how to put it inside. Please help me.
i have used font awesome for search icon, u can use local search icon, font awesome icons, material design icons or any icon source just use this below code.
.custom-select {
position: relative;
width: 250px;
outline: none;
height: 50px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background: none;
padding: 0;
border-radius: 5px;
z-index: 555;
}
.custom-select-search-icon {
position: absolute;
z-index: 2;
height: 22px;
width: 22px;
right: 10px;
opacity: 0.5;
}
.custom-select-input {
padding: 0 10px;
border-radius: inherit;
width: inherit;
height: inherit;
background: transparent;
color: #051833;
}
<!-- Load icon library -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<div class="custom-select">
<input type="text" placeholder="Search please" class="custom-select-input">
<i class="fa fa-search custom-select-search-icon"></i>
</div>
This should give you a basic idea of how it can be done:
document.getElementById('sb').addEventListener("click", function(e){
if(e.target.nodeName =='SPAN') {
let elem = e.target.children[0];
elem.focus();
}
});
.outer {
border: 1px solid gray;
padding: 10px;
border-radius:5px;
}
.outer img {
height: 22px;
width: 22px;
top:5px;
position:relative;
}
input {
/* Tell the input to use all the available space */
flex-grow:2;
/* And hide the input's outline, so the form looks like the outline */
border:none;
}
input:focus {
/* removing the input focus blue box. Put this on the form if you like. */
outline: none;
}
button {
/* Just a little styling to make it pretty */
border:1px solid blue;
background:blue;
color:white;
}
<span class="outer" id="sb">
<input placeholder="Search.."/>
<img src="http://assets.stickpng.com/thumbs/585e4ad1cb11b227491c3391.png">
</span>
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.
This question already has answers here:
HTML slider with two inputs possible?
(10 answers)
Closed 3 years ago.
I have a range slider that display the one value, but i wish to display 2 limits i.e min and max, something like a price range slider and then save the min and max value in database, but currently i have only one value.
There are various sliders made through js, but i am wondering can this code be modified to have both max and min values on a single slider (#fiddle)
<body>
<form>
<input type="range" name="amountRange" min="0" max="20" value="0" oninput="this.form.amountInput.value=this.value" />
<input type="number" name="amountInput" min="0" max="20" value="0" oninput="this.form.amountRange.value=this.value" />
</form>
</body>
You could create a widget yourself.
Broad idea:
Markup and Javscript:
Have two range inputs inside a container for the widget
Use data attributes on the container to hold the two values e.g. data-lbound for storing the lower value and data-ubound to store the higher value
Update the data attributes of the container on input event of the range inputs
Use these data attributes to retrieve the values any time required for form submission or any other use
CSS:
Use absolute positioning to position the two range inputs on top of each other inside the container
Stylize the range inputs to have their thumbs moved a little above so that overlapped range inputs do not prevent their usage
If required, hide the slider/bar/track
Create an ::after pseudo-element on the container with its content property set to the data attributes of the container. This will be used to display the current ranges.
Rest is all about beautifying the ranges inputs.
Here is a small demo that I created. (Test it out with Chrome or Firefox) Works with keyboard as well.
Fiddle: http://jsfiddle.net/abhitalks/a1f1k8d0/2/
Snippet:
.multi-range, .multi-range * { box-sizing: border-box; padding: 0; margin: 0; }
.multi-range {
position: relative; width: 160px; height: 28px; margin: 16px;
border: 1px solid #ddd; font-family: monospace;
}
.multi-range > hr { position: absolute; width: 100%; top: 50%; }
.multi-range > input[type=range] {
width: calc(100% - 16px);
position: absolute; bottom: 6px; left: 0;
}
.multi-range > input[type=range]:last-of-type { margin-left: 16px; }
.multi-range > input[type=range]::-webkit-slider-thumb { transform: translateY(-18px); }
.multi-range > input[type=range]::-webkit-slider-runnable-track { -webkit-appearance: none; height: 0px; }
.multi-range > input[type=range]::-moz-range-thumb { transform: translateY(-18px); }
.multi-range > input[type=range]::-moz-range-track { -webkit-appearance: none; height: 0px; }
.multi-range > input[type=range]::-ms-thumb { transform: translateY(-18px); }
.multi-range > input[type=range]::-ms-track { -webkit-appearance: none; height: 0px; }
.multi-range::after {
content: attr(data-lbound) ' - ' attr(data-ubound);
position: absolute; top: 0; left: 100%; white-space: nowrap;
display: block; padding: 0px 4px; margin: -1px 2px;
height: 26px; width: auto; border: 1px solid #ddd;
font-size: 13px; line-height: 26px;
}
<div class='multi-range' data-lbound='10' data-ubound='50'>
<hr />
<input type='range'
min='10' max='45' step='5' value='10'
oninput='this.parentNode.dataset.lbound=this.value;'
/>
<input type='range'
min='15' max='50' step='5' value='50'
oninput='this.parentNode.dataset.ubound=this.value;'
/>
</div>
Note: The above demo is well, just a demo. It will work perfectly in Chrome and Firefox, but I could not test it in IE/Edge. My feeling is that it will have problems with IE/Edge because the slider thumbs are inline with the track in those browsers. You can further customize and stylize it to work with IE/Edge.
I want to align the checkbox, label and text input in a same line using css. I can do it by using the default template of the browser.
However I really liked the simple theme given in this link. The theme has label and a input text. I wanted to add a checkbox as well at the beginning of the line. Somehow adding a checkbox inside the div makes the arrangement awry.
Though its better to look at the code in the link, I am providing a snapshot here:
HTML
<form>
<div>
<!--NEED TO ADD CHECKBOX HERE -->
<label for="pub_url">Public URL</label>
<input type="text" id="pub_url" name="pub_url" value="http://cssdeck.com">
</div>
</form>
CSS3
/* Onto the styling now. Some quick generic styles first. */
html, body {
width: 100%; height: 100%;
}
body {
font-size: 76%;
font-family: Verdana;
background: #eee;
padding: 50px 0;
}
form {
background: #fafafa;
padding: 20px;
width: 400px;
margin: 0 auto;
border: 1px solid #ffe2e3;
}
form div {
/* Float containment */
overflow: hidden;
}
/* Things are looking good now, onto the main input field
styling now! */
/*
Lets change the box model to make the label and input
contain into the 100% div.
You might want to specify the box sizing properties inside
`* {}` at the top.
Things are looking great now! Lets just spice it up a bit.
*/
form label, form input {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
form label {
font-weight: bold;
background: linear-gradient(#f1f1f1, #e2e2e2);
padding: 5px 10px;
color: #444;
border: 1px solid #d4d4d4;
/* lets remove the right border */
border-right: 0;
border-bottom-left-radius: 5px;
border-top-left-radius: 5px;
line-height: 1.5em;
width: 30%;
/* takes the width properly now and also the
spacing between the label and input field got removed. */
float: left;
text-align: center;
cursor: pointer;
}
/* The label is looking good now. Onto the input field! */
/*
Everything is broken now! But we can fix it. Lets see how.
*/
form input {
width: 70%;
padding: 5px;
border: 1px solid #d4d4d4;
border-bottom-right-radius: 5px;
border-top-right-radius: 4px;
line-height: 1.5em;
float: right;
/* some box shadow sauce :D */
box-shadow: inset 0px 2px 2px #ececec;
}
form input:focus {
/* No outline on focus */
outline: 0;
/* a darker border ? */
border: 1px solid #bbb;
}
/* Super! */
p.s: It will be delightful if someone can stylize the checkbox in the same way as the example
try this one,
form input[type="checkbox"] {
width:20px;
}
<div>
<input type="checkbox" >
<label for="pub_url">Public URL</label>
<input type="text" id="pub_url" name="pub_url" value="http://cssdeck.com">
</div>
http://jsfiddle.net/KW6AY/1/
Here you go \w quick styling:
http://codepen.io/daniesy/pen/puema
alter the css to input[type="text"] and lower the width to around 60% (so it won't affect your checkbox), add a checkbox with a float left
just rename class
form input into form input[type="text"]
Good luck.
I have a problem with IE & firefox. I believe the effect I wanted to achieve works only on chrome.
The problem is that it displays the dropdown perfectly in chrome like on this picture below:
and in firefox / ie it displays it in this way:
So, basically it keeps the default dropdown arrow.
here is a code:
<select name="gender">
<option value="">Gender</option>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
and css:
input {
height: 67px;
width: 400px;
border:none;
background:url(../_images/butt-reg.png) no-repeat;
padding: 0 20px;
margin: 0 10px 20px 10px;
text-align:left;
vertical-align: middle;
font-size: 18pt;
color: #666;
I'm sure there is a simple solution to sort it out, but i tried couple of things and nothing was working.
Thank you in advance.
Take a look at Style a Select Box Using Only CSS
Look here: http://result.dabblet.com/gist/3358882/5eeb2b8d4fe6adf243c5c463111d367c7651a029
I have tried to overlay the dropdown button with a custom one by using the after-pseudo-element on the parent node (a label-element in this case). The CSS property pointer-events makes sure that you can still click on the pink button to open the select-control.
Doing this cross-browser using CSS only is real hard (if not impossible) to do. The only way I can think of to style your <select> element is to simulate it. First, insert a hidden text input that'll have the selected value. Here's an example HTML that simulates a dropdown-select element:
<div class = "select">
<div class = "curVal">Gender</div><div class = "arrow">V</div>
<div class = "choices">
<div class = "choice">Male</div>
<div class = "choice">Female</div>
<div class = "choice">Refuse to answer</div>
</div>
</div>
Let's style it:
body {
font-family: 'Arial', Helvetica, Sans-Serif;
}
.select div {
display: inline-block;
}
.curVal {
height: 30px;
width: 150px;
line-height: 30px;
vertical-align: middle;
background-color: rgb(0, 162, 232);
color: white;
}
.arrow {
color: white;
background-color: rgb(0, 140, 200); /* this can be an image */
cursor: pointer;
height: 30px;
line-height: 30px;
vertical-align: middle;
position: absolute;
top: 0px;
}
.choices {
position: absolute;
left: 0px;
top: 30px;
background-color: rgb(255, 127, 39);
color: white;
padding: 3px 3px 3px 3px;
width: 150px;
}
.choices div {
display: block;
cursor: pointer;
}
Some jQuery:
$(document).ready()(function(){
$(".choices").hide();
});
$(".arrow").click(function(event) {
$(".choices").slideToggle("fast");
event.stopPropagation();
});
$(".choice").click(function() {
$(".curVal").html($(this).html());
$(".choices").slideToggle("fast");
event.stopPropagation();
});
$("html").click(function() {
$(".choices").slideUp("fast");
});
Put them all together, you get this: jsFiddle.
I hope that helped you in any manner!