Using `box-sizing: border-box` with `inline-block` elements - css

I'd like to use the box-sizing: border-box CSS property to split a form into a left and right half:
<form class=container>
<fieldset class=left>
<label>Description</label>
<textarea name=description></textarea>
</fieldset>
<fieldset class=right>
<label>Name</label>
<input type=text name=name />
</fieldset>
</form>
In order to make this work, I need to float both <fieldset> elements to the left:
.left, .right {
width: 50%;
margin-left: 0px;
marign-right: 0px;
box-sizing: border-box;
float: left;
}
The problem is of course that since the <fieldset>'s are floated, they are no longer in-flow, and the <form> element gets a height of 0 (unless i add a clearfix or something). If I remove the float property and change their display to inline-block, they're back in flow, but they no longer line-up next to eachother.
Is there some way to use border-box here without needing to add a clearfix element (or :after pseudo element)?
For reference, here's a fiddle that uses floats, and here's a fiddle that uses inline-block.

That's quite a common problem.
Adding an overflow value on the container, will have the browser to recalculate the container's dimensions despite it have no not-floated elements.
.container { overflow: hidden; }
Before and After

Related

CSS container height zero... why not height of contents?

I am not seeing any vertical space (specified by the 50px margin in lineitem) between lineitem elements. However, if I add something like height:40px; to lineitem's css format, then both the height and the margin are respected. Why doesn't lineitem just derive the heights of the input and label elements and add the margin to whatever that is?
<div id="checkoutform">
<div class="lineitem">
<input type="text" name="EMAIL">
<label for="EMAIL">Your E-Mail:</label>
</div>
<div class="lineitem">
<input type="text" name="NAME">
<label for="NAME">Your Name:</label>
</div>
</div><!-- #checkoutform -->
And the CSS:
#checkoutform .lineitem {
margin:0px 15px 50px 0px;
clear:both;
}
#checkoutform label {
float: right;
text-align:right;
font-family:"Open Sans";
font-weight:normal;
font-size:14px;
}
#checkoutform input {
width:280px;
float:right;
font-family:"Open Sans";
font-weight:normal;
font-size:14px;
}
It could have to do with the line-height of your element's content (if you've set that elsewhere). All elements in the DOM and "essentially" rendered as text. If you don't have a height set for the element, it assumes the line-height for the calculated height, not necessarily the height of the content. You could essentially "force" the .lineitem height be adding a clearfix element, or adding a clear:both;to one of it's children elements.
I suggest looking in this direction as it seems that floating the element as a means to do layout is not the accepted practice.
Very simple:
You need to clear the floats inside .lineitem.
Add this to your css, this clears the floats with a pseudo element without any need to modify your HTML.
#checkoutform .lineitem:after {
display: table;
clear: both;
content: "";
}
Demo: https://jsfiddle.net/jrkph1ra/
The reason this works:
Floated elements get out of the normal flow of height calculation of their containers.
An element that follows the floated elements with clear:both; will mean that no floating elements are allowed on the left or the right side of that element, it moves the margin edge of the element below the margin edge of all relevant floats, forcing the browser to take into account the height of the floated elements into the height calculation.
This element can be a pseudo element of the parent of the floated elements so no HTML modification is needed.
"Clearing the floats" is a common practice and well-tested.
If you use it frequently you can create a class like clearfix and add that class to all relevant elements.
.clearfix:after {
display: table;
clear: both;
content: "";
}
Then add .clearfix to all relevant elements with floated children.
Demo https://jsfiddle.net/jrkph1ra/1/
display: table; vs display:block;
Both display: table; and display:block; will generate block level elements, the major difference is that table will only expand to the width of its content, in this case a width of 0 but block will extend to the width of its container, so using table minimizes the footprint of this method.
Add "float: left" to .line-item
https://jsfiddle.net/q6ytv3tt/1/
#checkoutform .lineitem {
margin:0px 15px 50px 0px;
clear:both;
float:left;
}

How can I expand this <input> tag?

This is a simplified version of my question earlier today since I didn't get a satisfactory reply.
I have a HTML and CSS code as in this Fiddle: http://jsfiddle.net/wNGHz/
How can I make the <input> resize automatically when its parent frame is resized?
Notes:
I prefer to use only CSS rather than JavaScript.
The <input> should have 100px distance from left and right edges of the parent.
#thirtydot semantically I want to have a simpler HTML. I can wrap
<input> with <div> but it's just weird to add one more element for the
sole purpose of styling another one. I was wondering if anyone has a
better solution.
Unfortunately, there is no better way. It has to do with the fact that input is a replaced element, which means it behaves differently to non-replaced elements such as div.
One difference is that position: absolute; left: 0; right: 0 won't work in the same way on an input as it does on div (except in WebKit).
The best workaround is to wrap the input in a div:
http://jsfiddle.net/thirtydot/wNGHz/6/
<div class="inputContainer">
<input type="text" value="test" />
</div>
.inputContainer {
position: absolute;
left: 50px;
right: 50px;
}
input {
width: 100%;
background-color: red;
color: white;
border: none;
}
When you have input { width: 100%; }, it's usually a good idea to also add box-sizing: border-box, to make any padding and border on the input be counted inside the width: 100%: http://jsfiddle.net/thirtydot/wNGHz/7/
The only pure CSS way I know of is by adding a width in %: http://jsfiddle.net/PeeHaa/wNGHz/1/
You can do this better way.
<div class="inputContainer">
<input type="text" value="test" />
</div>
input {
width: 100%;
margin:0 100px;
}

Relatively aligning element in a div with fix width and height

My markup looks like this:
<div id="content">
<img src="some_content.jpg">
<form action="...">
<input type="text" ... >
<input type="submit" ...>
</form>
<div id="forgotyourpassword">
Forgot your password?
</div>
</div>
The mark up for the form is generated by a CMS, so I cannot change it.
The content div has a fixed width and height so that I can center it vertically and horizontally in the page. Currently all children within content is set to display: inline-block and then aligned horizontally and vertically within the content div.
I have aligned the forgot your password link like this:
And here is the css for the link in question:
#forgot-password{
float: right;
margin: 0; /* reset some stuff inherited from parent */
padding: 0; /* reset some stuff inherited from parent */
margin-right: 171px;
margin-top: -20px;
}
Here are some relevant css:
#content{
position:absolute;
width: 650px;
left:50%;
top:50%;
height:242px;
margin-top:-126px;
margin-left: -325px;
text-align: center;
}
#content > *{
vertical-align: middle;
display: inline-block;
zoom:1;
*display:inline;
margin-left: 20px;
margin-right: 20px;
}
That all works well. However, in some cases, for example, if an error has occurred with the form submission, then an error message will be appended to the from in the <form> element by the backend.
In such a case, I want the link to be aligned like so:
The problem with my css as it stands is that the forgot password link is aligned from the bottom of its parent (content). I need to align it relative to the button.
My initial idea was that I will align the forgotyourpassword div straight under the form. Thus, if the size of the form changes when the error messages are added, the forgotyourpassword link will be pushed downwards.
I can then set margin-top to a negative amount of pixels which should then push my forgotyourpassword div back up x pixels, which will then align the element with the submit button no matter how tall the form has become.
I am finding that this is not the case:
In firefox 10, the forgotyourpassword div does not seem to get "pushed up" by a the amount of pixels I have defined once it overlaps with the content area of the form.
In IE9, the forgotyourpassword appears above the form!
Is there a way to do this with just CSS and having it work with IE7 and above and firefox?
#content form{
position: absolute;
top: 80px;
right: 0px;
}
#forgot-password{
height:80px;
}
If you try something like this, you take the form out of the flow, and the link will appear above it without any fine-tuning. Once the top value for #content form and the height value for #forgot-password match, you should be safe as houses.
In some cases, you could have issues with clearing the absolutely positioned div, but you say you're setting the height for #content, so it shouldn't be a problem here.
Since I am not able to change the markup for the form, I am not able to insert the div for forgotyourpassword as a child of the form.
So, I added a wrapper div:
<div id="content">
<img src="some_content.jpg">
<div id="wrapper>
<form action="...">
<input type="text" ... >
<input type="submit" ...>
</form>
<div id="forgotyourpassword">
Forgot your password?
</div>
</div>
</div>
Then is simply a matter of adjusting the margins for the forgotyourpassword div:
#forgotyourpassword{
float: left;
margin-top: 10px;
}
This is the best solution I can come up with now as the wrapper div does not add any sematic value to the document, but I don't think there would be an easy solution otherwise (until we can use math and get dimensions of elements in CSS).

CSS to Replace Table Layout for Forms

I've looked at other questions and am unable to find the solution to this. Consider this image: mockup http://img201.imageshack.us/img201/935/image2h.png
I want to wrap divs and stack them vertically. The GREEN div would be a wrapper on a line. The BLUE div would contain an html label and maybe icon for a tooltip. The ORANGE div would contain some sort of entry (input, select, textarea).
Several of these would be stacked vertically to make up a form. I am doing this now, but I have to specify a height for the container div and that really needs to change depending on the content - considering any entry could land there. Images and other stuff could land here, as well.
I have a width set on the BLUE div and the ORANGE is float:left. How can I get rid of the height on divs and let that be determined by content? Is there a better way? Changing all to something else would be difficult and would prefer a way to style all elements or something.
The code I'm using is like:
<div class=EntLine>
<div class=EntLbl>
<label for="Name">Name</label>
</div>
<div class=EntFld>
<input type=text id="Name" />
</div>
</div>
The CSS looks like:
.EntLine {
height: 20px;
position: relative;
margin-top: 2px;
text-align: left;
white-space: nowrap;
}
.EntLbl {
float: left;
width: 120px;
padding: 3px 0px 0px 3px;
min-width: 120px;
max-width: 120px;
vertical-align: text-top;
}
.EntFld {
float: left;
height: 20px;
padding: 0px;
width: 200px;
}
Well, for a start I think you could use less mark-up to achieve your aim. You might have a good reason for wrapping a div around every element of your form, but if it's just to force a single label-input pair to each line then you can nest the input inside the label tag:
<label for="Name">Name
<input type="text" id="Name" />
</label>
This way you can use a simple:
label {display: block; }
to force each pair to their own line. This would also remove the need to float the labels, which removes the need to specify the height of any containing element.
You can still apply multiple classes to the relevant fields/labels, but it's far less trouble. Unless I'm really missing something.
Failing all of that, you could simply add an empty div (or other element), after the last of your fields and style with:
#empty_element {
disply: block;
height: 0;
clear: both; /* to force the parent element to expand to contain this element and, by extension, any non 'position:absolute' siblings that precede it in the mark-up */
visibility: hidden;
}

Select inputs and text inputs in HTML - Best way to make equal width?

I've got a simple form like so (illustrative purposes only)...
<form>
<div class="input-row">
<label>Name</label>
<input type="text" name="name" />
</div>
<div class="input-row">
<label>Country</label>
<select name="country">
<option>Australia</option>
<option>USA</option>
</select>
</div>
</form>
My layout method using CSS is as follows...
form {
width: 500px;
}
form .input-row {
display: block;
width: 100%;
height: auto;
clear: both;
overflow: hidden; /* stretch to contain floated children */
margin-bottom: 10px;
}
form .input-row label {
display: block;
float: left;
}
form .input-row input,
form .input-row select {
display: block;
width: 50%;
float: right;
padding: 2px;
}
This all aligns quite nicely, except my select element (in Firefox anyway) isn't always the same width as my other input elements. It generally is narrower by a few pixels.
I've tried changing the width to a pixel size (e.g. 200px) but it has not made a difference.
What is the best way to get these to all have the same width? I hope it doesn't resort to me setting the select's width individually, or putting them into tables...
The solution is to specify box model for form elements, and browsers tend to agree most when you use border-box:
input, select, textarea {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
There's normalize.css project that aggregates such tricks.
padding will make the text be closer to the edge of the box.
try setting the margin to 0px, and if that seems right, play around with it (like just setting margin-left only)
Had same problems with 100% width table and cells, with a textbox (also with width at 100%) wider than the table cell.
This solved my problem in the css:
table td
{
padding-right: 8px;
}
Not the best solution ever, cause you probably get some additional space to the right side. But at least it's not hiding anymore!

Resources