tags:

views:

392

answers:

3

I am sure this problem has been asked before but I cannot seem to find the answer.

I have the following markup:

<div id="foo">
    <div id="bar">
        here be dragons
    </div>
</div>

My desire is to make foo's width = 600px (width: 600px;) and to make bar have the following behaviors:

padding-left: 2px;
padding-right: 2px;
margin-left: 2px;
margin-right: 2px;
outerWidth: 100%;

In other words instead of setting width of bar to "592px" I would like to set the outer width of bar to 100% so that it is computed to 592px. The importance here is that I can change foo's width to 800px and bar will calculate when rendered instead of me having to do the math for all these instances manually.

Is this possible in pure css?

Some more fun with it:

  • What if #bar is a table?
  • What if #bar is a textarea?
  • What if #bar is an input?

  • What if #foo is a td? (does this change the problem or the problem is identical?)


So far the table#bar, input#bar has been discussed. I have not seen a good solution for textarea#bar. I Think a textarea with no border/margin/pading with a div wrap might work with the div styled to work as borders for the textarea.

+2  A: 

almost there, just change outerWidth: 100%; to width:auto; (outerWidth is not a CSS property)

alternatively, apply the following styles to bar:

width:auto; display:block;
Rowan
That wont work if he is setting padding an margin on `bar` because the will be added to the 100% effectively making `bar` wider than its parent `foo`.
prodigitalson
yeah, I answered that one too fast ;P
Rowan
Wait a second. So if I set the width property to anything, it will bleed through? width: auto is not the solution, rather not setting width at all is?
Dmitriy Likhten
yeah, that's right. Any element that has `display:block;` (also known as a block level element) will adopt this behavior. a DIV element has `width:auto;` and `display:block;` set by default.
Rowan
+6  A: 

EDIT:

Well those three different elements all have different redndering rules haha.

So for:

table#bar you need to set the width to 100% otherwise it will be only be as wide as it determines it needs to be. However, if the table rows total width is greater than the width of bar it will expand to its needed width. IF i recall you can counteract this by setting display: block !important; though its been awhile since ive had to fix that. (im sure someone will correct me if im wrong).

textarea#bar i beleive is a block level element so it will follow the rules the same as the div. The only caveat here is that textarea take an attributes of cols and rows which are measured in character columns. If this is specified on the element it will override the width specified by the css.

input#bar is an inline element, so by default you cant assign it width. However the similar to textarea's cols attribute, it has a size attribute on the element that can determine width. That said, you can always specifiy a width by using display: block; in your css for it. Then it will follow the same rendering rules as the div.

td#foo will be rendered as a table-cell which has some craziness to it. Bottom line here is that for your purposes its going to act just like div#foo as far as restricting the width of its contents. The only issue here is going to be potential unwrappable text in the column somewhere which would make it ignore your width setting. Also all cells in the column are going to get the width of the widest cell.


Thats the default behavior of block level element - ie. if width is auto (the default) then it will be 100% of the inner width of the containing element. so in essence:

#foo {width: 800px;}
#bar {padding-left: 2px; padding-right: 2px; margin-left: 2px; margin-right: 2px;}

will give you exactly what you want.

prodigitalson
Hey, thanks. Also having fun with tables deciding to bleed though anyways. I assume tables have the same behavior as the divs?
Dmitriy Likhten
@Dimitry: No they have special rules that render them more like `inline-block` than `block` elements. Note though that i said **more like** not **same as** :-) What youre probably experiencing is that unless otherwise defined they will generally expand to accommodate all the columns which can be really annoying if some of the headers/cells have long unwrappable text in them.
prodigitalson
Thanks for helping :) Let me update the question a bit to give a much more complete overview of the problems and hopefully all the workarounds can be listed in one section.
Dmitriy Likhten
I've been experimenting with the div#foo table#bar and setting width: 100% on table#bar will indeed expand the table, but the borders/margins of the table will bleed through div#foo. Setting the table to display: block is not good since it screws up other aspects of the table rendering such as the row's width handling.textarea#bar will not expand when width is set to auto or not set.
Dmitriy Likhten
for `textarea#bar` you should be able to set that to `display: block` with little adverse effect. As far as the table, I know ive used some sort of solution/mitigation for that in the past but i dont recall what it was at the moment. However i will say that i generally dont set "margins" on a table but rather wrap it in a div with padding/margins... this could be #foo itself or another div used jsut to apply this type of spacing. Also you can do to counteract the border issue to to apply the borders only to the first/last cell in a row/the cells in the first/last row
prodigitalson
`table#bar` - The div wrapping will solve the issue. Thanks.|`textarea#bar` - `display:block` not doing it.
Dmitriy Likhten
A: 

So after research the following is discovered:

For a div#bar setting display:block; width: auto; causes the equivalent of outerWidth:100%;

For a table#bar you need to wrap it in a div with the rules stated below. So your structure becomes:

<div id="foo">
 <div id="barWrap" style="border....">
  <table id="bar" style="width: 100%; border: 0; padding: 0; margin: 0;">

This way the table takes up the parent div 100%, and #barWrap is used to add borders/margin/padding to the #bar table. Note that you will need to set the background of the whole thing in #barWrap and have #bar's background be transparent or the same as #barWrap.

For textarea#bar and input#bar you need to do the same thing as table#bar, the down side is that by removing the borders you stop native widget rendering of the input/textarea and the #barWrap's borders will look a bit different than everything else, so you will probably have to style all your inputs this way.

Dmitriy Likhten