Richard Russell
Richard Russell

Reputation: 1125

Positioning Divs semi-randomly, without overlaps

I have a page which has DIVs which contain short phrases (one-two words) of varying font sizes, which need to be positioned left-to-right according to a numerical parameter, and vertically so as not to overlap.

It's like a tag cloud, but there's information contained in the y-axis as well ("coolness" in this case - http://cool-wall.appspot.com)

How should I lay these out? I'm currently using a very messy series of DIVs like this:

<div style="position:absolute; top:150px;left:10px;right:10px;bottom:10px"> 

<!-- then, repeated, with different top, left and font-size values -->

  <div style="align:center; margin:0; border:none; padding:0; float:left; visibility:visible; position:absolute; top:21%; left:56%; font-size:11px"> 
    <div style="margin-top:0%; margin-right:50%; margin-bottom:0%; margin-left:-50%;"> 
      <a href="foo"><span style="display:inline"> &larr; </span></a> 
      <a href="bar"><span style="display:inline"> Buzz </span></a> 
      <span style="display:inline"> &rarr; </span> 
    </div> 
  </div>

  <!-- of course, followed by a close div -->

</div>

I use a stylesheet to extract some of those styles, and I realise that it's pretty poor CSS (and HTML)... but this was all I could hack together to do (almost) what I wanted to do. The main problem with the above (apart from it being confusing) is that I can't set the positioning so it doesn't overlap, because I don't know what size the font will be, nor how it will display onscreen.

Happy to use JavaScript to get it right. But I don't know where to start. Any tips?

Upvotes: 0

Views: 2676

Answers (3)

Steve Brewer
Steve Brewer

Reputation: 2100

The x-value is set on each one, you want to be as high on the page as possible (lowest y) as it can go without overlapping. Not too bad:

1) Render the container - position:relative; Render each item inside the container with "position:absolute; top:0; left:-1000; " - draw them all off screen.

2) One by one, move the element to it's needed x-coorinate and y=0; Check it with all previous render items to see if it collides, if it does, move it down one pixel until it doesn't collide:

var regions = [];
for(var i = 0; i < items.length; i++){
  var item = items[i];

  item.style.x = getX(item); // however you get this...
  var region = YAHOO.util.Dom.getRegion(item);
  var startingTop = region.top;
  for(var iReg = 0; iReg < regions.length; iReg++){
    var existingRegion = regions[iRegion];
    while(region.intersect(existingRegion)){
      region.top++;
      region.bottom++;
    }
    item.style.y = (region.top - startingTop) + 'px';
  }
}

It's important to just update the region and not actually move the dom node 1px at a time for performance reasons.

Put most important items first and they will render with more priority than items below them.

Upvotes: 0

Jason
Jason

Reputation: 52523

Don't position your elements absolutely. This is the reason they are falling on top of each other....

Upvotes: 0

Zoidberg
Zoidberg

Reputation: 10323

There is a javascript property on the dom object that will tell you the height of the tag if you have the width set. I believe its called clientHeight

alert(document.getElementById('myElement').offsetHeight);

Try that (also see http://www.webdeveloper.com/forum/archive/index.php/t-121578.html)

OR

Try this

<span style="margin-top:${randomNumber}px;margin-bottom:${randomNumber}">randomtext</span>
<span style="margin-top:${randomNumber}px;margin-bottom:${randomNumber}">randomtext</span>
..
<span style="margin-top:${randomNumber}px;margin-bottom:${randomNumber}">randomtext</span>

Have all your element just display inline, output them in random order, and then set random margin's on them. This could all be done with server side code (or javascript if you want it client side).

Upvotes: 1

Related Questions