Three part dynamic spacing wo/Table and Absolute Positioning - html

I'm trying to place 3 divs within a larger div such that the center one is 800px wide, and centered, and the other two fill the space remaining. I cannot use tables, nor can I use absolute positioning, as I have html below that must be outside the three divs but inside the larger div. I can get the center div:
.center-div {
width: 800px;
margin-left: auto;
margin-right: auto;
}
But how do I position the other two divs?
<div id="outer">
<div id="left-div"></div>
<div id="center-div"></div>
<div id="right-div"></div>
</div>

You could try messing around with display: table-row; for the container div and display: table-cell; for the inner divs. You might even need a second container with display: table;—the basic idea is emulating a table without using table, tr, and td.
All those table-values for the display property are specified in CSS 2.1, but I have never personally tested which browsers support them. I’ll bet my money though that IE6 won’t be able to cope with it. ;-)

Related

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/)

Make div fill remaining space of parent

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)

Vertical centering of multiple images inside one DIV

I have a simple DIV with a fixed height like and several images with individual heights inside (their height is equal or less the height of the outer DIV):
<div>
<img src="..">
<img src="..">
...
</div>
This markup is as-is and can not be changed. I need to display all images side by side and all images should be vertically aligned with the middle of the DIV (so the padding top and bottom is identical per-image).
How to do that without changing the markup? Various answers deal with a markup where the image is placed itself inside a DIV which is not the case here.
After re-reading your question, that the <div> is at least as high as the highest image, simply do this:
CSS
img {
vertical-align: middle;
}​
Try it here: http://jsfiddle.net/AsD9q/
You can also prevent the div from breaking (when the viewport is to small) by setting an explicit width or using white-space: nowrap; on the container: http://jsfiddle.net/MvDZJ/ (using width) or http://jsfiddle.net/xMtBp/ (using white-space)
That's the outcome:
First answer, which works with every height of the div:
As you said nothing about container itself, I assume, that it's not wider than the viewport. Than you could simply do something like this:
HTML
<div>
<img src="http://lorempixel.com/200/100/">
<img src="http://lorempixel.com/200/80/">
<img src="http://lorempixel.com/200/120/">
<img src="http://lorempixel.com/200/60/">
</div>​
CSS
​div {
display: table-cell;
vertical-align: middle;
/* only added for demonstration */
height: 200px;
border: 1px solid red;
}
img {
vertical-align: middle;
}
This won't work in IE7 though, as it can't handle display: table-cell. You can try it here: http://jsfiddle.net/3vXXy/.
This can be done with jQuery, the problem is you have no explicit selectors to work with so it would affect every image in every div on the page.
First you need to set the images to the top of the div like this in the CSS:
div img{vertical-align:top;}
Then take each image in succession, get it's height and set it's top padding to half the difference between the height of the div and the height of the image.
​$(document).ready(function(){
$("img").each(function(){
var margin= ($(this).parent().height() - $(this).height())/2;
$(this).css('margin-top',margin);
});
});​
Again, not an ideal solution without good solid selectors, but it does work. http://jsfiddle.net/calder12/H4Wkw/

Vertical middle for an element within a variable height container

I have the following situation:
A variable height div (#container) with an image on the inside (image that is placed within another div) that I need to float:right and align vertically in the middle. How to do this?
Thanks.
EDIT:
Maybe I didn't make it clear enough that i do not know beforehand how much content the container has, from a few lines to a wall of text, so any solution relying on its height won't work (and that's my problem :P)
This is a fiddle with an example of possible content to which align the image: http://jsfiddle.net/9DbmN/
You should take a look at Centering in the Unknown by Chris Coyier. Imo it´s a pretty solid solution to the holy grail of vertical centering.
I would not discourage using tables here))) If you use a two-cell table with vertical-align: middle set on its td elements - it will perfectly (and easily!!!) solve your problem.
If you want to have two containers, one of which (the one with the image) will be floated to the right and needed centering - I'd say you'll have to avoid using float property for this. Because a) as far as I understand you don't need you content on the left to be UNDER the image, right? b) floats are block-level elements and you can't change it even if you set display: table-cell, the browser will still render it as display: block - which leads me to the conclusion that you won't manage to center it by css (at least by the means I'm aware of).
If you don't need ie7 support a possible workaround might be this:
html:
<div id="container">
<div class="content">Content goes here, vertically aligned with the image</div>
<div class="i_used_to_be_floated_right">Image goes here</div>
</div>
css:
#container {
display: table;
width: 100%;
}
.content, .i_used_to_be_floated_right {
display: table-cell;
vertical-align: middle;
}
.content {
background: green;
width: 80%;
}
.i_used_to_be_floated_right{
background: red;
width: 20%;
}
The working example live can be seen here: http://jsfiddle.net/skip405/sDXMj/1/
But if you need ie7 - I would vote for the table-solution I stated at the very beginning.

equalization 2 divs height only with css

I want to equal two divs height when a div height large
example :
<div style="float:left;padding:2px;background:red;">B</div>
<div style="float:left;padding:2px;background:green;">A<br />C<br />D</div>
<div style="clear:both;"></div>
the Div 2 height larger then div one
I may have a possible solution for you:
http://jsfiddle.net/adaz/wRcWj/1/
Well, it'll probably work on ie7+ so I'm not sure if that's good enough for you.
Brief description:
1) Set position relative to the container and self-clear it (I've used overflow: hidden but you can also use clearfix).
2) Float one of the divs inside so the container will expand depending on content inside.
3) Set position absolute to one of your divs, and give it top and bottom position 0px, this will make sure that it has 100% height.
Cons:
- Lack of IE6 support
- You need to chose which div will always have less content and then position in absolute
Hope it helps!
This is typically the behavior of a table, so you can do this with display: table-cell. I based an example on Adaz's : http://jsfiddle.net/L2uX4/
Wrap the two div's whose height you are trying to equalize in a container div, i.e.
<div id="container">
<div class="column">A<br/>B</div>
<div class="column">C</div>
</div>
Set an explicit height on the container and set height=100% on the columns:
div#container {
float: left;
height: 10em;
}
div.column {
height: 100%;
background-color: red;
}