Regarding html forms, a very common markup pattern is:
<form ...>
<p>
<label>Name:</label>
<input .../>
</p>
<p>
<label>Birthdate:</label>
<input .../>
</p>
..
<input type=submit/>
</form>
How much markup (classes, etc.) do you typically provide to allow for the most flexible visual formatting of the form? That is, how much markup do you add to help with your css selectors and do you use generic selectors?
<form ...>
<p class='name'>
<label>Name:</label>
<input .../>
</p>
<p class='birthdate'>
<label>Birthdate:</label>
<input .../>
</p>
..
<input type=submit/>
</form>
vs.
<form class='person' ...>
<p class='name string'>
<label>Name:</label>
<input .../>
</p>
<p class='birthdate date'>
<label>Birthdate:</label>
<input .../>
</p>
..
<input type=submit/>
</form>
In the second case, adding generic types ("date") straight from the database can make it more easy to consistently format date fields. Wrapping a grouping ("person") to show the model from which the fields come, can help too. (Or I could have used an internal DIV.) Yet, to increase css reuse, I find myself adding extra markup. In some books I've read I hear that the less markup, the better (and that line can be very gray though it rings true to me). For example, I could very well have used the markup from one of the prior blocks and added a lot more selectors to the css.
What are your principles for deciding just how much markup makes sense? Or how much to put on the css side?
Also, I know that I can select against the name of the input, but since that's a nested element I lose my ability to control formatting from the outer wrapper ("p") which is usually where I want that extra control.
I tend to use definition list tags to style my forms.
<form>
<dl>
<dt><label for="name">Name:</label></dt>
<dd><input name="name" /></dd>
<dt><label for="birthdate">Birthdate:</label></dt>
<dd><input name="birthdate" /></dd>
...
</dl>
</form>
I also use the following CSS:
FORM DT {
clear:both;
width:33%;
float:left;
text-align:right;
}
FORM DD {
float:left;
width:66%;
margin:0 0 0.5em 0.25em;
}
More information here: http://www.clagnut.com/blog/241/
It's a lot of markup, but the effect is consistent and effective.
Another arguably acceptable method of styling forms is to use tables. Just think of the form as "interactive tabular data."
I wouldn't use a <p> tag to group a label and its field, since it's not a paragraph. If you have no other use for <fieldset> you could use one per "row". If you have three inputs for birthday then a fieldset is totally appropriate.
A definition list as Gavin suggested isn't a bad idea but it does seem like unnecessary markup - you can just style the labels and inputs to the right widths and float them.
Adding wrapper classes is also perfectly valid - remember that you don't have to use them in CSS, they add a semantic layer regardless. There may even be a microformat you can use in some cases.
You can also use attribute selectors to style inputs nicely:
input[type="text"], input[type="password"] {
border: 1px solid #ccc;
background: #fff;
}
input[type="submit"], input[type="reset"] {
border: 1px solid #666;
background: #ccc;
}
I do try and keep html markup to a minimum.
HTML forms are the hardest thing to keep html and css to a minimum, as it is very hard to target all the various inputs across all browsers without adding classes to them, such as Textbox to textboxes etc.
If all your forms for that site use simple textboxes and not much of anything else, the minimal mark-up approach works just fine. However controls with complex mark-up such as the telerik RAD controls don't play with simple mark-up and often extra markup and classes are needed.
These small tricks add mark-up, but also make the css much cleaner and will no doubt making styling such elements much easier.
For other general html/css, I tend to use as few classes as possible, such as
.Menu {}
.Menu li {}
.Menu li a {}
This sort of pattern can be re-used a lot for repeated data, and templates can be made and designed with very little html mark-up.
Sometimes its un-avoidable adding classes and whatnot, but I think if your generally thinking about both css and html you should end up with slick markup.
From site to site, I rarely re-use CSS. Its so quick and easy knocking up styles for whatever you wish, re-designing an existing skin to fit a new site is often not worth it IMO.
Mainly with CSS I tend to take the knowledge i've learnt from previous sites and apply it to the new sites, to make coding for all browsers easy :)
After many years, I've arrived at:
<fieldset>
<div>
<label for="Whatever">A text field</label>
<input type="text" id="Whatever" />
</div>
<div class="required">
<label for="RequiredField">A required field</label>
<input type="text" id="RequiredField" />
</div>
<div class="stretch">
<label for="LongField">A long field (stretched across 100% form width)</label>
<input type="text" id="LongField" />
</div>
<div class="cmd">
<button type="submit">Do whatever</button>
</div>
<fieldset>
Additionally, I have two CSS classes that I can apply:
fieldset div {
clear: both;
}
fieldset.block label {
display: block;
font-weight: bold; /* labels above fields */
}
fieldset.aligned label:first-child {
width: 20%;
float: left;
}
fieldset.block .stretch input,
fieldset.block .stretch textarea,
fieldset.block .stretch select {
width: 100%;
}
fieldset.aligned .stretch input,
fieldset.aligned .stretch textarea,
fieldset.aligned .stretch select {
width: 79%; /* leave space for the label */
}
Personally I just do:
<form>
<label for="foo">Foo</label>
<input type="text" id="foo" name="foo" />
<br />
<label for="foo2" class="block">Foo 2</label>
<textarea id="foo2" name="foo2"></textarea>
<br />
Then for css it depends whether or not I want the element to be inline with it or not
form label.block{
display: block;
}
Or you can block + float them like #DisgruntledGoat wrote. (I really hate extra markup)
Related
When I apply ::after for my <p> element, it works fine, but when I use it for the ::placeholder pseudo-element on my input fields, it doesn't work:
p::after {
content: "*";
color: red;
}
#registerFirstName::placeholder::after {
content: "*";
color: red;
}
<!DOCTYPE html>
<html>
<body>
<input id="registerFirstName" tabindex="1" name="registerFirstName" title="" alt="" value="" required="required" maxlength="40" aria-required="true" placeholder="First Name" class="error" aria-invalid="true" type="text">
<p>I live in Ducksburg</p>
</body>
</html>
Output:
Can someone help me fixing this?
:after and :before are not supported in Internet Explorer 7 and under, on any elements.
It's also not meant to be used on replaced elements such as form elements (inputs) and image elements.
In other words it's impossible with pure CSS.
However if using jquery you can use
$(".mystyle").after("add your smiley here");
Psuedo elements do not work on empty elements such as <input>.
There are two problems with your code.
First, the pseudo elements can be set only for elements. Not for other pseudo elements.
Second, as others already mentioned, generated content pseudo elements (::before and ::after) are not supposed to work on empty elements (those that have no content between start and end tags in the markup) and usually they don't (there are some exceptions, but, IIRC, the only browser that allowed these pseudo elements for <input> was Opera with Presto engine).
So to add the asterisk in a cross-browser way, you need an extra element. For example, you can do the following:
/* selecting spans immediately following anything with the "placeholder" attribute */
[placeholder] + span::after{
content:"*";
color: red;
}
<input id="registerFirstName" tabindex="1" name="registerFirstName" title="" alt="" value="" required="required" maxlength="40" aria-required="true" placeholder="First Name" class="error" aria-invalid="true" type="text">
<span></span>
UPD: Sorry, I missed the part that the asterisk should be next to the placeholder text at first. Unfortunately, it's impossible with CSS. But you can use the floating label pattern instead of the placeholder, which makes it possible to add the asterisk in the needed place with ::after pseudo element, and also improves the accessibility of the form in comparison to the bare placeholder solution.
Pretty sure its a dumb question but after a long search i didnt find anything.
While browsing the League of Legends page i noticed something i would like to replicate on my own page.
link:http://na.leagueoflegends.com/en/page/champion-reveal-illaoi-kraken-priestess
In the middle of the page there is a video and text beneath, it also shows 5 buttons everyone of them represents another video and a text. If you press one of the buttons the text and video changes smoothly but it doesn't load a new page or anything. How is this achieved iam not getting it out of the source code. I hope somebody can help. Is this achievable without Javascript?
Does somebody know a tutorial which deals with that?
Thanks for help.
Edit: Maybe if this question is inapproriate for this forum is there some kind of webdesign forum for stupid beginner questions?
There are a variety of ways.
The link you provided does so with Javascript.
While Javascript likely provides the most robust method / functionality - and since you asked if there is a pure CSS way, I wanted to share with you this pure CSS / HTML way. Here is an example: Fiddle Example
HTML:
<div>
<label for="content1">First Button Text Here</label>
<input id="content1" type="radio" name="content">
<div>
This is my content.
</div>
</div>
<div>
<label for="content2">Second Button Text Here</label>
<input id="content2" type="radio" name="content">
<div>
This is my alternate content.
</div>
</div>
<div>
<label for="content3">Third Button Text Here</label>
<input id="content3" type="radio" name="content">
<div>
This is my third set of content.
</div>
</label>
</div>
CSS:
label {
display: inline-block;
color: white;
background: #009;
padding: 5px 10px;
border: 1px solid black;
margin: 10px 0 0 0;
}
input {
display: none;
}
input + div {
display: none;
border: 1px solid blue;
padding: 20px;
}
input:checked + div {
display: block;
}
IMPORTANT THINGS to watch for
This markup will not work unless the following items are in place:
1. The labels for the radio button has a for attribute that matches exactly the id attribute of the radio buttons. The label does not have to be next to the button, but could be separate as needed to get the layout desired.
2. The div that contains the content must be immediately after the input. There cannot be any elements between them.
And, as a side-note, the div that contains the content can, if you like, contain a variety of rich markup to display sophisticated html such as images, tables, video embeds, etc.
IT would be nice if you could provide a link as an example (or at least images). But what you are describing can be achieved pretty simply by using jQuery and it's .show() and .hide() functions. Doing so, you can just create DOM elements you want (e.g. divs, videos, images, ...) and hide or show themn through jQuery.
Here a little example (to be honest, it's not the most fanciest one, but it works).
https://jsfiddle.net/fuzkoewj/
So Two Divs Walk Into A Form
Looks like this:
<form>
<div id="top">
<label>Gimme a Number:<input type="number" /></label><br />
<label>Gimme a Word:<input type="textarea" /></label><br />
<label>Now tell me how you feel about HTML forms: <textarea rows="4" cols="50"></textarea></label><br />
</div>
<div id="bottom">
<label>Gimme a Number:<input type="number" /></label><br />
<label>Gimme a Word:<input type="textarea" /></label><br />
<label>Now tell me how you feel about HTML forms: <textarea rows="4" cols="50"></textarea></label><br />
</div>
</form>
There's some css positioning all the form fields absolute and left, a fiddle of the principal is here (Step 1)
So I fixed the first problem by adding additional line breaks (fiddle of step 2).
This is not an ideal solution for two reasons. Extra elements in the DOM for one, and um... well just look at it. The textarea still overflows into the bottom div.
I found a temporary hack when the miscellaneous clearfix answers I tried didn't work (Mostly from other SO questions) by inserting:
<hr class="clearfix" /><br />
in between the two, and giving the hr visibility:hidden in the CSS.
That made it work on my page, but as you can see here (Step 3) it doesn't actually work. In the form on my page the div's have transparent backgrounds, and it puts them far enough apart that the users are happy, and since this is an intranet order form (used from a phone no less) and not a SV startup webapp, I'm kind of content to leave it production for now, but in the end, what was the right way to do this?
How should I have gotten the div.top to encompass the full content, including the textarea? I've tried a lot of the "go to" solutions for elements with float, but as expected, they don't work since the textarea's aren't floated.
Ideally I want to ditch the extra <br>s, and have the <div>s actually contain their content without either manually positioning every single element or adding a ton of complexity to the page. Any ideas are appreciated.
A nice trick for what you're looking for is using a Html Description List.
For example, you can write this:
<dl id="top">
<dt>Gimme a Number:</dt>
<dd><input type="number" /></dd>
<dt>Gimme a Word:</dt>
<dd><input type="textarea" /></dd>
<dt>Now tell me how you feel about HTML forms:</dt>
<dd><textarea rows="4" cols="50"></textarea></dd>
</dl>
<dl id="bottom">
<dt>Gimme a Number:</dt>
<dd><input type="number" /></dd>
<dt>Gimme a Word:</dt>
<dd><input type="textarea" /></dd>
<dt>Now tell me how you feel about HTML forms:</dt>
<dd><textarea rows="4" cols="50"></textarea></dd>
</dl>
jsfiddle
And here is a bit more css to make it look like your fiddle:
#top{
color:white;
font-weight:700;
background-color:blue;
}
#bottom{
font-weight:700;
background-color:red;
}
dl {
padding: 0.5em;
height: 100%;
display: table;
}
dt {
float: left;
clear: left;
}
dd {
float: right;
clear: right;
}
fiddle
Edit
About label issue being non-superfluous - there is an easy solution using the "for" attribute. Here is an example:
<dt><label for="number1">Gimme a Number:</label></dt>
<dd><input id="number1" type="number" /></dd>
updated fiddle
Your original use of label:
<label>Gimme a Number:<input type="number" /></label><br />
will couple the two tags together and shouldn't be used. Plus talking about semantics, should the input really be part of the label?
Taking in acount your comment about non-semantic use of dd / dt, you can easily swap between the dt and dd, like this fiddle. Here is the updated example:
<dd><label for="number1">Gimme a Number:</label></dd>
<dt><input id="number1" type="number" /></dt>
Now we have a semantic HTML where the CSS takes care of the design choices.
Edit 2
new fiddle - no need in height: 100%; on dl
The situation:
I have a site with a long list of questions across multiple pages.
Each question is within a made up of a label and an input. Groups of question divs are within an additional div to provide grouping and bordering styles, etc.
The problem:
I want to number my questions, but want to avoid hard coding the numbering. However, it is invalid html to place the <li> inside the divs or labels.
In addition some question divs are conditionally hidden and revealed depending on user input. The divs therefore provide key functionality, and the number must be hidden and revealed along with these divs, (so positioning each <li> outside a divs would be problematic.
Code:
Here is an example of a pared down structure of my form, showing two question "blocks":
<form id="myform" method="post" action="/destinaion/page.php">
<div class="formfield">
<div class="page1">
<div class="lowerborder">
<div class="question">
<label for="q2">Question 1</label>
<input type="number" id="q1" name="q1"/>
</div>
<div class="question">
<label for="q1">Question 2</label>
<input type="number" id="q2" name="q2"/>
</div>
</div>
</div>
</div>
</form>
The div class form field contains the form page, and page1 various styling particulars for page 1.
I'd like to make an ordered list from my questions, perhaps something like
Attempt at achieving goal:
<form id="myform" method="post" action="/destination/page.php">
<div class="formfield">
<ol>
<div class="page1">
<div class="lowerborder">
<div class="question">
<label for="q2"><li>Question 1</li></label>
<input type="number" id="q1" name="q1"/>
</div>
<div class="question">
<label for="q1"><li>Question 2</li></label>
<input type="number" id="q2" name="q2"/>
</div>
</div>
</div>
</ol>
</div>
</form>
But as you can see I am putting the <li> inside the <label> which a) is not valid html, and b) doesn't play well with all browsers.
How can I avoid putting <li> elements inside invalid parents, when my list items are separated by many nested divs?
jsFiddle:
See a fiddle of my above attempt. Including some styling and functionality I am trying to achieve (styling via nested divs, hidden questions that reveal etc)
Please see this fiddle demonstrating how to do everything you want without interposing any other elements. I found no need for even a single div anywhere.
Note: I initially used float:left for the question to make the answers line up properly. However, this caused IE to render the numbers just left of the answers instead of left of the questions. I switched to using display:inline-block and now everything works in IE as well.
Comments:
I cleaned up the style sheet, which had some sections repeated and conflicting style rules. I removed unnecessary rules.
I created the lines separating groups of questions using a class, and I also made it apply to the top border of a question rather than the bottom, so that you can use it even if there are hidden questions ending a group, since a hidden question would probably never begin a group. There was no need for additional elements to have borders.
In my opinion the label for the "Reveal" checkbox should be the text next to it, so that you can click that text to check and uncheck the box. Thus, I added a "question" class to the items that are the question, rather than using a label. You must apply the style "question" to the questions to make them style properly. You can apply that to a label element (which is for something else or not), or you can use a span or other element to contain the text when it is not a label.
IE 7 stupidly puts the numbers at the bottom of the line, even though the questions are styled with vertical-align:top. I don't know how to fix that at this time, but it could be another question to those more expert than I in CSS quirks.
IE was not handling the "hidden" method very well, taking up extra space and then when revealing not showing the child elements, so I used absolute positioning instead (which, by taking it out of the document flow, has the same effect). See the CSS for how it works.
I modified the way you were applying the reveal script. Instead of manually wiring up each individual item, instead I put a data value on the checkbox itself, then at the ready event I use that to wire up the page appropriately. Now you can have checkboxes that reveal more questions just by adding an id to the revealed question (or use class instead if you need to reveal more than one at a time) and a data expando attribute like data-togglehidden="l4" to specify the id to toggle right in the checkbox element. No script changes required.
It looks a little like you may have "div-itis" which is the tendency to multiply divs all over the place. No need to be embarrassed, I have had div-itis too, when I was new to html development. You'll grow out of it due to experiences like this. In general, you should use normal non-div page elements and style them directly, rather than wrap things in divs and styling those. Divs are useful when you need to style a group of related functionality or provide a box for different elements. One hint that you may be using divs improperly is when they only have a single item in them (especially another div). Sometimes that is necessary, but ask yourself: can I move the style to the parent or child element instead?
I need to know more about how the "pages" work that you mentioned and that were in your original html markup. There are no pages in html, only when html is printed. So I'm not quite sure what that means or how to style your pages for you.
Here is the cleaned-up html, without the need of additional elements between ol and li:
<form id="myform" method="post" action="/destination/page.php">
<ol class="formfield">
<li>
<label class="question" for="q1">What is your first name?</label>
<input type="text" id="q1" name="q1"/>
</li>
<li>
<label class="question" for="q2">A very long question 2 that is sure to run to a second line just to prove that such a thing will work properly and not mess up the layout, described in your own words?</label>
<input type="text" id="q2" name="q2"/>
</li>
<li class="begingroup">
<span class="question">Are you the type of person who likes to needlessly answer extra questions?</span>
<input type="checkbox" id="q3" name="q3" data-togglehidden="l4"/>
<label for="q3">Yes, yes, that's me!!!</label>
</li>
<li id="l4" class="hidden">
<label class="question" for="q4">Why do you like to do extra needless work?</label>
<input type="text" id="q4" name="q4"/>
</li>
<li class="begingroup">
<label class="question" for="q5">What was your first pet's name?</label>
<input type="text" id="q5" name="q5"/>
</li>
</ol>
</form>
Here's what it looks like in Firefox 16.0.2:
And in IE 7.0.5730.13CO:
The CSS:
ol.formfield {
width: 500px;
margin: 10px auto;
padding: 16px 16px 16px 0;
border: 5px groove #005E9B;
list-style: decimal outside;
color: black;
background-color: #6Fc2F7;
font-family: 'Oxygen', sans-serif;
font-size:15px;
}
ol.formfield li {
clear: both;
padding: 2px;
margin-left: 1.7em;
}
ol.formfield li.begingroup {
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid #005E9B;
}
.question {
display:inline-block;
width:300px;
vertical-align:top;
}
.hidden {
position: absolute;
height: 0;
width: 0;
overflow: hidden;
}
ol.formfield input {
border-radius:5px; /* css 3 */
-moz-border-radius:5px; /* mozilla */
-webkit-border-radius:5px; /* webkit */
}
And the script to wire up your hide/reveal based on data values on elements:
$('ol.formfield input:checkbox')
.each(function() {
var d = $(this).data('togglehidden');
if(d) {
$(this).on('change', function() {
if ($(this).attr('checked')) {
$('#' + d)
.removeClass('hidden')
.find(':input')
.focus();
} else {
$('#' + d).addClass('hidden');
}
});
}
});
I'm wondering what are the best solutions to structure a html form with labels and inputs.
I used to do this with float: left to the label and float: right for the inputs. And each line is surround with a block clear: both.
But i don't think these CSS property were made for something like that..
So what are the others solutions ? Tables ?
Well it really depends on what you want the form to look like. For example, if you want a clear grid with borders I recommend using a table.
To duplicate what you have, you can do this:
<label for='textbox'>Label</label><input type='text' id='textbox' />
And then this css:
label { display: inline-block; width: 100px; }
This will make the label stay on the same line as in input element but will push it the appropriate distance.
Personally, I try to avoid using floats to align elements. I would rather use position absolute and set left or right and top or bottom. To me floating is like asking the browser to do it for you, and maybe some browsers (cough ie cough) will decide to draw it a little differently.
Form markup and CSS will always be a personal choice. Sure, there are some rights and wrongs semantically and technically from a CSS point of view, but there certainly isn't one (or even a few) "right" techniques.
My personal preference is to float the label left and contain my inputs inside lists, which I personally consider more semantic than a div or p tag.
HTML:
<form>
<fieldset>
<ol>
<li>
<label for="input1">Label 1</label>
<input type="text" name="input1" id="input1">
</li>
<li>
<label for="input2">Label 2</label>
<input type="text" name="input2" id="input2">
</li>
<li>
<label for="input3">Label 3</label>
<input type="text" name="input3" id="input3">
</li>
</ol>
<button type="submit">Submit</button>
</fieldset>
</form>
CSS:
li {
clear: left;
margin-bottom: 10px;
}
label {
float: left; /* You could use "display: inline-block;" instead. */
margin-right: 10px;
width: 80px;
}
tables is also a solution.
also , Div with 2 inner divs( left and right)
or 1 div with both elements with float:left with margin-left.