CSS: How to make custom file upload button take full width (button works) - html

I am new to CSS and hope someone here can help me with this.
I am trying to apply a simple custom style to a file upload button (as part of an HTML form) to make it look similar to other buttons on my page and to get a similar look cross-browser.
So far I have the following which works as intended.
My only problem now is that I would like the button to take the full width of its parent div (in my case this will span across 9/12 ('col-9') of the page).
I tried adding width: 100%; to the CSS but then the button doesn't work anymore.
My HTML:
<div class="col-3 frmCaption">Attachments:</div>
<div class="col-9">
<div class="customUpload btnUpload btnM">
<span>Upload files</span>
<input type="file" class="upload" />
</div>
</div>
My CSS:
.btnDefault, .btnUpload {
background-color: #FFFFFF;
border: 1px solid #CCCCCC;
color: #333333;
cursor: pointer;
font-weight: 400;
display: inline-block;
padding: 6px 12px;
text-align: center;
text-decoration: none;
vertical-align: middle;
}
.btnDefault:focus, .btnDefault:hover, .btnUpload:focus, .btnUpload:hover {
background-color: #E6E6E6;
}
.btnM {
border-radius: 4px;
font-size: 14px;
padding: 6px 12px;
}
.customUpload {
overflow: hidden;
position: relative;
}
.customUpload input.upload {
cursor: pointer;
margin: 0;
opacity: 0;
filter: alpha(opacity=0);
padding: 0;
position: absolute;
right: 0;
top: 0;
}

To style input elements, you need to actually style its label element.
From MDN,
The HTML Label Element () represents a caption for an item in a user interface. It can be associated with a control either by placing the control element inside the element, or by using the for attribute. Such a control is called the labeled control of the label element.
So, whenever you click a label, the attached input gets triggered.
So, just wrap the input element in a label instead of a div and stretch as much as you want. That will fix your issue.
.btnDefault,
.btnUpload {
background-color: #FFFFFF;
border: 1px solid #CCCCCC;
color: #333333;
cursor: pointer;
font-weight: 400;
display: inline-block;
padding: 6px 12px;
text-align: center;
text-decoration: none;
vertical-align: middle;
}
.btnDefault:focus,
.btnDefault:hover,
.btnUpload:focus,
.btnUpload:hover {
background-color: #E6E6E6;
}
.btnM {
border-radius: 4px;
font-size: 14px;
padding: 6px 12px;
}
.customUpload {
overflow: hidden;
position: relative;
display: block;
}
.customUpload input.upload {
cursor: pointer;
margin: 0;
opacity: 0;
filter: alpha(opacity=0);
padding: 0;
position: absolute;
right: 0;
top: 0;
}
<div class="col-3 frmCaption">Attachments:</div>
<div class="col-9">
<label class="customUpload btnUpload btnM"> <span>Upload files</span>
<input type="file" class="upload" />
</label>
</div>
Working Fiddle

You need to apply the width property to the containing <div> as well. Once the div has the full size, then only the button inside can have the full width.
For simplicity i have made change to html, you can move it to appropriate classes.
<div class="col-3 frmCaption">Attachments:</div>
<div class="col-9">
<div class="customUpload btnUpload btnM" style="width:100%;">
<span>Upload files</span>
<input type="file" class="upload" style="width:100%;"/>
</div>
</div>
JS Fiddle
Or you can use this CSS andadd it both to your div and file upload,
.fullwidth
{
width : 100%;
}
<div class="col-3 frmCaption">Attachments:</div>
<div class="col-9">
<div class="customUpload btnUpload btnM fullwidth">
<span>Upload files</span>
<input type="file" class="upload fullwidth"/>
</div>
</div>

Make the button take 12 cols (as you use a 12 col system) , as that is the max number of cils available, in that way the elemts will take up the size of the div that it is contained in

Related

Radio Button Method - HTML Accordion

I would like some assistance with my accordion code,
My idea is to get something like this:
The Radio Button Method adds a hidden radio input and a label tag to each accordion tab.
The logic is straightforward:
when a user selects a tab, they essentially check the radio button associated with that tab.
when a user clicks the next tab in the accordion, the next radio button is selected, and so on.
Only one tab can be open at a time using this method.
I'd like some advice on how to incorporate this into my current accordion code.
<!doctype html>
<html>
<head>
<style>
input {
display: none;
}
label {
display: block;
padding: 8px 22px;
margin: 0 0 1px 0;
cursor: pointer;
background: #6AAB95;
border-radius: 3px;
color: #FFF;
transition: ease .5s;
position: relative; /* ADDING THIS IS REQUIRED */
}
label:hover {
background: #4E8774;
}
label::after {
content: '+';
font-size: 22px;
font-weight: bold;
position: absolute;
right: 10px;
top: 2px;
}
input:checked + label::after {
content: '-';
right: 14px;
top: 3px;
}
.content {
background: #E2E5F6;
padding: 10px 25px;
border: 1px solid #A7A7A7;
margin: 0 0 1px 0;
border-radius: 3px;
}
input + label + .collapse {
display: none;
}
input:checked + label + .collapse {
display: block;
}
</style>
</head>
<body>
<input type="checkbox" id="title1" />
<label for="title1">Accordion 1</label>
<div class="collapse">
<p>Your content goes here inside this division with the class "content".</p>
</div>
<input type="checkbox" id="title2" />
<label for="title2">Accordion 2</label>
<div class="collapse">
<p>Your content goes here inside this division with the class "content".</p>
</div>
</body>
</html>
No need to change the CSS (at least the part handling the accordion functionality) but you'd have to change a bit in your HTML.
To get the desired accordion effect where only one tab can be open at a time you should:
use radio buttons instead of checkboxes (input[type="radio"]).
And the important part is to give those radio buttons the same name (the attribute name must be the same for all the accordion component's radio buttons) in order to achieve the desired outcome.
Here's a a live demo:
/** nothing changed on the CSS part, see the HTML part for the required changes */
input {
display: none;
}
label {
display: block;
padding: 8px 22px;
margin: 0 0 1px 0;
cursor: pointer;
background: #6AAB95;
border-radius: 3px;
color: #FFF;
transition: ease .5s;
position: relative;
/* ADDING THIS IS REQUIRED */
}
label:hover {
background: #4E8774;
}
label::after {
content: '+';
font-size: 22px;
font-weight: bold;
position: absolute;
right: 10px;
top: 2px;
}
input:checked+label::after {
content: '-';
right: 14px;
top: 3px;
}
.content {
background: #E2E5F6;
padding: 10px 25px;
border: 1px solid #A7A7A7;
margin: 0 0 1px 0;
border-radius: 3px;
}
input+label+.collapse {
display: none;
}
input:checked+label+.collapse {
display: block;
}
<!-- changed "type=checkbox" to "type=radio" -->
<!-- added the same "name" attribute value for all the radio buttons -->
<input type="radio" name="radio-btn" id="title1" />
<label for="title1">Accordion 1</label>
<div class="collapse">
<p>Your content goes here inside this division with the class "content".</p>
</div>
<!-- changed "type=checkbox" to "type=radio" -->
<!-- added the same "name" attribute value for all the radio buttons -->
<input type="radio" name="radio-btn" id="title2" />
<label for="title2">Accordion 2</label>
<div class="collapse">
<p>Your content goes here inside this division with the class "content".</p>
</div>
CAUTION: Even though the radio buttons hack works as needed, there is no way you can close all the accordion items after interacting for the first time (you can have a closed accordion initially though).
I have found this example using Sass that looks exactly like what you need: https://codepen.io/alvarotrigo/pen/dyJbqpd.
The example uses radio buttons, such as <input type="radio" id="title1" name="select"/>. Because they have the same name, you can only select one at a time.
In your example, you have checkboxes like in this example at w3schools.com. Using checkboxes, you can tick any number of checkboxes at a time, therefore the current accordion behavior.
Here's a stripped-down version (converted to CSS):
input {
position: absolute;
opacity: 0;
z-index: -1;
}
.tab {
overflow: hidden;
}
.tab-label {
display: flex;
justify-content: space-between;
padding: 1em;
background: #2c3e50;
color: white;
cursor: pointer;
}
.tab-content {
max-height: 0;
padding: 0 1em;
color: #2c3e50;
background: white;
}
input:checked ~ .tab-content {
max-height: 100vh;
padding: 1em;
}
<div class="tab">
<input type="radio" id="rd1" name="rd">
<label class="tab-label" for="rd1">Item 1</label>
<div class="tab-content">Content</div>
</div>
<div class="tab">
<input type="radio" id="rd2" name="rd">
<label class="tab-label" for="rd2">Item 2</label>
<div class="tab-content">Content</div>
</div>
I have slightly changed your code and added another div with overflow: hidden:
/** nothing changed on the CSS part, see the HTML part for the required changes */
input {
display: none;
}
label {
display: block;
padding: 8px 22px;
margin: 0 0 1px 0;
cursor: pointer;
background: #6AAB95;
border-radius: 3px;
color: #FFF;
transition: ease .5s;
position: relative;
/* ADDING THIS IS REQUIRED */
}
label:hover {
background: #4E8774;
}
label::after {
content: '+';
font-size: 22px;
font-weight: bold;
position: absolute;
right: 10px;
top: 2px;
}
input:checked+label::after {
content: '-';
right: 14px;
top: 3px;
}
.content {
background: #E2E5F6;
padding: 10px 25px;
border: 1px solid #A7A7A7;
margin: 0 0 1px 0;
border-radius: 3px;
}
input+label+.collapse {
display: none;
}
input:checked+label+.collapse {
display: block;
}
<div class="tab">
<input type="radio" id="title1" name="select"/>
<label for="title1">Accordion 1</label>
<div class="collapse">
Your content goes here inside this division with the class "content".
</div>
</div>
<div class="tab">
<input type="radio" id="title2" name="select" />
<label for="title2">Accordion 2</label>
<div class="collapse">
Your content goes here inside this division with the class "content".
</div>
</div>

How to fit content inside div element?

I am trying to fix my content inside my div tag. I have only fit in some of the content inside it, but there is more that needs to be put inside it. I need help.
Note I am doing Angular but I need to fix my HTML & CSS only.
My HTML
<div class="contentBox">
<h1>Please Type In Your Address</h1>
<form (ngSubmit)="onSubmit()" [formGroup]="addressData">
<input class="addressBar" type="text" placeholder="Address" maxlength="30" formControlName="address" autofocus>
</form>
<a routerLink=""><button class="button">Proceed</button></a><br><br>
<a routerLink="mainMenu"><button class="button">Cancel</button></a>
</div>
CSS
.button {
padding: 20px 30px;
font-size: 25px;
background-color: lightblue;
position: relative;
top: 28em;
left: 3em;
}
.button:hover {
padding: 22px 32px;
}
.contentBox {
display: inline-block;
background-color: lightgray;
}
.addressBar {
padding: 20px;
font-size: 30px;
border: 3px black inset;
text-align: center;
position: relative;
top: 3em;
}
Output
You can see the two buttons are not within the div (in grey). How do I expand the div so it will be behind the buttons, providing the background for all the content?
Thanks!
You need to replace your top styles with margin as shown in the fiddle https://jsfiddle.net/saksham_malhotra/cnLrv87f/
By providing top coordinates with position relative, you are shifting your element position without considering the containing element.
It's because you're using position: relative for your address bar and buttons. This shifts that element down by whatever your top value is, relative to where it's normal position is. I would use margin-top to achieve the same effect for your purpose.
.button {
padding: 20px 30px;
font-size: 25px;
background-color: lightblue;
}
.button:hover {
padding: 22px 32px;
}
.contentBox {
display: inline-block;
background-color: lightgray;
}
.addressBar {
padding: 20px;
font-size: 30px;
border: 3px black inset;
text-align: center;
margin-top: 3em;
}
<div class="contentBox">
<h1>Please Type In Your Address</h1>
<form (ngSubmit)="onSubmit()" [formGroup]="addressData">
<input class="addressBar" type="text" placeholder="Address" maxlength="30" formControlName="address" autofocus>
</form>
<a routerLink=""><button class="button">Proceed</button></a><br><br>
<a routerLink="mainMenu"><button class="button">Cancel</button></a>
</div>
You can read more about the position property here
Try this:
<html>
<head>
<style>
textarea {
width:100%;
max-width:250px;
padding: 0 0 80px 0;
}
.contentBox {
display: inline-block;
background-color: lightgray;
}
.addressBar {
/*some style*/}
.button {/*button style here*/}
</style>
</head>
<body>
<div class="contentBox">
<h1>Please Type In Your Address</h1>
<form (ngSubmit)="onSubmit()" [formGroup]="addressData">
<textarea class="addressBar" type="text" placeholder="Address" maxlength="30" formControlName="address" autofocus></textarea>
</form>
<a routerLink=""><button class="button">Proceed</button></a><br><br>
<a routerLink="mainMenu"><button class="button">Cancel</button></a>
</div>
</body>
</html>

How do I get this section with the form to center. The form field and button aren't centering

I need the text to center in the middle of the section and the field and button to align under that text (with the field and button remaining side by side.) Everything is good - the field and button are currently beside each other the way it's supposed to be, but just it's all not centering properly. The text is centered but the form field and button are messed up. I have attached an image. I'm using HTML5, CSS3 and bootstrap.
<section class="more-products">
<div class="container">
<div class="row">
<div class=" col-lg-8 col-md-4 col-sm-4 prod-form">
<p class="par-headform"> TEXT</p>
<p class="para-form">
text about products
</p>
<p class="para-blue">
Sign up for the newsletter Stay informed
</p>
<form class="subscribe_group wow fadeInUp row col-m-12">
<div class=" col-md-6 col-sm-6 col-xs-5 ">
<input class="form-control subscribe_mail" type="email" placeholder="email">
</div>
<div class="col-md-5 col-sm-6 col-xs-5 " >
<input class="btn-form" type="submit" value="Subscribe">
</div>
</form>
</div>
</div>
</div>
</section>
CSS
.more-products {
padding: 60px 0;
background: #FCFCFC;
text-align: center;
}
.more-products .block {
position: relative;
z-index: 99;
}
.more-products .par-headform .block {
padding: 20px 15px;
margin-top: 0;
color: #666;
}
.prod-form .btn-form {
border: 1px solid #00bfff;
background-color: #fff;
color: #00bfff;
padding: 3% 14%;
font-weight: 500;
text-decoration: none;
border-radius: 200px;
transition: background-color 0.2s, border 0.2s, color 0.2s;
border: 1px solid #00bfff;
background-color: #fff;
letter-spacing: .8px;
font-size: 120%;
display: inline-block;
}
.prod-form .btn-form: Hover{
color: #00bfff;
padding: 3% 14%;
font-weight: 500;
text-decoration: none;
border-radius: 200px;
transition: background-color 0.2s, border 0.2s, color 0.2s;
border: 1px solid #00bfff;
background-color: #fff;
letter-spacing: .8px;
font-size: 120%;
display: inline-block;
}
.par-headform {
font-size: 250%;
line-height: 35px;
}
.form-control {
max-width: auto;
margin: 1px;
}
Try this:
<form class="subscribe_group wow fadeInUp row col-m-12">
<div class="col-lg-8 col-md-4 col-sm-4 center1">
<input class="form-control subscribe_mail" type="email" placeholder="email">
<input class="btn-form" type="submit" value="Subscribe">
</div>
</form>
I removed the DIV tags around the two input elements (to have them in one wrapper), gave the parent DIV the same classes as the DIV for the texts above it and added an additional class center1, which you have to put into your CSS like
.center1 {
text-align: center;
}
The input elements need to be defined as inline-blocks, if they aren't already:
.subscribe_mail, .btn-form {
display: inline-block;
}
Since you don't have a fiddle or codepen, I can't try it, but it should work - maybe the classes in the DIV around the input tags need to be different, that depends on the rest of your code.
use the following css for form and div's inside the form.
form {
width: auto;
display: inline-table;
}
form > div {
margin: 0 auto;
float: left;
}
and change subscribe padding to px instead of % like below example
.prod-form .btn-form {
padding: 3px 6px;
}
UPDATE
use the following css to the section
section {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
}
check the jsfiddle https://jsfiddle.net/s45wgw1h/1/

Position button segment right

I'm writing a CSS framework and when it comes to handling buttons I'm trying to make it so that the user can segment the button (this is done, see the fiddle below) - however, I want to add another semantic CSS selector that will allow the user to positon this left/right of the button text (automatically right). My issue is, however - I don't want to affect the HTML in any way, the HTML structure is the same for every other button, so I'd rather not altar this if possible.
I've tried floating the segment left, afterwards I thought it was pretty obvious that wouldn't work - the height of the button is also dependent on the padding of the segment - so (as far as I'm aware) it's not possible to position this absolutely. I'm having a mental block as to how to achieve this.
Here is my current CSS:
.dte.button {
border-radius: 0;
display: inline-block;
border: 0;
outline: 0;
padding: 10px;
background: #34495e;
color: white;
font-family: 'Roboto', sans-serif;
text-transform: uppercase;
cursor: pointer;
transition: 0.25s all;
position: relative;
}
button.dte.button.segmented {
padding: 0;
padding-left: 10px;
position: relative;
}
.dte.button .segment {
filter: brightness(50%);
background: rgba(0, 0, 0, 0.53);
padding: 10px;
display: inline-block;
margin-left: 10px;
}
And my HTML structure
<button class="dte button segmented">
This should align the segment RIGHT (it does)
<div class="segment">
<i class="fa fa-align-right"></i>
</div>
</button>
<button class="dte button segmented left">
This should align the segment LEFT(It doesn't)
<div class="segment">
<i class="fa fa-align-left"></i>
</div>
</button>
Fiddle of what I current have.
It is not pretty, but you can use float:left if you then fix your spacing with some negative margins.
So for example:
.dte.button {
border-radius: 0;
display: inline-block;
border: 0;
outline: 0;
padding: 10px;
background: #34495e;
color: white;
font-family: 'Roboto', sans-serif;
text-transform: uppercase;
cursor: pointer;
transition: 0.25s all;
position: relative;
}
button.dte.button.segmented {
padding: 0;
padding-left: 10px;
position: relative;
}
button.dte.button.segmented.left {
padding: 10px 10px 10px 0;
}
.dte.button .segment {
filter: brightness(50%);
background: rgba(0, 0, 0, 0.53);
padding: 10px;
display: inline-block;
margin-left: 10px;
}
.dte.button.left .segment {
float: left;
margin: -10px 10px -10px 0;
}
<div style="padding: 20px;">
<button class="dte button">dte-button</button>
<button class="dte button segmented">
Dropdown Button
<div class="segment">
ICON
</div>
</button>
<button class="dte button segmented">
Segment Aligned Right
<div class="segment">
ICON
</div>
</button>
<button class="dte button segmented left">
Segment Aligned Left
<div class="segment">
ICON
</div>
</button>
</div>
Here also a fiddle.

Why is the same text content rendered differently in <input> than in <div> or <span> tags?

The Situation
I have two pages with identical content and styling. The difference between them is that one lists items with <div> elements and the other with <input> elements (for showing and editing a resource, respectively).
I'd like both pages to have the same layout. I've achieved the layout I want on the standard <div> page and would like to duplicate it on the page with <input> elements. Both pages have the same CSS rules applied to them as well as Eric Mayer's Reset.
The Problem
Text is rendered differently in a <div> element than it is in an <input> element and results in an <input> that is too high.
What's Been Tried
I've tried setting the height of the input so that it is the same as the div, though that causes the text to become clipped at the bottom. I couldn't find a way to remove the white space at the top of the input.
I also did a diff of the computed styles for each element and they are almost identical (aside from a few styles that have no affect on the issue here).
The Question
Is there a way to make the input in the first picture match the height of the div in the second?
Additionally, is there a place where I can learn more about how/why browsers have this sort of behavior and what controls it? I've already read through W3C's CSS Fonts Module Level 3 with unsatisfactory results.
See current state (input, div):
.recipe .header {
margin-bottom: 50px;
text-align: left;
font-weight: 600;
color: #f0424b;
}
.form-recipe input {
font-family: "futura-pt";
}
.header {
margin-bottom: 40px;
font-size: 3em;
text-align: center;
}
// Reset
input {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-family: inherit;
font-size: 100%;
vertical-align: baseline;
}
// User agent stylesheet
input {
padding: 1px 0px;
-webkit-appearance: textfield;
padding: 1px;
background-color: white;
border: 2px inset;
border-image-source: initial;
border-image-slice: initial;
border-image-width: initial;
border-image-outset: initial;
border-image-repeat: initial;
-webkit-rtl-ordering: logical;
-webkit-user-select: text;
cursor: auto;
}
<div class="delicious">
<form name="recipe.edit" class="form form-recipe recipe">
<div class="form-group">
<div class="form-row">
<input type="text" class="header" value="Banana Bread"/>
</div>
</div>
</form>
</div>
.recipe .header {
margin-bottom: 50px;
text-align: left;
font-weight: 600;
color: #f0424b;
}
.header {
margin-bottom: 40px;
font-size: 3em;
text-align: center;
}
// Reset
div {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-family: inherit;
font-size: 100%;
vertical-align: baseline;
}
// User agent stylesheet
div {
display: block;
}
<div class="delicious">
<div class="recipe">
<div class="header">
Banana Bread
</div>
</div>
</div>
How about this? That works if you want them exactly identical. (The spaces between them are because of the other wrappers)
HTML
<div class="delicious">
<form name="recipe.edit" class="form form-recipe recipe">
<div class="form-group">
<div class="form-row">
<input type="text" class="header" value="Banana Bread"/>
</div>
</div>
</form>
</div>
<!------------------------------------------------------------>
<div class="delicious">
<div class="recipe">
<div class="header">
Banana Bread
</div>
</div>
</div>
CSS
.recipe .header {
margin-bottom: 50px;
text-align: left;
font-weight: 600;
color: #f0424b;
}
.form-recipe input {
font-family: "futura-pt";
}
.header {
margin-bottom: 40px;
font-size: 3em;
text-align: center;
width:100%;
border:none;
padding:0;
outline:0;
}
Though I personally wouldn't recommend this, because I believe the user needs to realize that it's now able to edit the contents, anyway, maybe set outline-color:#f0424b and focus the element on edit? outline does not affect the element's width/height but it does give some clue that you are in focus and able to edit.
Hope it helps!