Make div fill remaining space of parent - html

I need some help with positioning divs. The HTML structure is as follows:
<div class="container">
<div class="item">
<div class="left">
lorem lorem
</div>
<div class="right">
<p>right</p>
<p class="bottom">bottom</p>
</div>
</div>
</div>
And I have the following CSS:
.container {
float: left;
padding: 15px;
width: 600px;
}
.item {
float: left;
padding: 15px;
width: 570px;
}
.left {
float: left;
padding: 40px 20px;
margin-right: 10px;
}
.right {
position: relative;
float: left;
}
.bottom {
position: absolute;
bottom: 0;
}
The width and height of the left div is dynamic.
What I want to achieve is:
Make the height of the right div equal to height of the left div.
Make the width of the right div fill the rest of the div with class item.
The paragraph with class bottom should be at the bottom of the right div.
Here is a simple image that represents my goal:
And a link to a JSFiddle demo.

Getting the correct position and width of .bottom appears to be the biggest hurdle for a cross-browser, CSS solution.
Options
1. Floats
As #joeellis demonstrated, the flexible widths can be achieved by floating only the left column, and applying overflow:hidden to the right column.
The position of .bottom cannot be achieved in any browser. There's no CSS solution for floated columns with equal, variable height. An absolutely positioned .bottom element must be inside the right column div, so that 100% width would give it the correct size. But since the right column won't necessarily be as tall as the left column, positioning .bottom with bottom:0 won't necessarily place it at the bottom of the container.
2. HTML tables and CSS tables
The flexible widths can be achieved by giving the left cell a width of 1px and not specifying a width for the right cell. Both cells will grow to fit the content. Any extra space will be added to the right cell alone.
If .bottom is inside the right table cell, the position can't be achieved in Firefox. Relative position has no effect in a table cell in Firefox; absolute position and 100% width would not be relative to the right table cell.
If .bottom is treated as a separate table cell in the right column, the correct heights of the right and bottom table cells cannot be achieved in any browser other than Firefox. Table cells aren't flexible in height the same way they are in width (except in Firefox).
3. CSS3 flexbox and CSS3 grids
Flexbox and grids are the promising layout tools of the near future. But flexbox isn't supported by IE9 or earlier, and grids aren't supported by any browser other than IE10. Haven't tested if either can achieve this layout, but browser support may prevent them from being an option at present.
Summary
Floats don't offer a solution for any browser.
HTML tables and CSS tables don't offer a cross-browser solution.
Flexbox doesn't offer a potential solution for IE9 or earlier (and may or may not offer a solution to other browsers).
Grids only offer a potential solution to IE10 (and may or may not offer a solution there).
Conclusion
There doesn't appear to be an adequate CSS solution at present, one that would work in enough relevant browsers, with the possible exception of flexbox (if support for IE9 and earlier isn't required).
jQuery
Here's a couple modified demos that use jQuery to force the columns to have the same height. The CSS and jQuery for both demos is the same. The HTML only differs by how much content is in the left and right column. Both demos tested fine in all browsers. The same basic approach could be used for plain JavaScript.
Taller content on the left
Taller content on the right
To keep things simple, I moved the internal padding for the left and right div to a child element (.content).

Sibling elements of same height and staying on the same row can be achieved by displaying them as table-cell and parent as display: table.
Working fiddle: http://jsfiddle.net/SgubR/2/ (which also display the overflow: hidden along a floating element technique for creating a column. The latter needs a clearfix)
Table-cell in CSS uses any HTML element you want (section, div, span, li, whatever), its semantics is unrelated to table, tr and td elements used for table layout (except that the visual result is the same, that's what we want).
display: table is set on a parent
display: table-row may be used on an element in-between but if it works without it, fine
display: table-cell is set on each child
a width is set on none, some or all these "cells". Browser will adapt both to content and widths set in order to calculate their widths (and total width of parent, obviously)
table-layout: fixed will tell browsers to switch to the other table layout algorithm where they don't care about the quantity of content, only to widths set by CSS
vertical-align: top will be needed in most cases (but you may set other values, great for complex layouts)
margins aren't applied on "cells", only padding. Margins only apply on table itself. Though you still can separate "cells" with border-collapse: separate and/or border-spacing: 4px 6px
Compatibility: IE8+
Fallback for IE6/7 if needed is exactly the same as for inline-block
Longer explanations in previous answers: here and there with also the good old method of faux-columns (your design must be thought with this technique in mind)

Just add an oveflow to the right column and don't float it.
.right {
position: relative;
overflow: hidden;
}
This will make right to fill the rest of the width.

Something like this might work:
http://jsfiddle.net/PCvy9/2/
The main key of what you're looking for lines in the:
.right {
overflow: hidden;
background-color: #C82927;
}
This is due to something called the "block formatting context." Great reasoning and tutorial as to why here: http://colinaarts.com/articles/the-magic-of-overflow-hidden/#making-room-for-floats
However, their heights are not completely linked; in this example, your left side block's height would still need to be manually set (as it's a floated container)

Related

Chrome and Edge floating middle image below first and last, is this correct?

It seems that in Microsoft's edge and google chrome the floating doesn't rearrange the divs properly, if you have three divs floated left and the page is scaled in a width between 444 and 436 px the third div goes to the second div's position instead of going below it. This "bug" does not occur in firefox.
I made a JSFiddle to be tested http://jsfiddle.net/e47jckrh/
HTML
<div id="d1">
<p>1</p>
</div>
<div id="d2">
<p>2</p>
</div>
<div id="d3">
<p>3</p>
</div>
CSS
div{
float: left;
}
Down below there is a visual representation of how it should behave
Full page Layout
Correct div floating when page width is more than 444px
Wrong div floating order when page width is between 444 and 436px
Correct div floating when page width is less than 444px
It may be just me thinking there is something wrong, but i assume the firefox behavior to be the correct one.
I've edited your fiddle here: http://jsfiddle.net/e47jckrh/5/
You didn't float all your elements as you'd suggested in the question. So I added float: left; to the div numbered 3 and set all 3 to display: inline-block;. And using display: table; and display: table-cell; with vertical-align: center; is a really old way to get something to align vertically.
These 3 lines work for most things:
position: relative;
top: 50%;
transform: translateY(-50%);
Okay. So #d3 shouldn't be on the right side at all because it isn't floated, but you used display:table. This gives it the effect of being floated with the other two divs for some reason.
Since it uses display: table #d3's margins are off the page but don't count as "not fitting" and don't force it to the next line.
#d2 is floated though so its margins DO affect it. So in the small range you're experiencing this #d1 + #d2 won't fit because of their margins contributing to an overall larger size width but #d1 + #d3 will because #d3 is not being affected by its margin on the right side giving the combo an overall smaller size width.
Simple solution is to float #d3 as well:
#d3 {
background-color: #ede4ad;
border: 3px dotted #6e5b3c;
clear: right;
float: left;
}
The behavior is caused by margin-right.
When div 2 reaches its containers right limit it overflows. In this case you control his limit by margin-right. BUT margin-right is only effective if there is succeeding element ( its calculated base on a succeeding element ). In this case div 3.
After it overflows in new line the div 3 takes its spot. But in this case margin-right has no effect since its the last element in this flow.
EDIT : I just realized you haven't floated all element , I don't know if that was your initial idea. If it was I won't delete this answer.

How to make a div fill up remaining horizontal space

I have two divs. One that is floated left and one floated right. The one of the left has a width set to 18% and a min-width of 217px. I want to have the div on the right take up the remaining space, while also being able to resize to fit the window.
The problem I am having is that I can set the right div's width to 82% and to float right, which works until I make the window side too small, in which case the min-width of the left div kicks in and it stops shrinking. The right div doesn't have enough space to fit, so it is pushed down.
Here's some sample code.
HTML
<div id="div1">
stuff inside of it
</div>
<div id="div2">
stuff inside of it
</div>
CSS
#div1
{
float: left;
width: 18%;
height: 100vh;
min-width: 130px;
box-shadow: 0px .3em .2em #000;
z-index: 2;
}
#div2
{
width: 82%;
float: right;
z-index: 1;
}
So this is where I'm stuck, how should I approach fixing div2? I've tried using a table instead of divs, but a border appeared around the cells that I couldn't change and it removed my box-shadow, so I would prefer a solution without it.
Your thinking of using tables is somewhat on the right track, as table elements do actually have many properties that make them capable of such a thing, but as people are pointing out in the comments, it's no longer a valid approach to use table elements for the purposes of layout for non-tabular data.
This is why CSS implemented a set of style rules built to reflect those unique properties. You can set a container around two elements with the style display: table;, and then give it's children the style display: table-cell;
Setting the width for the right side div to 100% will ensure it always fills as much space as is available to it.
But, since table cells can't break to a new row when the content exceeds the width of the table, it will automatically adjust to fit. So when another div (the left one) has a specific min-width, the div on the right is given less space in order to keep the cells contained.
Here's an example using your code:
http://jsfiddle.net/Q5rjL/
CSS table display properties give you all the benefits of these unique elements, but without the semantic issues. They are great for complex layouts where other style display types fall short.
You can also contain floats with overflow:hidden:
#div2{
overflow:hidden;
z-index: 1;
}
The DIV will fill up the remaining space (http://jsfiddle.net/MAjwt/)

Making a button element fill available width

There are a lot of "fill available space" questions on this site, but my issue is a bit particular in that I've already gotten a solution, but it doesn't work for buttons. I'd like to understand why this doesn't work for buttons, and how I can make it work. I imagine it's just some browser-style for the button element that I need to override.
I have two floating elements within a (fixed-width, if that matters) wrapping div. The right element has fixed width, and the left element should take up whatever width remains.
I can accomplish that by setting the right element to have fixed width and float: right, and leaving the left element without any special styling. This works perfectly for divs. It also works for spans, but only if I set display: block on them. For buttons, I can't get it to work at all. I tried block, inline-block, and every obscure width value I could find on the MDN.
http://jsfiddle.net/wjFbD/2/
I don't know why I didn't think of just wrapping the buttons in divs earlier. Here's what I've come up with:
http://jsfiddle.net/SkczB/2/
This involves the overflow: hidden box formatting context trick (which I suspected was going to make an appearance here, but couldn't quite see where to fit it in). Highlights:
The two buttons are wrapped in divs with class buttonWrapper.
Those divs are formatted according to the trick I outlined in the third paragraph, above. The right div has float: right and a fixed width, the left div has no special styling.
We now apply the box formatting context trick. The left div is given overflow: hidden, which causes it to make space for the right-floated div.
We can now apply a left margin to the right div, and change its width, and the left div will always be the right size.
The divs create the desired "fill available width" effect for us, now we just have to put the buttons inside the divs and give them a height and width of 100%.
If it's the left button you wanted to have a fixed width, then basically repeat the above steps with left and right swapped.
This may not be exactly what you're looking for here, but here's an option that seems to have worked out for me with your fiddle.
If you've got a fixed width div that the elements are contained in, you could split get the remaining width of the div after button A has been set to fill up, say, 100 pixels and then set button 2 to be the remaining size.
Alternatively, another option would be to run it as percentages 20%/80%, 30%/70%, that kind of thing. Here's a fiddle that achieves what you're looking for on just the button wrapper at the bottom. I've applied specific classes for it and added divs around each button for a bit more control. The button wrapper divs are set to 20% and 80% respectively, while the button is set to fill 100% of the containing space.
Here's the modified fiddle and the modfied HTML/CSS. Hope it helps for what you're looking for...
http://jsfiddle.net/wjFbD/7/
HTML
<div class="btnWrapper">
<div class="buttonWrapperB">
<button class="left">
button Left
</button>
</div>
<div class="buttonWrapperA">
<button class="right">
button Right
</button>
</div>
</div>​
CSS
.btnWrapper
{
width: 100%;
background-color: #FEE;
border: 2px solid black;
margin-bottom: 10px;
height: 50px;
}
.buttonWrapperB{
float: left;
width: 20%;
}
.buttonWrapperB button{
width: 100%;
height: 50px;
}
.buttonWrapperA{
float:left;
width: 80%;
}
.buttonWrapperA button{
width: 100%;
height: 50px;
}
​
I adjusted the background opacity of your .right elements to see what was going on below them. It looks like the .left elements are not only taking up the remaining space-- they're also taking up the entire row. Weirdly, the text inside these elements is centered as if it were only taking up the remaining space.
If you want the same to work for the buttons, it seems like the only solution involves a little hack. Buttons are quite complex indeed.
button.left {
margin: 0;
position: absolute; /*this seems to be the only way to get the button to stay on the same row - floating it left won't even work*/
z-index: -1; /*hides the "overflowing" part below the right button*/
width: 100%; /*make the button stretch to the full width of the row*/
padding-right: 400px; /*add a padding-right hack so that text will be centered correctly - should be same size as fixed width .right element*/
padding-left: 0;
display: block;
}
See updated fiddle: http://jsfiddle.net/wjFbD/6/
starting with
One element has fixed width, and the other element should take up
whatever width remains.
here is my general solution:
<div class="container">
<div class="two">125 €</div>
<div class="one">my favorite provider</div>
</div>
(stylus syntax, in your mind just add {,},;)
.one // red
border none
height auto
overflow hidden
white-space nowrap
text-overflow ellipsis
.two // green
float left
white-space nowrap
text-overflow ellipsis
You can set the one green thing to a fixed width, but indeed, you do not even have to! Things full up nicely. And String get's truncated with an ellipsis, if it gets too long.
Things get a bit more complicated, when one of them is a <button> rather than a <div> (and I can't figure out, which style property differenciates them, so I would need to style away), but anyway, with a wrapper, that also works:
→ See full codepen here. (Feedback appreciated.)

use margin or position relative to position elements

I have always used margin to move a floating div to the correct position in a parent div (say the logo div within a header div). This has always worked but that meant you have to play with the individual height of the elements else it will affect the remainder of the layout downwards.
I found another method today and that is to make the logo div position: relative; and then use example top: 20px; to move the element around, and this does not appear to affect the layout.
I don't want to adapt to this without knowing that there may be other implications, so can anyone point out common flaws in either of the above methods or possibly suggest a better solution?
// Sample HTML
<div id='header'>
<div id='logo'>
LOGO GOES HERE
</div>
</div>
// Sample CSS
#header {
height: 100px;
}
// Version 1
#logo {
float: left;
margin-top: 20px;
}
// Version 2
#logo {
float: left;
position: relative;
top: 20px;
}
From Mozilla developer:
relative
Lay out all elements as though the element were not
positioned, and then adjust the element's position, without changing
layout (and thus leaving a gap for the element where it would have
been had it not been positioned). The effect of position:relative on
table-*-group, table-row, table-column, table-cell, and table-caption
elements is undefined.
I hope this answers your question.
Sometimes it might be the right thing to use, other times not. It really depends on your layout, if you want to make a responsive design, it might be better to have the margin there.
In your case you have a fixed height on the header, so you can use relative. I think it is a more common practice to use margin. I am only aware on issues concerning position: fixed on mobile devices.
You can learn more about CSS and positioning here.
In postion absolute and fix when u use top or bottom or right or left,you must not use float, you must for its parent use this style
postion:relative;
best regards

Displaying elements in multiple rows using CSS

I have a fixed width container <div> that displays one or more widget <div>s. I want it to look like this:
<- grey blocks are widgets, red border is the container
Simplified, my structure in HTML looks like this:
<div id="container">
<div id="widget1">1</div>
<div id="widget2">2</div>
<div id="widget3">3</div>
<div id="widget4">4</div>
<div id="widget5">5</div>
<div id="widget6">6</div>
<div id="widget7">7</div>
</div>
Considerations
Widgets will have a fixed height e.g. 100px
Widgets will have a fixed width e.g. 100px but they may also be a multiple of that width (plus any margins crossed - see widget 1)
Widgets should be spaced nicely with a margin (or similar) e.g. 10px
I don't know how many widgets there will be (the user can assign as many or few as they like to the container).
The container is a fixed width but doesn't have any "visual" styling (the red border is there for demonstration)
Solution has to work in modern browsers (and MSIE7) and would ideally be pure CSS.
Because of consideration 4. I can't assign additional markup e.g. row div, classes (.first-child, .last-child) and because of 2. :nth-child wouldn't work AFAIK.
Things I've tried
margin-left on widgets with :first-child setting margin-left: 0 won't display a new row properly.
margin-right on widgets with :last-child setting margin-right: 0 the first row forces the container div wider and last-child isn't supported until MSIE9.
equal left and right margins (e.g. margin: 0 5px 10px) forces the container wide again.
overflow - works great in my head! Not so much with either margins or padding.
Is there a way to do this in CSS?
http://jsfiddle.net/agtb/VHXGT/
I believe you are thinking too complicated :-)
If I understand you correctly you don't need any special handling of the separate widgets. Just give the widgets an all around margin of half the spacing, and the container the same margin but negative.
#container {
width: 440px;
margin: -5px;
}
#container div {
background-color: gray;
height: 100px;
width: 100px;
float: left;
margin: 5px;
}
See http://jsfiddle.net/SGdG3/1/
set container width 400 and the first div width 200 float left, rest width 100 float left