82

Is there a way, without using JavaScript, to cause child divs to extend to the borders of their parent, without exceeding those borders, when you cannot know beforehand the size of the parent div?

Below is a sample markup/style demonstrating my issue. If you load it into a browser, you will see that #two and #three extend outside their parent, #one, and cause scrollbars to appear.

My issue is not so much the scrollbars but that I need to learn how to tell the child divs to occupy the width or height remaining to them rather than the full height or width of the parent.

<html>
   <head>
      <style>
         html,
         body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
         }
         .border {
            border: 1px solid black;
         }
         .margin {
            margin: 5px;
         }
         #one {
            width: 100%;
            height: 100%;
         }
         #two {
            width: 100%;
            height: 50px;
         }
         #three {
            width: 100px;
            height: 100%;
         }
      </style>
   </head>
   <body>
      <div id="one" class="border">
         <div id="two" class="border margin"></div>
         <div id="three" class="border margin"></div>
      </div>
   </body>
</html>

Harshil Modi
  • 397
  • 3
  • 8
  • 15
Tim Sheiner
  • 3,253
  • 4
  • 27
  • 22

11 Answers11

28

I had a similar problem, but in my case, I have content in my div that height-wise will exceed the boundaries of the parent div. When it does, I want it to auto-scroll. I was able to accomplish this by using

.vscrolling_container { height: 100%; overflow: auto; }
Alfred
  • 21,058
  • 61
  • 167
  • 249
meem
  • 289
  • 3
  • 2
24

you could use display: inline-block;

hope it is useful.

codingrose
  • 15,563
  • 11
  • 39
  • 58
a b
  • 265
  • 2
  • 2
  • I've tried this but this doesn't solve #two #three extending beyond the boundary of #one. Instead, adding 'overflow' to the style of #one solved the issue. – goldenriver4422 Sep 15 '22 at 06:50
10

In your example, you can't: the 5px margin is added to the bounding box of div#two and div#three effectively making their width and height 100% of parent + 5px, which will overflow.

You can use padding on the parent Element to ensure there's 5px of space inside its border:

<style>
    html, body {width:100%;height:100%;margin:0;padding:0;}
    .border {border:1px solid black;}
    #one {padding:5px;width:500px;height:300px;}
    #two {width:100%;height:50px;}
    #three {width:100px;height:100%;}
</style>

EDIT: In testing, removing the width:100% from div#two will actually let it work properly as divs are block-level and will always fill their parents' widths by default. That should clear your first case if you'd like to use margin.

ajm
  • 19,795
  • 3
  • 32
  • 37
  • 1
    Or, stick with percentages: using a percentage margin and a percentage width/height will also do the trick as you're working with the same "units." That 100% height is going to get you, though, since there's another child in there using up part of the parents' height. – ajm Jul 08 '09 at 14:14
  • That doesn't quite work, the height: 100% in #three will always overflow the parent container. – Matt Bridges Jul 08 '09 at 14:17
  • Yeah, as I said in my comment, the 100% height is going to overflow every time. Something like a 2% margin on #two and #three, a 10% height on #two and an 82% height on #three might do the trick. – ajm Jul 08 '09 at 15:34
  • As noted, this doesn't address issue of child div that is using vertical space, and thus pushing other child out of parent. – Tim Sheiner Jul 08 '09 at 17:25
7

There are two techniques commonly used for this:

  1. Absolute Positioning
  2. Table Styles

Given the HTML you provided here is the solution using Absolute positioning:

body #one {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  width: auto;
  height: auto;
}
body #two {
  width: auto;  
}
body #three {
  position: absolute;
  top: 60px;
  bottom: 0;
  height: auto;
}
<html>
<head>
<style>
html, body {width:100%;height:100%;margin:0;padding:0;}
.border {border:1px solid black;}
.margin { margin:5px;}
#one {width:100%;height:100%;}
#two {width:100%;height:50px;}
#three {width:100px;height:100%;}
</style>
</head>
<body>
 <div id="one" class="border">
  <div id="two" class="border margin"></div>
  <div id="three" class="border margin"></div>
 </div>
</body

You can always just use the table, tr, and td elements directly despite common criticisms as it will get the job done. If you prefer to use CSS there is no equivalent for colspan so you will likely end up with nested tables. Here is an example:

html, body {
  height: 100%;
  margin: 0;
  padding: 0;
  width: 100%;
}
#one {
  box-sizing: border-box;
  display: table;
  height: 100%;
  overflow: hidden;
  width: 100%;
  border: 1px solid black;
}
#two {
    box-sizing: border-box;
    display: table;
    height: 50px;
    padding: 5px;
    width: 100%;
}
#three {
  box-sizing: border-box;
  display: table;
  height: 100%;
  padding-bottom: 60px;
  padding-left: 5px;
  
}
#four {
  display: table-cell;
  border: 1px solid black;
}
#five {
  display: table-cell;
  width: 100px;
  border: 1px solid black;
}
#six {
  display: table-cell;  
}
<html>
 <div id="one">
     <div id="two">
            <div id="four"></div>
        </div>
        <div id="three">
            <div id="five"></div>
            <div id="six"></div>
        </div>
 </div>
  </html>
Ryan
  • 7,499
  • 9
  • 52
  • 61
4

For width it's easy, simply remove the width: 100% rule. By default, the div will stretch to fit the parent container.

Height is not quite so simple. You could do something like the equal height column trick.

html, body {width:100%;height:100%;margin:0;padding:0;}
.border {border:1px solid black;}
.margin { margin:5px;}
#one {width:500px;height:300px; overflow: hidden;}
#two {height:50px;}
#three {width:100px; padding-bottom: 30000px; margin-bottom: -30000px;}
Matt Bridges
  • 48,277
  • 7
  • 47
  • 61
  • 1
    This one also truncates the long child div, but doesn't make it shorten to fit inside parent with desired margin at bottom. – Tim Sheiner Jul 08 '09 at 17:31
2

you could use inherit

#one {width:500px;height:300px;}
#two {width:inherit;height:inherit;}
#three {width:inherit;height:inherit;}
Silfverstrom
  • 28,292
  • 6
  • 45
  • 57
2

Make sure the outermost div has the following CSS properties:

.outer {
  /* ... */
  height: auto;
  overflow: hidden;
  /* ... */
}
  • 1
    When I tried this, instead of fitting in, the child divs are getting cut out, any other better suggestions perhaps? – Surya Dec 01 '18 at 13:10
2

I think I have the solution to your question, assuming you can use flexbox in your project. What you want to do is make #one a flexbox using display: flex and use flex-direction: column to make it a column alignment.

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.border {
  border: 1px solid black;
}

.margin {
  margin: 5px;
}

#one {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

#two {
  height: 50px;
}

#three {
  width: 100px;
  height: 100%;
}
<html>

<head>
</head>

<body>
  <div id="one" class="border">
    <div id="two" class="border margin"></div>
    <div id="three" class="border margin"></div>
  </div>
</body>

</html>
Aman
  • 59
  • 2
  • 12
1

If I've understood you correctly, the easiest method is to float the children. For example:

#one { width: 500px; height: 1%; overflow: hidden; background: red; }
#two { float: left; width: 250px; height: 400px; background: aqua; }
#two { float: left; width: 250px; height: 200px; background: lime; }

Setting a dimension (height/width) and overflow to auto or hidden on the parent element causes it to contain any floated child elements.

Note that overflow:hidden; can occasionally cause problems with content getting cut off, in which case you might want to try this alternative method:

http://www.positioniseverything.net/easyclearing.html

Olly Hodgson
  • 15,076
  • 3
  • 40
  • 60
  • This forces you to set the height of the contained elements as opposed to setting the height of the container and making the contained elements stretch to fit. – Matt Bridges Jul 08 '09 at 14:13
  • This sort of works, but truncates bottom of long child, doesn't make child 'fit' inside parent – Tim Sheiner Jul 08 '09 at 17:28
1

For closure, I think the answer to this question is that there is no solution. The only way to get the behavior I want is with javascript.

Tim Sheiner
  • 3,253
  • 4
  • 27
  • 22
  • See my answer. I actually provide two different ways to do it. – Ryan Sep 14 '16 at 17:10
  • Often tables can easily do what divs require hoop-jumping to get accomplished. Unfortunately, divs got into CSS very poorly thought out. – fyngyrz Nov 11 '16 at 03:12
0

If you want the child divs to fit the parent size, you should put a margin at least of the size of the child borders on the child divs (child.margin >= child.bordersize).

For this example, just remove the width:100%; and the height:100% in #one and remove the width:100% in #two. It should be something like this:

html, body {width:100%; height:100%; margin:0; padding:0;}    
.border {border:1px solid black;}   
.margin {margin:5px;}  
\#one {}   
\#two {height:50px;}    
\#three {width:100px; height:100%;}
LPL
  • 16,827
  • 6
  • 51
  • 95
Wade
  • 73
  • 4