I would like to build a sort of "stack" of divs (with class .inner) within a containing div (#container) where each inner is pushed as far down in the container as possible without overlapping another inner. I've included illustrations of what this would look like with one and three inners, respectively:
I know I could get the result on the left by setting...
#container { position: relative; }
.inner {
position: absolute;
bottom: 0;
}
...but this solution would not scale to the example on the right - instead it would cause all of the inners to overlap one another. Is there any good way to accomplish what I want through CSS alone for an arbitrary number of inners? I know I could do it with some hacky Javascript.
You could use an additional container for the inner containers and use the trick you suggested.
<style>
div{border:1px solid red}
#container{height:1000px;}
#inner-container{position:absolute;bottom:0px;}
.inner {height:200px;width:200px;margin:5px;;
</style>
<div id="container">
<div id="inner-container">
<div class="inner"></div>
<div class="inner"></div>
<div class="inner"></div>
</div>
</div>
Depends on what browsers you need to support. But a much cleaner solution would be to try mimicking some table layout in CSS.
I've not had a chance to thoroughly test this with IE8+, but most modern browsers can handle CSS table layout properties which would allow you to do something like this relatively easily.
So...
CSS
.container { display: table-cell; vertical-align: bottom; height: 400px}
HTML
<div class="container">
<div class="inner">1</div>
<div class="inner">2</div>
<div class="inner">3</div>
</div>
The only caveat is that if you have two of these "container" divs following each other in the code, than they will behave like table-cells (TDs) and sit next to each other.
If you want to stack them, then you can get around this by wrapping the containers in a div without the table-cell style, or sticking another element inbetween... e.g.
<div>
<div class"container">
<div class="inner">1</div>
<div class="inner">2</div>
<div class="inner">3</div>
</div>
</div>
<div>
<div class="container">
<div class="inner">1</div>
<div class="inner">2</div>
<div class="inner">3</div>
</div>
</div>
OR...
<div class="container">
<div class="inner">1</div>
<div class="inner">2</div>
<div class="inner">3</div>
</div>
<div></div>
<div class="container">
<div class="inner">1</div>
<div class="inner">2</div>
<div class="inner">3</div>
</div>
Related
I have a container div with X amount of smaller container squares. So something like this:
<div class="container">
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
</div>
The little-square divs will be rendered iteratively by use of a handlebars template. What I want it to do is to have a maximum of four little-square divs per line. So if we approach this situation:
<div class="container">
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
</div>
Then the expected result should be four little-squares in the first line of the container div, and then two little-squares in the second line. I was thinking about having some sort of js code implementing 'if created div is fourth in line, then inject a br in this div to force the newline', but not too sure if that's even well looked upon.
Any suggestions on how to do this? What should I take into consideration when planning this effect? (css noob here. thanks for the help).
There is no easy solution for this but you could hack it with display: inline on elements and content: "\00000a", white-space: pre.
.little-square {
background: black;
margin: 10px;
display: inline;
padding: 15px 25px;
line-height: 65px;
}
.little-square:nth-child(4n):after {
content: "\00000a";
white-space: pre;
}
<div class="container">
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
<div class="little-square"></div>
</div>
How to positioning the elements one under the other, regardless of the height of the item? As having the following markup, to place the elements in the following way:
.photo {
display: inline-block;
vertical-align: top;
max-width: 160px;
width: 100%;
margin: 0px 20px 20px 0;
background:red;
}
<div class="photo">
<div class="photo__item photo__item_1"></div>
</div>
<div class="photo">
<div class="photo__item photo__item_2"></div>
</div>
<div class="photo">
<div class="photo__item photo__item_3"></div>
</div>
<div class="photo">
<div class="photo__item photo__item_4"></div>
</div>
<div class="photo">
<div class="photo__item photo__item_5"></div>
</div>
<div class="photo">
<div class="photo__item photo__item_6"></div>
</div>
There are a couple of ways of doing this.
Emulate this effect by using the css column property, I found this fiddle for example, you can see how the elements are positioned.
Other way (most viable I think) is to use a plugin like masonry as #kukkuz said before, it does almost everything you need.
Create your own grid using javascript and css in order to position every element based on other element's positions (which I wouldn't recommend) because you have to do some calcs and it could take some time.
I am trying get a grid of div elements into a dynamic grid system. When the width and height of all elements are static (and most importantly all the same) it works by setting float:left on the element to get the desired effect.
HTML:
<div id="main">
<div class="someDiv">1 - Text</div>
<div class="someDiv">2 - Text</div>
<div class="someDiv">3 - Text</div>
<div class="someDiv">4 - A lot longer text.</div>
<div class="someDiv">5 - Text</div>
<div class="someDiv">6 - Text</div>
<div class="someDiv">7 - Text</div>
<div class="someDiv">8 - Text</div>
<div class="someDiv">9 - Text</div>
<div class="someDiv">10 - Text</div>
</div>
CSS:
div.someDiv {
float:left;
margin: 10px;
padding:5px;
width:150px;
display:inline-block;
}
If I however have one element that has a larger body of text inside it (thus having a larger height than the others) all elements which are on the row below and to the left of this seem to be "pushed" down. Behaviour can be observed here; jsFiddle.
What I wish to do is to get all div elements (in the example this would be elements 5,6 and 7) to be just under the elements above them (elements 1,2 and 3 in the fiddle).
How can I achieve this, whilst still keeping a dynamic height of each div?
Assuming the columns have a fixed width and you are ok with a fixed number of columns then rework the html to have fixed width columns (divs) that float left. Put equal width divs in them and the height won't matter.
If you want a dynamic number of columns with this method you would need to use javascript to move inner divs and decide the number of cols to have based on width then assign the dis to columns.
I believe angularjs ui-grid can handle them much more complicated situations often.
EDIT:
Here is a fiddle to demonstrate.
http://jsfiddle.net/6mDLC/
Maybe I misunderstood what you want, let me know if the fiddle doesn't do what you do want
HTML:
<div class="main">
<div class="col">
<div class="content">
Some text
</div>
<div class="content">
Some text
</div>
<div class="content">
Some text ASFKLAJJK ALKSJFLF LAJ SFLKJAS LFKJA LSFJ ALSKFJASL FK ALSKFJ ALKFJ AL
</div>
<div class="content">
Some text
</div>
</div>
<div class="col">
<div class="content">
Some text ASFKLAFJK ALKSJSKF LAJ SFLKJAS LFKJA LSFJ ALSKFJASL FK ALSKFJ ALKFJ AL
</div>
<div class="content">
Some text
</div>
<div class="content">
Some text
</div>
<div class="content">
Some text
</div>
</div>
<div class="col">
<div class="content">
more text
</div>
<div class="content">
Some text ASFKLAFJK ALKSJSKF LAJ SFLKJAS LFKJA LSFJ ALSKFJASL FK ALSKFJ ALKFJ AL
</div>
<div class="content">
Some text
</div>
<div class="content">
Some text
</div>
</div>
CSS:
.content{
width:150px;
border:1px solid red;
margin-bottom:10px;
}
.col{
margin:5px;
float:left;
}
JS:
$(".content").click(function () {
if ($(this).html().length > 40) {
$(this).html("This is just some random text");
} else {
$(this).html("This is just some random text, but is taking up more space than it was before. This will cause others to do weird stuff.");
}
});
Try using this
div.someDiv {
float:left;
margin: 10px;
padding:5px;
background:aqua;
width:150px;
display:inline-block;
overflow:auto;
height:50px;
}
What I am trying to accomplish is having a fixed-width first div and a fluid second div which will fill up the rest width of the parent div's width.
<div class='clearfix'>
<div style='float:left; width:100px;'>some content</div>
<div style='float:left'>some more content</div>
</div>
and on this one everything seems alright and fluid.
<div style='display:table'>
<div style='display:table-cell; width:100px;'>some content</div>
<div style='display:table-cell'>some more content</div>
</div>
I want to go ahead with the second one but i feel like the second example will give me headaches in the future.
Could you offer some suggestions or insights?
display: table-cell is perfectly fine to use, with just one downside..
It doesn't work in IE7 (or IE6, but who cares?): http://caniuse.com/#search=css-table
If you don't need to support IE7, then feel free to use it.
IE7 still has some usage, but you should check your Analytics, and then make a decision.
To answer your specific use case, you can do it without display: table-cell, provided that you don't need the height to adjust based on content:
http://jsfiddle.net/g6yB4/
<div class='clearfix'>
<div style='float:left; width:100px; background:red'>some content</div>
<div style='overflow:hidden; background:#ccc'>some more content</div>
</div>
(why overflow: hidden? With: http://jsfiddle.net/g6yB4/3/ vs without: http://jsfiddle.net/g6yB4/4/)
You could do something like this. It puts your main content first. You can use a vertically repeating css background image on your main "content" container to create the illusion of a background running all the way down the left column.
<div id="content" style="clear:both;">
<div id="mainwrap" style="float:left; width:100%;">
<div id="main" style="margin-left:100px">
Main content here
</div>
</div>
<div id="leftnav" style="float:left; width:100px; margin-left:-100%;">
Left content here
</div>
</div>
To extend to a 3-column with fluid center:
<div id="content" style="clear:both;">
<div id="mainwrap" style="float:left; width:100%;">
<div id="main" style="margin-left:100px; margin-right:100px;">
Main content here
</div>
</div>
<div id="leftnav" style="float:left; width:100px; margin-left:-100%;">
Left content here
</div>
<div id="rightnav" style="float:left; width:100px; margin-left:-100px;">
Right content here
</div>
</div>
To get the first example working, you should also float the containing div, this will make sure that both of the elements within sit as you would expect within it. Not really sure what you mean by 'is a pain', though?
One down side of using table-row (very related to the OP) is that you can't use margin/padding on a row.
I have a question about my layout. I have a setup something like this:
<div id="container">
<div id="body">
<div id="item">
</div>
<div id="item">
</div>
</div>
</div>
And I want the body box to stretch with the amount of items I put in it but it doesn't. anyone know how to fix this with css.
If your items are floated, you could add a block with clear: both; parameter set, as Pat mentioned already.
If you don't want one more element in your code, you could apply overflow: hidden; to your body:
<div id="container">
<div id="body" style="overflow: hidden;">
<div class="item"></div>
<div class="item"></div>
</div>
</div>
Be carefull though, as everything that sticks outside the body box will be cut.
First off, you should use a class for your item div's as id's should be unique on the page. Second, this is probably being caused by your item div's being floated. If you add a clearing element below them, it should fix it:
<div id="container">
<div id="body">
<div class="item"></div>
<div class="item"></div>
<div style="clear: both"></div>
</div>
</div>
Have your item divs float left (display: inline might work too, haven't tried it), and set the display of your body div to display:inline-block;. That should shrink to fit its contents.
Quick and dirty:
<div id="container">
<div id="body" style="display:inline-block; overflow: auto;">
<div class="item" style="float: left;">
Hi
</div>
<div class="item" style="float: left">
There
</div>
</div>
</div>
Edit: Fixed, thanks to Matt Sach.
I would personally discourage the use of inline-block, Internet Explorer support for it is poor in older versions.
IE 6-8 (8 compatibility mode only) have issues with it.