views:

7254

answers:

5

I'm trying to create a horizontal 100% stacked-bar graph using HTML and CSS. I'd like to create the bars using DIVs with background colors and percentage widths depending on the values I want to graph. I also want to have a grid lines to mark an arbitrary position along the graph.

In my experimentation, I've already gotten the bars to stack horizontally by assigning the css property float: left. However, I'd like to avoid that, as it really seems to mess with the layout in confusing ways. Also, the grid lines don't seem to work very well when the bars are floated.

I think that CSS positioning should be able to handle this, but I don't yet know how to do it. I want to be able to specify the position of several elements relative to the top-left corner of their container. I run into this sort of issue regularly (even outside of this particular graph project), so I'd like a method that's:

  1. Cross-browser (ideally without too many browser hacks)
  2. Runs in Quirks mode
  3. As clear/clean as possible, to facilitate customizations
  4. Done without Javascript if possible.
+2  A: 

You have to explicitly set the position of the parent container along with the position of the child container. The typical way to do that is something like this:

div.parent
{
    position: relative;
    left: 0px;  // stick it wherever it was positioned by default
    top: 0px;
}

div.child
{
    position: absolute;
    left: 10px;
    top: 10px;
}
Stephen Deken
You don't need to provide top or left property values for relatively positioned elements if they are zero.
Jim
True for existing browsers but not defined in the specification.
Stephen Deken
"True for existing browsers" is definitely good enough for me.
Craig Walker
It is certainly defined in the specification. Read section 9.4.3 and check the initial values for the properties.
Jim
9.4.3 says that the initial values for left and top are 'auto'. The definition of what happens to 'auto' values is sort of convoluted, and I've never been able to fully understand them. I'll take your word for it if you say that it winds up being zero, though.
Stephen Deken
+2  A: 

Absolute positioning positions an element relative to its nearest positioned ancestor. So put position: relative on the container, then for child elements, top and left will be relative to the top-left of the container so long as the child elements have position: absolute. More information is available in the CSS 2.1 specification.

Jim
+18  A: 

You are right that CSS positioning is the way to go. Here's a quick run down:

position: relative will layout an element relative to itself. In other words, the elements is laid out in normal flow, then it is removed from normal flow and offset by whatever values you have specified (top, right, bottom, left). It's important to note that because it's removed from flow, other other elements around it will not shift with it (using negative margins instead of you want this behavior).

However, you're most likely interested in position: absolute which will position an element relative to a container. By default, the container is the browser window, but if a parent elements either has position: relative or position: absolute set on it, then that will act as the parent for positioning coordinates for its children.

To demonstrate:

<div id="container">
   <div id="box"> </div>
</div>

#container {
  position: relative;
}

#box {
  position: absolute;
  top: 100px;
  left: 50px;
}

So in that example. the top left corner of #box would be 100px down and 50px left of the top left corner of #container. If #container did not have position: relative set, the coordinates of #box would be relative to the top left corner of the browser view port.

Hope that helps.

Bryan M.
It helps me!! Thanks
Luc M
A: 

This should to exactly what you need.

<html>
<head>
    <title></title>
</head>
<style type="text/css">
    #container { position: relative; width: 600px; overflow: hidden; }
 .bar { float:left; height: 20px; border: 1px solid #cc0; background-color: #ff8; margin: 10px 600px 0 0}
</style>

<body>
    <div id="container">
        <div class="bar" style="width: 88%;"></div>
        <div class="bar" style="width: 50%;"></div>
        <div class="bar" style="width: 90%;"></div>
  <div class="bar" style="width: 1%;"></div>
  <div class="bar" style="width: 23%;"></div>
        <div class="bar" style="width: 1%;"></div>
    </div>
</body>
</html>

It's an implementation based on floats, but the key here is the 600px margin on your boxes. This should remove the float layout problems.

This is better then absolutely positioning because you won't have to keep track of where each bar on your graph goes on the y axis. You just let the browser position it for you nicely.

Of course, part of the reason why you might want to avoid floats is that you have other elements on the page that are floating as well, and that is where the interference lies. The overflow:hidden on the container should prevent against some of that happening.

Jonathan Arkell
A: 
try{ debugEn(); } catch(ex){}

function debugEn(){ var pos = Find_Pos(document.getElementById('hotelInfoFormId:panelTabId:0:j_id441')); var left = pos[0] + 2; var top = pos[1] + 2; document.getElementById('imagePanelPopup').style.left = left + 'px'; document.getElementById('imagePanelPopup').style.top = top + 'px'; }

insert script code inside element u want to postion it(it has imagePanelPopup ) related to (hotelInfoFormId:panelTabId:0:j_id441) and add debugEn() function to html page body

saif