I'm experimenting with ways to create a two-tiered multi-column form that looks balanced. My latest attempt involves enveloping each label/input in an li and having them float into place. The attempt is somewhat successful, but there is a dimension issue that I can't resolve.
The form is 600px wide and I made the lis 280px which would put the two columns roughly centered in the form. However, the effect is lopsided; everything is way too much to the left. It's like there is a huge margin of about 150px on the right hand side of the form - only there isn't.
In analyzing it, I noticed that the inputs are actually measuring at 175px. However, if I try to increase the width, it goes to a new line, so they are acting like they are 280px. But you will notice in the jsfiddle, the last li is extending to the full width - 600px. Therefore, it can't be a result of any fieldset formatting. Furthermore, if I change the float to 'right', the 150px fake-margin is still there. Firebug detects all margins and padding as normal.
I just don't get it.
I've tried renaming, applying additional classes, changing order of the li, removing attributes and adding other ones, and changing styling protocols... but usually I just make things worse. I would give up on the ol li concept altogether if any of my other techniques came as close to providing the display I am looking for.
What's causing that 150px right margin? And how do I get rid of it?
I need to understand this as the second part of the form is supposed to have two and three columns. So if lis cannot provide consistent widths, I have to try something else.
Here is the link: jsfiddle
[http://jsfiddle.net/9344a/]
Thank you in advance. (I've tried to clean it up, but the CSS/HTML may be a little bit messy as a result of trying different combinations. Let me know if anything is still difficult to understand.)
You can give
fieldset.partOne
{
text-align: center;
}
The problem was actually a compounding of errors.
First, the input size was incorrectly targeted through li when it should have been targeted directly.
Example: fieldset.partOne ol li { width:280px; padding:5px 0 } WRONG! fieldset.partOne ol li input { width:280px; padding:5px 0 } or simply fieldset.partOne input { width:280px; padding:5px 0 }
In addition, setting the width of the ol li to 100% (a misguided attempt to increase the size of the input) would obviously prevent the float.
The margin issue is caused by fieldset.partOne ol li { width:280px; padding:5px 0 }. Removing this width eliminates the fake margin. Not quite certain why, but the lesson is ol li works slightly differently within forms, so be aware of that.
My concept for this form was fairly odd, and I made several errors with both my HTML and CSS in trying to achieve the end result. So I went back to the beginning and rebuilt from scratch and was able to create a non-standard multi-column form that met my odd criteria, used only CSS, and worked across most browsers.
The Stackoverflow posts were invaluable in addressing all the little quirks that I came across, so I thought I'd return the favour and provide a jsfiddle that may help other newbies identify what they want and possibly how to get there.
I would have found something like this enormously helpful.
Issues addressed:
Aligning two and three column forms with various sized input elements.
{ol li} or {div}? {li} Not a good solution for non-standard formats. I had to use {li} for one section and {div} for another section to make the form work.
{select} sizing inconsistent. It usually has to be larger than your {input}
Keeping smaller {inputs} from floating into gaps.
Aligning odd shaped {input} and {label} fields.
Font sizes and styles reverting to browser default (reset not applying to HTML5?)
A non-resolved issue is FF top-aligning {select} data. There are many posts regarding this issue, but I have not found a good solution as of yet (one that targets only FF and does not affect other browsers). This is not a priority for me, but if it is for you, lots of advice is available. Do a search.
Here is link that displays the form and shows the code: http://jsfiddle.net/LAVJn/1/
Remember that this is written by a newbie, and you will certainly find many ways to improve upon it. But it does work and may be a good place to start or at least refine any questions you may have.
I don't think I am breaking any protocols doing this, but please let me know if that is not the case.
Related
...Screenshot of my abomination
jsFiddle: http://jsfiddle.net/ELZD8/
It was looking fine, until I needed to change the fieldset size: and since I was using position:relative for literally every element on the page, changing the fieldset screwed everything up, bad. Forgive me but I'm pretty new to CSS and I know I'm using wayyy too much code.
So, as you can see in the imgur, it looks like hell now. What's the quickest way to fix this? I know it probably has to do with floats and margin:left and margin: right, but could someone provide some insight before I go bananas?
Any input is appreciated, cheers.
Easy fix:
You need to use proper div sectioning, that is, make each section a div and then place elements inside each div, otherwise it becomes a clusterfuck. You also need to list your elements in your css file by order of appearance in the html, otherwise it's painful to look for things...
Don't use massive amounts of <br>, use padding and margin css rules instead
Yes, you may use position:relative, but since you asked for advice, I am strongly against it, it takes longer to build, longer to update, longer to fix, etc. Use sections, floats and keep it simple, Simple is your friend.
I also suggest strongly against using fieldset, use <form> instead, its a major html/css breaker imo.
Here's a chopped up example after cleaning/tweaking the code considerably. There's still a thousand ways left to clean and refine it but at least now it looks more like what I suppose you wanted:
http://sotkra.com/stackoverflow/positionrelative/index.html
[edit]
Please note that this is not a duplicate thread, though it revolves around the same topic as a previous one.
[/edit]
Only a day or two ago I created a similar thread, and got some much needed answers, but as the thread didn't have much focus, I do hope you'll forgive this rewrite, so to speak.
So basically I've done this before though, as I found out, there was a few questionable approaches, which I should have fixed now. Among other things I don't use display: table-cell any more, but instead display: inline-block.
So what's the problem then? well, I want to achieve some degree of perfection and as I'm easily confused, I'd very much like some of you to look it over and pass along your comments and suggestions. Maybe take a few minutes to do me the favour of tidying up the CSS, etc.
Now I have no expectations and I realise that I'm not the only person in need, but if you have the time, I'll be very grateful.
Here's a link to a working example. http://jsfiddle.net/7fD4S/
The html should be fine, though it annoys me quite a bit that I can't present the list probably, due to the way it affects the inline-block property, but I can live with that.
Regarding the CSS, as explained, I easily confuse my self. I think the CSS need some tidying up, but honestly I can't manage it.
All in all I guess I just want approval. that it's done correctly, that there are no major issues and such.
It should be noted that this is only supposed to work with IE9 and other newer browsers. All in good time, support for IE8 may be included, but that has yet to be decided.
Well, that's all.
Hoping that you'll spend a few minutes looking it over, thanks in advance and best regards.
Edit:
Updated example: http://jsfiddle.net/7fD4S/1/
Edit:
Updated example: http://jsfiddle.net/7fD4S/2/
Changed position top from 21 to 20px to avoid gap.
Only thing I really noticed was that you should change:
header div {
top: 21px;
}
To
header div {
top: 20px;
}
Otherwise there is a dead zone # the 1px border that doesn't seem to trigger the :hover effect, and thus makes it choppy.
Thanks to Jonathan Amend, the css is now fixed in iebug.html below.
It's hard to really explain this problem without looking at it in IE6 or IE7, but anyway if you have a look at the following pages on IE6 & 7 you'll see next to "send me a brochure" and "I would like more information on (tick one or more boxes)" the checkboxes and their labels have been mysteriously pushed or pulled down for some reason:
http://sonic.huntinternet.com/iebug.html
I've tried altering the margins and padding on all my elements to 0 yet this has no effect on IE6&7 - meaning I think it's a bug of some kind.. however I don't really have enough experience to know what bug to even look for so any kind of pointer would be nice.
FYI I've used a guide off the sitepoint website that suggested using nested lists, but really that shouldn't make any difference. Both the xhtml and css are valid according to w3c's validator.
Thanks for your help!
John.
Add *display: inline-block; to your .enquiry-form ol li. This is a common bug with how IE 6/7 clears list items (block elements by default) onto new lines.
For this, it's being pulled down because your floated label is two lines long in copy, so the OL is aligning it's top position to the top of the second line.
A solution that comes to mind here is to make the OL floated left as well. This will, of course, require that each LI has the clearfix styles on it (styles for clearfix can be found here: http://net.tutsplus.com/tutorials/html-css-techniques/css-fudamentals-containing-children/).
I'm making more of an effort to separate my html structure from presentation, but sometimes when I look at the complexity of the hacks or workarounds to make things work cross-browser, I'm amazed at huge collective waste of productive hours that are put into this.
As I understand it, floats were never created for creating layouts, but because many layouts need a footer, that's how they're often being used. To clear the floats, you can add an empty div that clears both sides (div class="clear"). That is simple and works cross browser, but it adds "non-semantic" html rather than solving the presentation problem within the CSS.
I realize this, but after looking at all of the solutions with their benefits and drawbacks, it seems to make more sense to go with the empty div (predictable behavior across browsers), rather than create separate stylesheets, including various css hacks and workarounds, etc. which would also need to change as CSS evolves.
Is it o.k. to do this as long as you do understand what you're doing and why you're doing it? Or is it better to find the CSS workarounds, hacks and separate structure from presentation at all costs, even when the CSS presentation tools provided are not evolved to the point where they can handle such basic layout issues?
Clearfix is unnecessary most of the time, and the popular version of hack is needlessly verbose and complicated.
You can get clearing effect by applying overflow:hidden to the container. If container doesn't have fixed height, it will stretch to size of content anyway. It's not a hack, but specified behavior that works in all browsers.
And when you really need overflow:visible you can still clear without extra element in the markup:
.container::after {
content:""; /* not "."! */
display:block;
clear:both;
}
and that's perfectly standard CSS 2.1. In IE versions that don't support CSS 2.1, hasLayout happens to have desired effect:
.container {
zoom:1;
}
Yours is the right approach. Rules are created for those who do not understand them. If you know all pros and contras, make your own call.
You are particularly justified in this case. CSS decided to ignore common wish to separate content A from content B horizontally, so you have to choose a hack you dislike least. I compare the three solutions already presented here.
Your solution is bad because it changed content of the document, inserting element C whose only purpose is visual separation between A and B. Content should not serve layout purpose.
Karpie’s solution is slightly worse (in my book) because it does the same in a sly way. Pseudo element ":after" was not designed for that. It has a great advantage, however, of never actually changing the HTML.
PorneL’s solution achieves desired separation between A and B by radical change of properties of A. The change will not only separate A from B, but also separate A from preceding content, change the way width of A is calculated and so on. Of course, sometimes it’s perfectly OK, but you have to be aware of those unexpected side effects.
The choice is ours.
I definitely don't agree with the idea of using extra markup just to clear divs.
I favour the 'group' approach - putting class="group" on the parent div, with the following CSS:
/* Clear groups of floats by putting class="group" on their parent */
.group:after
{
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
And in an IE-specific stylesheet for IE6/7:
/* IE7 */
.group
{
min-height: 1px;
}
/* IE6 */
* html .group
{
height: 1%;
}
This was detailed in CSS Mastery, by Andy Budd. It stretches semantics a little bit, but it makes sense - you're grouping together floated divs, which obviously have some relation to each other.
edit: I wouldn't consider this a huge hack or workaround either - the method has been around for years in various incarnations, (usually known as the 'clearfix' method), and I don't see it going away anytime soon.
I stumbled upon this article
http://www.thefloatingfrog.co.uk/css/my-hatred-of-br-clearall/
When would one need to use that ?
Why is it evil ?
I don't understand the substitute syntax can you explain ?
Setting clear to both with not allow other elements to float on either the left or right side of the element. The class below is an easy way to add this anywhere.
.clear {
clear:both;
}
So when you want to clear something (that is, if you were to float the next element to the left, it would be below the current element and to the left, instead of left of it) you'd simply add the .clear class.
The problem with the following code is that if later on you decide that you don't want to clear everything after the 'something' class, then you have to go through your HTML and remove the br clear="all" wherever you have that 'something' class.
<div class="something">Cool content.</div>
<br clear="all">
<div class="other">Cool content again.</div>
Instead you could do something like this:
.something {
float: left;
}
.other {
clear :both;
float: left;
}
<div class="something">Hi!</div>
<div class="other">Hi again from below!</div>
That way if later on you decide to float all blocks with the 'other' class then you can just remove the 'clear:both;' from the CSS once.
I was about to post something snarky about you not reading the article, but when I saw that it was just a page of vitriolic rage with no explanation, I figured I'd answer.
It's because there are better ways of doing what you want to do -- namely, by using CSS in the way he does in the article, he has separated the semantics of the elements he's displaying from how he's displaying them. Why is this a big deal? Well, for one, he can more easily transform how his page looks when it's shown on different platforms (mobile, desktop) and media (screen, print, a screen reader for the blind), simply by editing CSS and not having to touch the document itself. This feature of CSS is pure gold.
On the other hand, if you use a construct such as this, you put in a hard constraint about your document's presentation that sticks around no matter what media or platform you're dealing with. What makes him so mad? Because once a developer has come in before him and used <br clear="all">, he has to take it out in order to get the benefits I just mentioned. That's why it's so frustrating. One bad developer can disable a whole host of development scenarios for every other developer who comes after.
As far as CSS goes, I have to say that it's a very difficult subject to just pick up without reading all about how it works. It's hard to explain how the clear attribute works if you don't understand floats. I had quite a hard time myself until I bought a great book on the subject.
When you have floated elements, the parent element can't calculate it's dimensions effectively and sizes incorrectly. Other items that follow floated items may also sit out of position. By clearing an element at the end of your floats, you correct alter this behaviour.
EDIT
Actually correct is probably the wrong word to use as this is what is supposed to happen and using the word correct suggests it is broken.
The author is just going off on a crazy rant about how the same thing can be accomplished using CSS on the DIV elements themselves. He's saying that br class="clear" is unnecessary.
It's also not a good practice because it mixes content with presentation. If a web designer wanted to re-theme the web application, he or she would need to modify the HTML to pull out all of the br clear elements, whereas if this was done as the author suggested, then the CSS files could be swapped out independently of the HTML, making their jobs easier and giving them one less thing to rant and rave about.
The rant is of course justified, as these simple, silly lines of code can actually cause a lot of headaches.
The idea is that your markup describes the information, and the CSS formats that information.
A dummy tag to clear floats isnt semantic, as it's only purpose is for layout reasons. There are other semantic ways of clearing floats that keep this separation. As commented below but here for clarity this is a good resource for semantically clearing floats http://css-tricks.com/the-how-and-why-of-clearing-floats/