I want to do a simple form layout, labels and inputs, without tables. It works fine like this:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
form {
display: table;
}
form>div {
display: table-row;
}
form>div>* {
display: table-cell;
}
</style>
</head>
<body>
<form>
<div>
<label>Hello</label>
<input type="text"/>
</div>
<div>
<label>World</label>
<input type="text"/>
</div>
</form>
</body>
</html>
However, it doesn't work in IE7. What is the cleanest way to make table layouts that display correctly in IE7, IE8, Firefox, Chrome and Safari?
Edit:
I've added a mock up of the layout I want to achieve:
How about absolute positioning?
HTML:
<form>
<h3> LOGIN </h3>
<p> <label> Username: <input type="text"> </label> </p>
<p> <label> Password: <input type="text"> </label> </p>
</form>
CSS:
p { position:relative; }
input { position:absolute; top:0; right:0; }
Live demo: http://jsfiddle.net/GCWWv/1/
Or this CSS:
p { position:relative; }
input { position:absolute; left:100px; }
Live demo: http://jsfiddle.net/GCWWv/9/
Use <table>. Most likely, you've heard it is bad practice to use tables in HTML. It is true that you should avoid using tables for layout. But, if you are actually displaying tabular data, then you should use a table. If you are displaying rows and columns of data, that sounds like a table to me. It would be inappropriate to try and spoof it with css.
A little bit on why. An HTML tag should describe its content, not its appearance. Eg, <p> represents a paragraph, not a block element with top and bottom margins, and not something to use when you need more white space. Some people like this because it feels right. It's clean and tidy and provides a nice separation between content and style. Done well, it can make it easier to re-skin a website.
But more importantly, it makes a HUGE difference for accessibility. Consider screen readers for the blind. When the screen reader encounters a <table>, it expects it to contain data. It allows the user to navigate the table by columns, rows, and headings. Using a table at the wrong time can be very confusing. Using it properly, can make it much easier for the user. Creating a table out of divs and fancy CSS tricks forces the user to navigate each element individually, instead of being able to skip to the row and column that is pertinent. To use your example, if a user was filling out a form, and certain fields were unnecessary, he could easily navigate by <th> to find the fields he needed to fill out.
There are other similar reasons to follow the "tags describe content" convention. Mostly, it is when anything other than a standard browser is consuming your page. Think search engines, feeds, etc. There are
many
lengthy
discussions
about
this
online.
HTML5 takes this concept further with the introduction of some new semantic tags.
I would do something whereby you don't use display: table
I would:
form div {
float: left;
width: 200px /* change this to whatever */
}
If you need help could you please outline what visual layout you're trying to achieve? Good luck.
Related
I am working on a video game UI that is built in HTML/CSS/JS (Angular). This question has specifically to do with the chat component of the UI, which is a chat box with an input field and send button on the same line beneath it.
The simplified markup for the input and submit looks like this (removed all the angular markup):
<div class="chat-controls">
<form class="chat-form">
<input type="text" class="chat-input" />
</form>
<a href class="chat-send btn">Send</a>
</div>
Here's the problem I'm trying to solve: our game is localized for many different languages, meaning that the horizontal size of the Send button varies dramatically from one language to the next depending on the translation. Therefore I cannot predict the Send button width. I would like the text input box to fill the remainder of the space horizontally next to the send button (fixed .chat-controls width - variable .chat-send width = .chat-input width).
The tricky part is I'm trying to do this in pure CSS without using JS. I know I can measure .chat-send with JS and assign the width of .chat-input accordingly (or do something like add a CSS class to an ancestor that denotes the language version and hardcode the values for each language in CSS), but the most flexible and maintainable solution would be pure CSS.
This cannot be achieved with floating the send button right, since the text input will then either flow underneath the send button or I need to know the width of the send button to assign right padding on .chat-input to compensate. If calc() could predict the width of a sibling element this would be trivial, but alas it cannot. I played with flexbox for a while as well and it doesn't seem appropriate for this situation. My current fix is to make the send button the width of the maximum size it can currently be (Russian, which is about twice the length of "Send" in English) but this doesn't look too good.
My question is: is there any reasonable way to do this in pure CSS, or do I just need to do it in JS? Note that browser compatibility is not an issue as this is implemented with Chromium Embedded Framework so just about everything is supported.
you can use display with either flex or table.
<h1>display:flex;</h1>
<div class="chat-controls">
<form class="chat-form">
<input type="text" class="chat-input" />
</form>
<a href class="chat-send btn">Send</a>
</div>
<h1>display:table;</h1>
<div class="chat-controls bis">
<form class="chat-form">
<input type="text" class="chat-input" />
</form>
<a href class="chat-send btn">Send</a>
</div>
with this following CSS to test both version
.chat-controls {
display:flex;
}
.chat-form {
flex:1;
}
.chat-input , .bis .chat-form{
width:100%;
}
.btn {
padding:0 1em;
}
.bis {
display:table;
width:100%;
}
.bis .chat-form, .bis .btn {
display:table-cell;
}
You can play with it online here : http://codepen.io/gc-nomade/pen/MYmVZM
float is also an option if you do not mind to put the send link/button ahead in HTML (third exemple in the demo linked).
This question already has answers here:
Best practice for making web forms
(6 answers)
Closed 9 years ago.
A classical piece of web development mantra is: "Only use tables for tabular data". This has its roots in the elder days, when tables were abused for every possible layout task imaginable.
While I too hold to this rule whenever possible, there are now and then layout tasks which I just cannot solve without a table - or tasks that straddle on the boundary between "tabular data" and "non-tabular data". This is one of them.
The situation is a totally classical one:
Name: […]
Surname: […]
Age: […]
Job: […]
The […] are meant to be textboxes. Is this tabular data? Should I use a table for arranging these labels and textboxes or some unholy mashup of <div>s and <span>s? The table would make it easier to provide the proper vertical alignments and help lining up labels of unknown widths. But would it be "proper", or just another "hack that floats my boat"?
And what if we look at it like this?
Field | Value
---------------
Name: […]
Surname: […]
Age: […]
Job: […]
First of all, thanks for a good question!
This is obviously a form, not a table. The layout of it doesn't really matter, the point of a table is to designate that you are displaying data that lends itself to tabulate (think of it as a composite of simple lists.) Your use case here is to gather input, it doesn't matter whether its layout kind'a sort'a looks like a form.
Of course, none of this matters if you don't really care about semantics; in which case I say use whatever you want. In any event there are plenty of examples and frameworks out there that'll do what you want, but it's not particularly difficult to do by yourself either. And in fact, it can be very much like laying out a table, if you so wish. I'll walk you through it.
(tl;dr)
First, some markup:
<form>
<label><span>Name:</span><input name="name" type="text"></label>
<label><span>Surname:</span><input name="surname" type="text"></label>
<label><span>Age:</span><input name="age" type="text"></label>
<label><span>Job:</span><input name="job" type="text"></label>
</form>
This is not particularly tricky markup. I've not added any classes as you can see, and I'll get to that in a second. But first, I wanted to show you, without any extra markup, how to turn this into a layout like that you requested:
form {
display: table;
}
label {
display: table-row;
}
label > * {
display: table-cell;
}
label > :first-child {
text-align: right;
padding-right: 10px;
}
That's it really. By using css and the table, table-row and table-cell headers for the display values, it's dead simple to create a table like layout without having to sacrifice semantic markup. This css doesn't change the semantics or accessibility of your form, it just provides clues to the browser how it should lay things out. Now, you also asked about adding a header to this. Changing the markup to the following, will unfortunately not really work:
<form>
<div>
<span>Field</span><span>Value</span>
</div>
<label><span>Name:</span><input name="name" type="text"></label>
<label><span>Surname:</span><input name="surname" type="text"></label>
<label><span>Age:</span><input name="age" type="text"></label>
<label><span>Job:</span><input name="job" type="text"></label>
</form>
This is because our styling rules doesn't include any selectors for the div. Now, there are a number of ways this could be fixed, with various different pros and cons. You'll probably run into people that have one thing or another to say about best practices in this area, but honestly it mostly comes down to what works for you. I'd say so long as you keep the markup accessible for humans and robots alike – this does mean trying to stay semantic and make use of microformats, amongst other things – then adding whatever extra cherries on top to get the job done is A-OK!
Anyway, here's one way of doing it, to get your creative juices flowing. First, the markup:
<form>
<div class="form-row">
<span>Field</span><span>Value</span>
</div>
<label class="form-row"><span>Name:</span><input name="name" type="text"></label>
<label class="form-row"><span>Surname:</span><input name="surname" type="text"></label>
<label class="form-row"><span>Age:</span><input name="age" type="text"></label>
<label class="form-row"><span>Job:</span><input name="job" type="text"></label>
</form>
And then the css:
form {
display: table;
}
.form-row {
display: table-row;
}
.form-row > * {
display: table-cell;
}
.form-row > :first-child {
text-align: right;
padding-right: 1em;
}
As you can see all that had to change was that we introduced the class form-row to classify our content such, and replaced the label selectors in the css with .form-row. Now there are plenty of ways to go with this and I hope you take some time to play around with it, because there's plenty to learn (semantics, microformats, css practices etc.)
Hope this helps!
Tabular-data describes a collective form of definite information. A form is not "tabular-data", it is interactive and not even really information for the visitor of the website, rather, it is information that (usually) gets sent, therefore it's fair to consider it incorrect to view changeable forms as "tabular-data." (Then again, it really depends on the usage, but I'm assuming you mean forms as in the practical and semantic purpose).
As far as a practice for styling forms, I usually tend to use divs and ul li combinations, as a form element is in fact a list of information. It even comes with (very limited, but still) some formatting options such as fieldset, legend, etc. I would consider looking into those as well.
Then there's the other side of the force (not necessarily the dark side, just, the alternative side) where semantics, while they matter, shouldn't be turned into a religious discipline. If tables work for forms, then so be it. You cannot apply a single set of semantic rules to every single situation. I've found myself saying this a lot, lately, but I'll say it again, every situation is different.
Well, using table or not depends, but if you are going to design a form, using table element is not the only thing which can design it perfectly, if you want, simply use an ul element with label and see how flawlessly you design the same thing without table or div
Demo
ul {
margin: 50px;
}
ul li {
margin-bottom: 10px;
font-family: Arial;
}
ul li label {
display: inline-block;
width: 100px;
}
Infact you can use float on the li by assigning a fixed width to your ul element, this will result in a two column form, increase the width and make it three, so you don't need table here.
The example you provided does not require a table... And not does resort into an "unholy mashup" of divs.
<div>
<label for="x"></label>
<div class="value">
<input id="x" type="text">
</div>
</div>
<!-- rinse, repeat -->
CSS:
label {
min-width: 8em; /* or whatever makes sense */
display: inline-block;
text-align: right;
}
.value {
display: inline-block;
}
While I too hold to this rule whenever possible, there are now and
then layout tasks which I just cannot solve without a table
Table elements have some pretty cool layout properties, and yes, there are times that those properties are needed. In these cases, CSS has the ability to set elements to display like various table elements, while keeping your code semantically correct as you would not actually using tables elements.
This includes properties such as display: table; display: table-cell;, display: table-row;
In terms of your example.. Tabular data is used to display information to a user.. placing inputs or textareas inside of a table would not be semantically correct. However, if you were to have that same format, with pre-existing data just being displayed, I would say that a table would be acceptable.
That format layout can be made with css fairly easily, using anything from floats, display: inline-block; or the table display properties mentioned above.
So I have a simple page:
www.kensandbox.info/centerthis
This is a simple html/css page and I'm trying to add a paypal button.
The problem is that I can't figure out how to center the button? I've tried adding the following:
<div align="center"> form code here </div>
No dice. I've even tried adding the center tag before the form.
The site code (simple html and css file) can be downloaded here:
www.kensandbox.info/centerthis/centerthis.zip
My guess is that one of the other CSS elements is overriding my change.
What am I missing?
Thanks
there is a float:left in form input, form .btn inside mycss.css
Add float:none to that input if you want to override.
Without looking at your code I would say the best way to center a div is usually make sure it's displayed as a block element (should be by default) and that its width is specified; then finally apply margin: auto.
e.g.
<div class="container">
...
<div class="centered-element"> form code here </div>
...
</div>
where
container {
width: 200px;
}
centered-element {
width: 150px;
margin: auto;
display: block; /* to make sure it isn't being mucked up by your other css */
float: none; /* to make sure it isn't being mucked up by your other css */
}
Edit:
I say to do it this way because, like I now see someone has commented, <div align="center"> is deprecated and so is the <center> tag. To expand, this is because your HTML should only be used to create the structure and semantics of your web page, and CSS should be used for the presentational aspects of it. Keeping the two separate as best as you can will save you a lot of time in the long run.
Also it's best to design your CSS in a way where you shouldn't have to set display: block; on a div (because a div is already a block element) and your shouldn't have to unset a float by using float: none;. For more on a good way to do that, improve your workflow, save yourself some time, and generally be awesome, check into object-oriented CSS a.k.a. ooCSS
I found the answer and I want to thank the two individuals who took the time to answer.
The thing I didn't understand is how to look at a web page and see what CSS code was driving the formatting.
Some research lead me to a Chrome plug in named CSSViewer. Using this plugin and the information from the answer I was able to identify a float left css element that I simply had to change to a float center.
Thanks again for the help.
I looked online for examples of implementation of the form using DIVs and all I see is pretty simple one column forms. I have some pretty complicated forms, here is a picture of one:
http://img835.imageshack.us/img835/8292/formn.jpg
It is easy to make it work with table (which I do), the only problem I have is that sometimes I need to not display some of the choices and move the values up one row to avoid gaps.
I started making some forms using divs, but they fall apart when I change the browser window size and it is not easy to align things.
This topic is helpful:
Is it bad design to use table tags when displaying forms in html?
but it doesn't address some of the concerns I have.
What would you propose as a solution? I can dynamically delete/insert values in the table or try to do the DIVs.
I would go the div route. As long as you're careful of your widths when you apply floats, it's actually pretty straightforward to get the layouts to work properly in different screen resolutions.
Here are a few rules:
Set a max width on your form or your form's wrapper element. If you want to float elements on one row make sure their width's added together does not exceed this width.
If you are adding horizontal padding/margins to your floated elements remember that these add to the total width of the element.
Avoid mixing percentage widths with pixel padding and margins. Apply the percentage width to a parent element and the pixel padding/margins to a child element.
Use clearing elements between your rows of elements to keep everything in line.
As to the markup, you can use the form elements along with CSS to create a semantic structure:
<fieldset>
<legend>Fieldset Title</legend>
<label for="input1">Input 1:</label>
<span><input type="text" id="input1" name="input1"/></span>
<label for="input2">Input 2:</label>
<span><input type="text" id="input2" name="input2"/></span>
<br/>
<label for="input3">Input 3:</label>
<span><input type="text" id="input3" name="input3"/></span>
<label for="input4">Input 4:</label>
<span><input type="text" id="input4" name="input4"/></span>
</fieldset>
And the CSS:
fieldset {
padding: 20px 0;
width: 600px;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
background: black;
color: white;
}
label, span{
float: left;
width: 150px;
}
input {
width: 120px;
}
br {
clear: both;
}
You can see the result here.
If it is a fixed-width table, it's trivial to lay out with divs and floats. Just set each width to exactly what you want.
For a liquid-layout table—and liquid layout is in general highly desirable—it is much harder to arrange a form without table-style-display, because float and position do not readily allow for calculations like “this cell is half the remaining width of the parent, after the fixed-width labels have been allocated”.
So in cases like this, which certainly includes the kind of two-column form you posted, the table-* CSS display values are your only possibility. If you are aiming only at IE8 and the other modern browsers, you can use divs and set display: table-row et al in the stylesheet. However for compatibility with IE6-7 and other older/mobile/niche browsers, you will have to use actual <table>/<tr>/<td> elements, as only the modern browsers support table-CSS independently of the table-elements.
There is no shame in this. A form is kind-of semi-tabular anyway and there is no practical accessibility disadvantage because the page content remains ordered appropriately.
Note: for liquid-layout forms you also have the issue of sizing input fields to match the parent element. input { width: 100%; } almost does it, but not quite, because the width is not including the border or padding that inputs get by default. You can use CSS3 box-sizing and the browser-specific versions of it to get around that for modern browsers, but if you want it to line up exactly to the pixel on IE6-7 too you would have to use padding on the parent elements equal to the border/padding on the child input field.
General information is some kind of list, key > value list to be exact - <dl /> would be probably the best structure for it
Issues values is a table,
Ratings is a table,
Both Redemption and Indicators are lists - unordered lists <ul />
I'm trying to have two or more columns worth of DIVs for input elements in a form. It's a very complex form, and some elements will be hidden and shown depending on some answers.
The problem is I can't get the DIVs to space accordingly in IE6 while having an effective hide/show. This is what mostly works:
.first_column
{
float:left;
clear:both;
}
.second_column
{
float:left;
}
And some HTML...
<div id="question1" class="first_column">
first row, column 1 <input type="text" id="asdf">
</div>
<br style="clear:both;" />
<div id="question2" class="first_column">
second row, column 1 <input type="text" id="asdf2">
</div>
<div id="question3" class="second_column">
second row, column 2 <input type="text" id="asdf3">
</div>
<br style="clear:both;" />
This works as expected. The problem is the show/hide. If I hide #question1, the line break remains. This isn't so bad for this small example, but if there are many questions depending on a show/hide, large gaps start to appear between rows of questions.
How can I achieve this without that line break?
Use margin-bottom on your divs instead of br
I suggest wrapping your complete rows in another div, and give it an id like row_1, row_2. This would include all questions plus the br. Then when you hide the row, the br hides too.
Use this pattern. Better semantics, simple code. Wrap these in DIVS for hide/show.
this.next('.question').toggle() - uses Prototype library. It finds the next element with the given class name and will hide/show that element.
open
<div class='question'>
<label>First Name</label>
<input .... />
<div class="formClear"></div>
</div>
...and this CSS
.label {
width:120px;
float:left;
margin-right:15px
}
.input {
float:left
}
.formClear {
clear:left;
height:15px;
}
For this problem, in my websites I use this:
In the CSS:
.spacer
{clear: both; visibility: hidden;}
In the HTML:
<div class="spacer"></div>
DIV is betther than BR (or HR) for this type of things because it do not move a pixel so you are free to apply margins to other content DIVs in order to have the perfect layout that you want. This work in all browsers, also in IE6.
This will fix also most of the floating problems. I do not find other solutions without this that are cross browser.
Unfortunately IE6 is unwavering in it's resolve to render HTML differently from every other browser. Unfortunately I wasn't able to come up with a simple enough solution with using the br's with clear. Oh well... time to fight with IE6 elsewhere.
Thanks for the suggestions.