Imagine a newsletter subscription form. I have the form with just two different field types (text, checkbox), some of them need to be complete before submission. For sure, the required email field and at least one from the checkboxes. The submit/subscribe button should stay disabled until the condition from above is fulfilled. It also should revert from enabled to disabled state when the fields with values get empty.
I know this kind of question has been answered here a few times already. I went through some examples from previous questions of this functionality working with radios and checkboxes or <input> fields only:
Disabling submit button until all fields have values
Disable submit button until all form inputs have data
Some of them are answered but used code is outdated. Moreover, I'm not able to make a working code for my specific case. Quite close was Disable submit button with jQuery until all fields have values (input, radio, select, checkbox).
I used them all to make it to as far as here:
I can count a number of filled fields and enable the button when at least two of them are completed. However, two checkboxes (without the email) are enough - which is wrong. Can you please help me?
$(function() {
$('.subscribe-form').on('input',':input',function() {
var inputs = $('.subscribe-form :input');
var num_inputs = inputs.length;
var num_filled = inputs.filter(function() { return $(this).is(':checkbox')?$(this).is(':checked'):!!this.value }).length;
$('.subscribe-form :submit').prop('disabled',(num_filled+1<num_inputs));
});
});
.subscribe-form {
width: 400px;
margin: 50px;
}
.subscribe-form__row {
padding: 0 0 10px;
margin: 0 0 10px;
border-bottom: 1px solid grey;
}
p {
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<fieldset class="subscribe-form">
<div class="subscribe-form__row">
<p>E-mail</p>
<input type="text" placeholder="your e-mail" />
</div>
<div class="subscribe-form__row">
<p>Interests</p>
<label for="checkbox-1">Nature</label>
<input id="checkbox-1" type="checkbox" />
<label for="checkbox-2">Travel</label>
<input id="checkbox-2" type="checkbox" />
</div>
<input type="submit" value="Subscribe" disabled />
</fieldset>
I would count the email field and checkboxes separately.
Below, I added the required class to ease the selection of the required elements. Maybe you will need some not requiered fields someday.
Then, for the email field, I added an email class, because maybe you will want to add some first and last name fields in the future. I would suggest you to test it againt a regular expression instead of just empty... See this other SO answer to start on that.
Then having my_condition in a variable makes the code easier to read and maintain AND to debug... ;)
$(function() {
$('.subscribe-form').on('input',':input',function() {
console.clear() // Just for this demo...
var email = $('.subscribe-form .required.email').filter((i,el)=>el.value!=="");
var checkboxes = $('.subscribe-form .required:checkbox:checked');
console.log("email",email.length,"checkbox",checkboxes.length)
var my_condition = email.length>0 && checkboxes.length>0
console.log(my_condition)
$('.subscribe-form :submit').prop('disabled',!my_condition);
});
});
.subscribe-form {
width: 400px;
margin: 50px;
}
.subscribe-form__row {
padding: 0 0 10px;
margin: 0 0 10px;
border-bottom: 1px solid grey;
}
p {
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<fieldset class="subscribe-form">
<div class="subscribe-form__row">
<p>E-mail</p>
<input type="text" placeholder="your e-mail" class="required email"/>
</div>
<div class="subscribe-form__row">
<p>Interests</p>
<label for="checkbox-1">Nature</label>
<input id="checkbox-1" type="checkbox" class="required" />
<label for="checkbox-2">Travel</label>
<input id="checkbox-2" type="checkbox" class="required" />
</div>
<input type="submit" value="Subscribe" disabled />
</fieldset>
I'm trying to style the superslim Mailchimp form to go onto our homepage. I've created a new div to wrap it all in, and copied and pasted the code in and currently it appears below:
<div class="mailChimp">
****Copied Code****
<form action="blahblahblah" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<input type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="Email Address" required>
</div>
<div class="clear">
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded- subscribe" class="button">
</div>
Then in my CSS:
#mailChimp{
max-width:245px;
margin-left: 55px
}
#mce-EMAIL{
margin-bottom: 5px;
margin-top: 5px;
width: 95%
}
#mc-embedded-subscribe {
margin-bottom: 5px;
margin-top: 5px;
}
Now, this seems to have the correct IDs attached as it appears correctly in Dreamweaver. However, when I upload the files to the server then none of the CSS styling is applied.
None of the css is applying, which is frustrating! Even the div ID mailChimp isn't. I can't even find it in the inspected element.
Am I selecting the ID's incorrectly?
The main confusion comes from the fact that It appears correctly in Dreamweaver which is reading from the style sheet, but not when I upload both files live.
'mailChimp' is a class, so it starts with a . in the css not a #:
.mailChimp{
max-width:245px;
margin-left: 55px;
}
The margin-left had not been closed with a ;. Also, in mce-email, you have not closed the width tab with a ;.
In your css, you have '#mc-embedded-subscribe' but in the HTML is it written with a big gap between embedded- and subscribe.
I have a form whose submit input button has a background-image and is shifted left over the top of the input field:
This works in all current browsers. My problem is that it also needs to work in IE8 on Windows XP (!), and it doesn't. When you hover over the input (the magnifying glass), the pointer does not change, and the button is not clickable. Any ideas where I'm going wrong please?
HTML:
<form id="" action="" method="post">
<label for="search">Search</label>
<input type="text" id="search" name="search" value="" />
<input type="submit" name="searchsub" class="searchsub" value="" />
</form>
CSS:
#search {
width:222px;
height:36px;
padding-left:223px;
padding-right:10px;
float:left;
}
input.searchsub {
width:23px;
height:23px;
float:left;
background-image:url(../images/magnifier.jpg);
margin:8px 0 0 -32px;
border:0;
cursor:pointer;
}
This is a start: (demo: http://jsfiddle.net/KYL3A/)
I removed your floats and added a div as a "border wrapper". I think this will make IE8 play :) though I couldn't test it myself as I don't have IE8
<form id="" action="" method="post">
<div id="searchwrap">
<label for="search">Search</label>
<input type="text" id="search" name="search" value="" />
<input type="submit" name="searchsub" class="searchsub" value="" />
</div>
</form>
CSS
#searchwrap {
display: inline-block;
border: 1px solid #333;
padding: 0 10px;
}
#search {
width:150px;
height:36px;
border:0;
}
input.searchsub {
width:23px;
height:23px;
background:red url(); // added red as i dont have your image
margin:8px 0 0 0px;
cursor:pointer;
}
If you use the button element in an HTML form, different browsers will submit different values. Internet Explorer will submit the text between the and tags, while other browsers will submit the content of the value attribute. Use the input element to create buttons in an HTML form.
Therefore this would not work in the web browser you are saying (IE + XP) because that browser does not support it. There is no problem in your code. So i would say that just leave it like this, because there would not be many users of your website who are running Internet Explorer on XP but if there are many then you may want to put some text in there.
Source:
The first answer on this page and this source
Hi I would like the form width to be 100%. I would like the text box to extend almost the entire width of the page, and have the small "GO" button directly to the right of the text box, all on the same line (or block).
Right now my text box is only about the width of the text within it ("Enter an address here") Thank you!
CSS
#search1{
height: 25px;
padding:5px;
padding-left:11px;
display:inline-block;
background-color:#62564A;
width:100%;
}
HTML
<div id="search1">
<form style="margin: 0px; padding: 0px;" name="search_form" action="view" method="get" onsubmit="codeAddress(); return false">
<input id="address" style="color:#333" value="Enter an address here" onfocus="if(this.value==this.defaultValue) this.value='';"/>
<input type="button" value="GO" onclick="codeAddress()"/>
</form>
</div>
By default the form with is 100% if you do not change it. If you want the input field to be longer you can use the size attribute.
<input id="address" size="90" style="color:#333" value="Enter an address here" onfocus="if(this.value==this.defaultValue) this.value='';"/>
FIDDLE
Or you can achieve it through CSS by adding this:
#address{
width:80%;
}
css:
#search1{
height: 25px;
padding:5px;
padding-left:11px;
display:inline-block;
background-color:#62564A;
width:100%;
}
#search1 button {width:10%;}
#search1 input#address {width:85%;margin-left:5%;}
HTML
<div id="search1">
<form style="margin: 0px; padding: 0px;" name="search_form" action="view" method="get" onsubmit="codeAddress(); return false">
<input id="address" style="color:#333" value="Enter an address here" onfocus="if(this.value==this.defaultValue) this.value='';"/>
<button type="button" onclick="codeAddress()"> GO </button>
</form>
</div>
You could also do this with a bit of Jquery
CSS:
#search1{
height: 25px;
padding:5px;
padding-left:11px;
display:inline-block;
background-color:#62564A;
width:99%;
}
input {
display: inline-block;
}
Jquery:
$(document).ready(function () {
var $ww = $(window).width();
var $input = $('input#address');
$input.width($ww - 90);
$(window).resize(function() {
$input.width($(window).width() - 90);
});
});
I have kept the HTML the same.
include the Jquery library in your <head> tag with <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
You may need to tweek the - 90 to a lower or higher value depending on where you place the form.
Here is a link to the working example.
I've gotten used to using <table>s for aligning my form fields perfectly. This is how I commonly write my forms:
<table border="0">
<tr>
<td><label for="f_name">First name:</label></td>
<td><input type='text' id='f_name' name='f_name' /></td>
<td class='error'><?=form_error('f_name');?></td>
</tr>
</table>
I know this is bad practice, and I want to use CSS, <label>s, <div>s, or a cleaner method. However, the fact is, <table>s work extremely well for the forms. Everything is aligned exactly right, the spacing is perfect, all errors exactly below each other, etc.
I recently tried using <dt> and <dd> tags for a form, but I ended up reverting back to tables just because they looked so much better.
How can I get this kind of aligned table layout without using <table>s?
This might not get a lot of support but here's my two cents:
In some situations tables are easier for layout; such as three columns or forms (albeit there are some great suggestions here for doing a pure css form layout so don't ignore those either.)
Processes and methodologies can make good servants but are poor masters.
- Mark Dowd, John McDonald & Justin Schuh
in "The Art of Software Security Assessment"
I believe that this quote very strongly applies to this situation. If your table layout is working for you, not causing accessibility issues and isn't broken - then don't fix it.
Phrases like: "you should", "must", "always" - make me scared, because one-size-doesn't-fit-all! Take zealots with a grain of salt.
Yes, use labels and CSS:
<label class='FBLabel' for="FName">First Name</label>
<input value="something" name="FName" type="text" class='FBInput'>
<br>
css:
.FBLabel, .FBInput {
display:block;
width:150px;
float:left;
margin-bottom:10px;
}
See: http://www.alistapart.com/articles/prettyaccessibleforms
If you don't use tables you need to know the width of your labels upfront. This can often be a problem for multi-language sites (i18n).
With tables, they stretch to fit labels of differing sizes. CSS alone can't do that yet in a well-supported way.
Why do you not want to use tables? It sounds like they are working perfectly for you now. Are you worried about accessibility issues? Just because it is a table doesn't mean that accessibility will suffer.
I want to caution you from creating a new solution to a solved problem for nothing other than purity's sake. Even if you are worried about semantics, what kind of semantics describe a form anyway?
Most of the non-table based answers here rely on pre-determined fixed widths, which can be a pain for internationalisation, or any other scenario where you can't be certain of the required width for labels.
But CSS has display: table for this very reason:
HTML
<div class="form-fields">
<div class="form-field">
<label class="form-field-label" for="firstNameInput">First Name</label>
<div class="form-field-control"><input type="text" id="firstNameInput"></div>
<div class="form-field-comment">Required</div>
</div>
<div class="form-field">
<label class="form-field-label" for="lastNameInput">Last Name</label>
<div class="form-field-control"><input type="text" id="lastNameInput"></div>
<div class="form-field-comment">Required</div>
</div>
</div>
CSS
.form-fields {
display: table;
}
.form-field {
display: table-row;
}
.form-field-label,
.form-field-control,
.form-field-comment {
display: table-cell;
padding: 3px 10px;
}
Simple.
I use the following method most of the time and it allows me to get all my alignment set up exactly how I like it. As you can see, it gives me a great number of hooks for CSS and JS.
<form id="login-form" action="#" method="post">
<fieldset>
<label id="for-email" for="email">
<span class="label-title">Email Address <em class="required">*</em></span>
<input id="email" name="email" type="text" class="text-input" />
</label>
<label id="for-password" for="password">
<span class="label-title">Password <em class="required">*</em></span>
<input id="password" name="password" type="password" class="text-input" />
</label>
</fieldset>
<ul class="form-buttons">
<li><input type="submit" value="Log In" /></li>
</ul>
</form><!-- /#login-form -->
Really depends on who you talk to. The purists say use CSS because the table element was not meant for layout. But for me, if it works, why change it? I do use CSS now for layout, but I still have plenty of legacy code I have not and will not change.
There are tons of ways out there to do it without tables. Once you get the basic format down it's as easy to work with as tables are, it's just the initial playing around that can be a pain. So, just look to others that have already done the work of figuring it all out for you:
http://www.alistapart.com/articles/prettyaccessibleforms
http://woork.blogspot.com/2008/06/clean-and-pure-css-form-design.html
I also documented the method I've settled on last week (a snippet):
<form action="/signup" method="post">
<fieldset>
<legend>Basic Information</legend>
<ol>
<li><label for="name">Name <span class="error">*</span>
</label><input type="text" id="name" name="name" size="30" /></li>
<li><label for="dob">Date of Birth <span class="error">*</span></label>
<div class="inputWrapper">
<input type="text" id="dob" name="dob" size="10" />
<span class="note">YYYY-MM-DD</span></div></li>
<li><label for="gender">Gender <span class="error">*</span></label>
<select id="gender" name="gender">
<option value=""></option>
<option value="female">Female</option>
<option value="male">Male</option>
</select></li>
</ol>
</fieldset>
</form>
And the CSS:
fieldset {
margin: 0 0 20px 0; }
fieldset legend {
font-weight: bold;
font-size: 16px;
padding: 0 0 10px 0;
color: #214062; }
fieldset label {
width: 170px;
float: left;
margin-right:10px;
vertical-align: top; }
fieldset ol {
list-style:none;
margin: 0;
padding: 0;}
fieldset ol li {
float:left;
width:100%;
padding-bottom:7px;
padding-left: 0;
margin-left: 0; }
fieldset ol li input,
fieldset ol li select,
fieldset ol li textarea {
margin-bottom: 5px; }
form fieldset div.inputWrapper {
margin-left: 180px; }
.note {
font-size: 0.9em; color: #666; }
.error{
color: #d00; }
jsFiddle
There's no one-size-fits-all for this. The table example you used can be improved on, though:
<table>
<tbody>
<tr>
<th scope="row"><label for="f_name">First name:</label></th>
<td>
<input type='text' id='f_name' name='f_name' />
<?php form_error('f_name'); ?>
</td>
</tr>
<!-- ... -->
</tbody>
</table>
Not too sure about the error part; I think it makes more sense putting it next to the input than having a separate column for it.
I have used this in the past fairly effectively:
HTML:
<fieldset>
<p>
<label for="myTextBox">Name</label>
<span class="field"><input type="text" name="myTextBox" id="myTextBox" /></span>
<span class="error">This a message place</span>
</p>
</fieldset>
CSS:
<style type="text/css">
fieldset label, fieldset .field, fieldset .error { display: -moz-inline-box; display: inline-block; zoom: 1; vertical-align: top; }
fieldset p { margin: .5em 0; }
fieldset label { width: 10em; text-align: right; line-height: 1.1; }
fieldset .field { width: 20em; }
</style>
The only really gotcha is Firefox 2 which gracefully degrades. (see the -moz-inline-box which is a bit of hack, but not too bad)
I had this problem too, but with the cocidil that I had a menu in the left (also with float:left in it).
So. My solution was:
html
<div class="new">
<form>
<label class="newlabel">Name</label>
<input type="text" name="myTextBox" id="myTextBox" />
</form>
</div>
css
.new {
display:block;
}
.newlabel {
min-width: 200px;
float: left;
}
I think, it would work in the form class too, but in reality I had more forms in the 'new' class.