Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I have such situation: http://jsfiddle.net/HKHS3/
The question is how to make divs appear row after row where all divs in one row have the same height, depending on actual content of the tallest one?
So, depending on body's width the number of divs in a row will vary but each time the div right after the end of row should kind of clear floating and start a new row.
Fixed number per row
You can do this by creating a row type div to wrap your inner div elements.
First you need to restructure your HTML, something like this:
<div class="row">
<div>abc</div>
<div>adb djhf kdfhv fkjsh vhf jhds fjhf jh fjhf jh fdjh dh</div>
<div>dhfjgh jfh gkjhfde jghf jgh jfdh gjfhd gjfdhg jfhd gjdhf jhg djhg jdh gjhfd</div>
</div>
(you can add more rows like this as you need to)
Then the following css should do what you need:
.row {
display:table-row;
}
.row > div {
width: 100px;
display:inline-block;
vertical-align:top;
border: 1px solid black;
margin: 5px;
height:100%;
}
Here is your example updated
Dynamic number per row (not perfect)
The problem with the above method is that it requires you to have a fixed number of div elements per row. If you wanted it to be dynamic and wrap then you will have a problem doing this with just CSS alone. The closest you could get to it would be as follows:
div {
width: 100px;
display:inline-block;
vertical-align:top;
margin: 5px;
}
But the elements do not all have the same height, it is just you cannot tell that without the border. Due to this, adding a border, background-color or any other style that shows the element's height will break the effect.
Here is an example of this
Exactly as required (requires javascript)
It is worth mentioning that the effect you want is doable using javascript. I wont include an example of this because the actually implementation will depend heavily on how your real HTML is set up.
Actually, I had a quick go at the javascript approach, it uses JQuery though, and can likely be optimised too:
function updateHeights() {
var maxHeight = 0, lastY = 0, rowDivs = [], allDivs = $("div"), count = allDivs.length;
allDivs.each(function (i) {
var div = $(this), offset = div.offset(), y = offset.top, x = offset.left, h = div.height();
if (h > maxHeight) maxHeight = h;//store the highest value for this row so far
if (lastY == 0) lastY = y;//get the y position if this is the first element
//if new row
if (y > lastY) {
resizeElements(rowDivs, maxHeight);//resize all elements on this row
rowDivs.length = 0;//reset the array of row elements, ready for next row
maxHeight = h;//set maxHeight to first of new row
}
lastY = y;//store current y posible for checking if we have a new row or not
rowDivs.push(div);//add current element to row collection
//check if last item, is so then resize this last row
if(count - 1 == i)
resizeElements(rowDivs, maxHeight);
});
}
function resizeElements(elements, height) {
for (var i = 0; i < elements.length; i++) {
$(elements[i]).height(height);
}
}
$(window).resize(function () {
updateHeights();
});
updateHeights();
Here is a working example
It is very simple using jQuery. For all divs in same row give single class. Lets say 'sameheight' in my example. Then use this jQuery.
$(document).ready(function(){
var maxHeight = 0;
$(".sameheight").each(function(){
if ($(this).height() > maxHeight) { maxHeight = $(this).height(); }
});
$(".sameheight").height(maxHeight);
});
For multiple rows repeat the code with different class.
Hope this solves your issue.
try this
<script type="text/javascript">
$(document).ready(function () {
var maxHeight = 0;
$('div').each(function () {
var this_div = $(this);
if (maxHeight < this_div.height()) {
maxHeight = this_div.height();
}
})
$('div').css({ 'height': maxHeight.toString() });
})
</script>
Related
Here's an example list I have of products: http://imgur.com/7IGthIa
I've got a function that runs on document-ready that cycles through each list and adjusts the height of a span around the img, so that the space is uniform throughout the entire list.
What I'm wondering is, is there a way to have it detect when the "row" changes, so that the spans appear as-is on the first row (as they're sized appropriately based on the first two, but on the second row, with the single entry, the span is the height of THAT image?
The function does the same thing with the height of the LI elements, and I'll probably adjust it to size this per row as well, if there's a workable solution.
This is the function it runs to calculate the height, if it's of any use:
if ( jQuery('.product_list').length ) {
var tallest = 0;
var tallest_img = 0;
jQuery('.product_list li').each( function() {
if ( jQuery(this).height() > tallest ) { tallest = jQuery(this).height(); }
if ( jQuery(this).children('a').children('span').children('img').height() > tallest_img ) {
tallest_img = jQuery(this).children('a').children('span').children('img').height();
}
});
jQuery('.product_list li').height( tallest );
jQuery('.product_list li span').height( tallest_img );
}
Thanks!
You can detect when a row changes by checking an element's offset().top.
Since you're setting heights on the spans, I'll assume they have a style of display: inline-block. (You can't set the height of an inline element.)
Since the spans are children of the lis, you shouldn't have to worry about setting the li heights (unless I misunderstood your question).
This code iterates through the spans, giving them equal heights per row based on the tallest img within each row:
function sizeSpans() {
var spans= $('ul span'),
tallest,
top= $(spans[0]).offset().top;
spans.css('height', '');
tallest= $(spans[0]).height();
spans.each(function(idx1) {
if($(this).offset().top === top) {
tallest= Math.max(tallest, $(this).height());
spans.each(function(idx2) {
if(idx2 <= idx1 &&
$(this).offset().top === top
) {
$(this).css('height', tallest);
}
});
}
else {
tallest= $(this).height(),
top= $(this).offset().top;
}
});
} //sizeSpans
You can add this to a resize handler:
$(window).resize(sizeSpans);
Working Fiddle
Click the Size spans button at top. Resize the frame to see sizes readjust.
I have something like this:
http://s9.postimg.org/wwizuwnq7/Untitled_1.png
And if you see, the divs (Where I marked in green) have a space of some pixel.
And i want if there is a 0-20 pixel space between divs, to order them like this:
http://s23.postimg.org/ky2htcpt7/image.png
So, i started to do this on javascript and i dont know to to continue..
var position = new Array();
$(".post").each(function(){
position[$(this).attr("id")] = $(this).offset().top - $(window).scrollTop();
});
now i have all the position of all the divs, and now i need to check where divs have a space of 0 - 20 pixel, and then i want to take down the higher block.
I not sure if this is the good way, and if now, i need another idea..
Thanks!
I managed to find a method!
var position = new Array();
$(".hblocks").each(function(){
position[$(this).attr("id")] = $(this).offset().top;
});
$.each(position, function(key, value) {
$.each(position, function(key2, value2) {
var space = value2 - value;
if (space <= 20 && space >= -20 && space != 0)
{
var finalSpace = Math.max(value, value2);
var spaceplus = space + 28;
if (finalSpace != value)
{
$("#" + key).css("margin-top",spaceplus + "px");
}
else
{
$("#" + key2).css("margin-top",spaceplus + "px");
}
}
});
});
You can do this by adding a container div around the bottom 2 blocks. That way they will always be in line, regardless of the height of either of the top two blocks. You should try not to use javascript for styling. CSS is very powerful.
Here's a fiddle: http://jsfiddle.net/kVn7x/
HTML:
<div>
<div style='height:100px;'></div>
<div style='height:200px;'></div>
</div>
<div style='clear:left'>
<div style='height:80px;'></div>
<div style='height:80px;'></div>
</div>
CSS:
div div{background:red; width:150px; display:inline-block; margin:5px; float:left; clear:none}
Can't you simply add a bottom margin to the selected element in CSS?
#element {
margin-bottom: 20px;
}
Your answer would be some king of javascript+css coding to verify height of elements .. work on em then re-arrange them.
Stop trying to figure out by yourself, try using Masonry or jQueryEqualHeight explained on CSSTrick.
What is Masonry?
Masonry is a JavaScript grid layout library. It works by placing
elements in optimal position based on available vertical space, sort
of like a mason fitting stones in a wall. You’ve probably seen it in
use all over the Internet.
This is untested but something like this should work after your code...
The idea is to continuously add 1pixel to the top margin of the problematic div until the difference between the two divs is 20px
while(position['div1'] - position['div2'] <20){
$('#div2').animate({marginTop: '+=1px'}, 0);
}
If you want to show them directly in line as in your picture, it's even easier:
var diff = position['div1'] - position['div2']
if(diff < 20){
$('#div2').animate({marginTop: '+=' + diff + 'px'}, 0);
}
I wrote jsfiddle example for better explanation, so, how to make red bars fill the whole height of .frame? And may be there are any absolutely different better way to make things like this?
Positioned elements are no longer part of the layout, so they have no idea what the dimensions of the parent element are. You need to use JavaScript to do this.
I solve it myself. JSfiddle demo.
var move_bookmark = function(){
var sh = parseInt($(this).css('height').replace('px',''));
var ph = parseInt($(this).parent().css('height').replace('px',''));
if (sh%2==0)//this is for solving [this problem] -
//http://math.stackexchange.com/questions/183018/pixel-rectangle-precise-rotating
{
if(ph%2!=0)
{
ph++;
$(this).parent().css('height',ph+'px');
}
}
else
{
if(ph%2==0)
{
ph++;
$(this).parent().css('height',ph+'px');
}
}
$(this).css('width',ph+'px');
var sw = ph;
var offset = parseInt(ph-sw/2-sh/2)+'px'
console.log(sw+"/"+sh);
$(this).css('top',offset);
$(this).css('left',-sw/2+sh/2+'px');
$(this).parent().css('padding','0px 0px 0px '+sh+'px');
}
$('.bookmark').each(move_bookmark);
How can I determine (using jQuery?) the height of a div? Its' height is not defined in CSS - so it's fluid and based on the contents.
I've tried $('#div').height() - which returns 0.
Ideas?
EDIT: (the code)
$(document).ready(function () {
PositionBottomPicture();
});
function PositionBottomPicture() {
var parentOffset = $('#left_pane').offset();
var parentsHeight = $('#left_pane').height();
var childsTopPostion = (parentOffset.top + parentsHeight);
$('#bottom_pic').offset({ top: childsTopPostion, left: parentOffset.left });
}
CSS:
#left_pane
{
float: left;
margin-left: 27px;
position: relative;
}
where 'left_pane' and 'bottom_pic' are divs.
Thanks!
The problem is you're probably not waiting for the div to load into the DOM.
Try something along the lines of:
$(document).ready(function(){
var h = $("#div").height();
var w = $("#div").width();
;})
Using the Document Ready tool provided by jQuery will wait till the element has been processed.
If 'left_pane' only contains absolutely positioned elements it's height will be zero.
I have a paragraph followed by an unordered list, with several list items. I also have an image floated to the left of that. The problem I am having is that the list item margin/padding is being overlapped by that image.
I want the bullets that are next to the image to indent like it should.
Here is a test I wrote up for debugging, where you can see my issue in action.
All of this is inside of a CMS, so the image dimensions are variable, as well as the paragraphs and possible lists in the text.
Any solutions?
(See my first comment for pictures.)
ul {
overflow: auto;
}
I'll have the added advantage of not having the list items wrapping around the image.
Add this:
ul{ list-style-position: inside}
That's it!
Another option would be to shift the list to the right with relative positioning:
img+p+ul {
position: relative;
left: 1em;
top: 0;
}
li style="margin-left: 135px;" Worked best for me.
The overflow: auto; looked ok up front but wound up messing with other elements in my HTML.
You can give your list items an overflow property:
li {
overflow: hidden;
}
That will cause the list item to sort of behave correctly: They will display as a square block, continuing where the image ends as well, they don´t flow nicely to the left. The next list item will.
If you don't bother about adding javascript, here is a jQuery script that will add a margin to the ul that overlaps the image so all the list items remain aligned, and then assigns a negative margin to the li's that doesn't overlap.
$(function(){
//Define a context so we only move lists inside a specified parent
var context = $("#test_div");
//Build a list of images position a size
var imgRects = [];
var imgs = $("img.left", context);
imgs.each(function(i){
var pos = $(this).position();
pos.right = pos.left + $(this).outerWidth(true);
pos.bottom = pos.top + $(this).outerHeight(true);
imgRects.push(pos);
});
//Process each li to see if it is at the same height of an image
var lis = $("li", context);
lis.each(function(i){
var li = $(this);
if(li.parent().css('marginLeft') != "0px"){
return; //Already moved
}
var top = li.position().top;
for(var j in imgRects){
var rect = imgRects[j];
if(top > rect.top && top < rect.bottom){
li.parent().css('marginLeft', rect.right);
return;
} else if(li.parent().css('marginLeft') != "0px"){
li.css('marginLeft', -1 * rect.right);
}
}
});
});
I've tested with your demo page and jQuery 1.3.2 and it works on FF3.5 and IE8 because the image is on top of the document. If the image appears in the middle of a ul, the firsts li's will remain padded. If you need to correct this issue leave a comment and will try to update the script.