10

JSFIDDLE

EDIT: Trying to achieve the opposite of this.
(instead of 2 fixed-width divs on the sides and one fluid-width div in the middle,
I'm trying to get 2 fluid-width divs on the sides and one div centered in the middle)

I have 3 divs: A, B, and C.

B needs to sit centered between A and C.

What I need to do

What I'm currently doing is pretty much matching what's going on above. But, if A, B, and C's container has an odd width, some browsers are rounding A and C's widths down and others up (leaving C 1px too long and 1px too short, respectively).

notice the extra pixel to the right of C

notice the space to the right of C is a pixel thinner.

I don't care how many nested divs I need, but I've been spending way too much time on this! If someone already has a sure-fire solution to this problem, please share!

notes:
- A, B, and C's parent can't have overflow hidden.
- A, B, and C can't overlap (they have translucent png's)

This is my starting point: JSFIDDLE

MicronXD
  • 2,190
  • 16
  • 24

5 Answers5

7

Here are two ways that work, both with caveats (warning, both require a wrapper):

HTML

<section class="wrapper">
    <div class="column" id="a"></div>
    <div class="column" id="b"></div>
    <div class="column" id="c"></div>
</section>​​​​​​​​​​​

Base CSS

.column {
    height: 3em;
}

#a {
 background-color: red;   
}
#b {
 background-color: green;
}
#c {
 background-color: blue;   
}

#b {
  width: 50px;   
}

CSS3 Approach:

.wrapper {
    display:box;
    box-orient:horizontal;
    box-align:stretch;    
}

#a, #b {
    box-flex:1.0;
}

Caveat: Only supported (so far) in Firefox and Webkit (Chrome/Safari), both requiring prefixed rules. The above is what it will be someday.

Here is a demo with prefixes: http://jsfiddle.net/crazytonyi/cBVTE/

Table-Display approach

.wrapper {
    display: table;
    width: 100%;
    table-layout: fixed;

}    
.column {
    display: table-cell;
}

Caveats: IE didn't start supporting this display type until 7 or 8. On the other hand, worrying about users on older versions of IE is like worrying about people who still turn off cookies and javascript. Either they catch up or get used to pages breaking. End the pandering!

Here's a demo using the above: http://jsfiddle.net/crazytonyi/kM46h/

In both cases, no floats or positioning needed, just willingness to give the middle finger to older browsers. How old depends on which method you choose.

Anthony
  • 36,459
  • 25
  • 97
  • 163
  • You, sir, are a gentleman and a scholar. Thank you for your solutions! Much more elegant than the one I posted as the answer ([My JSFiddle](http://jsfiddle.net/ruMqY/7/). Have an upvote and an accepted answer, my friend. :) – MicronXD May 15 '12 at 08:00
  • 1
    Everyone please upvote this answer! The others don't handle browser whole-pixel rounding. – MicronXD May 15 '12 at 08:02
  • 1
    Box flex have very pure browser support caniuse.com/#feat=flexbox. It fails on ie9, opera, opera mobile and in all major browser this property has partial support. For support detection use modernizr – Vladimir Starkov May 15 '12 at 08:44
  • @matmuchrapna:+1 for modernizr plug. – Anthony May 15 '12 at 16:34
0

EDIT: Please use Anthony's solution! It meets all of the requirements without any terribly hacky CSS! If you do need to support older browsers, feel free to use my solution (but, srrsly, Anthony's solution is perfect for most cases).


I don't know how I haven't tried this solution yet, but this seems to work even better than this question's accepted answer! No rounding!

solved!

If we think of the rounded 50% as a value (X) and constant width of B as value Y, then we need:

width of A = X
width of C = 100% - X

I decided to use this as my structure:

<container>
  <a></a>
  <b></b>
  <c_holder>
    <c>
    </c>
  </c_holder>
</container>

Q. How can we get C to have a width of container_width - X?
A. We give C a container called c_holder with width 100% and give C a left offset of X (50%).

forget B for now...

now we have 2 divs next to eachother... each roughly 50% but adding up to exactly 100%.

Throw all of these into a container, and give this container a margin-right of Y (the width of the B div). now we have A and C next to eachother, but taking up 100% - Y of the width.

give c_holder a left offset of Y and drop B in between A and c_holder. apply a left float on A and B.

now A's width is X, B's width is Y, C's total left offset is X + Y, and C's visible width is 100% of the container - X - Y.

kinda funky, but it's worked perfectly in IE7, Chrome, and Safari. I'll test FF later.

Community
  • 1
  • 1
MicronXD
  • 2,190
  • 16
  • 24
  • My answer doesn't require nested wrappers. Your approach may work across more browsers. Lemme know. – Anthony May 15 '12 at 07:17
  • I didn't see your answer until just now... It's awesome.. thank you so much! I got all caught up in supporting as many browsers as possible (symptom of working in the corporate world where people still use IE6 from time-to-time u_u). Seriously... You made my night :P – MicronXD May 15 '12 at 08:07
0

i think you have to use like this..

HTML

<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>

CSS

.a
{
width:50%;
height:25px;
background-color:#0F0;
float:left  
}
.b
{
width:13px;
height:25px;
background-color:#FFF;
margin-left:-6px;
float:left; 
position:relative;
z-index:99;
}
.c
{
width:50%;
height:25px;
background-color:#C33;
margin-left:-7px;
float:left; 
}
</style>
cgvector
  • 931
  • 1
  • 10
  • 13
  • That breaks the rule: - A, B, and C can't overlap. This solution would have B overlap A and C. Thanks for trying though. – MicronXD May 15 '12 at 05:47
0
<style>

.a{ width:50%; height:25px; background-color:#0F0; float:left }
.b{ width:13px; height:25px; background-color:#FFF; float:left;
    position:relative; left:51%;}
.c{ width:50%; height:25px; background-color:#C33; float:right; }

</style>
Spudley
  • 166,037
  • 39
  • 233
  • 307
Hassaan
  • 328
  • 1
  • 2
  • 9
0

demo on dabblet.com:

http://img838.imageshack.us/img838/6116/cff430b799254087b6ec991.png

html:

<div id="main">
    <div class="half left">
        <div>
            <div id="a" class="col"> </div>
         </div>
    </div>
    <div class="half right">
        <div>
            <div id="c" class="col"> </div>
         </div>
    </div>
    <div id="b" class="col"> </div>
</div>

css:

#main {
    height: 40px;
    width: auto;
    border: 1px solid #cfcfcf;
    position: relative;
}

.half {
    width: 50%;
    height: 100%;
    position: absolute;
    top: 0;
}

.half.left { left: 0; }
.half.right { right: 0; }

.half > div {
    height: 100%;
    padding:0 8px;
}

.half.left > div { padding-left: 7px; }
.half.right > div { padding-right: 7px; }

.col {
    height: 100%;
    margin-top: 3px;
}

#a,
#c {
    background-color: green;
}

#b {
    background-color: red;
    margin-left: auto;
    margin-right: auto;
    width: 14px;
}

update: updated with no overlaping

Vladimir Starkov
  • 19,264
  • 8
  • 60
  • 114
  • close. unfortunately, your solution doesn't handle the rounding issues. outside of the widths of the container, A, and B, nothing should change. the spacing between your A & B and B & C jitters as the browser rounds 50% of the total width to the nearest pixel. – MicronXD May 15 '12 at 07:55
  • is it possible for you that #b has width equal to 14px ? – Vladimir Starkov May 15 '12 at 08:01
  • sure, but even still, there's the overlapping issue for one, and if the parent container has an odd (non-even) width, you will still run into whole-pixel rounding issues. Thanks for posting your solution, though. – MicronXD May 15 '12 at 08:04
  • chrome, firefox ok, just opera failed on odd container's width =( – Vladimir Starkov May 15 '12 at 08:21