5

According to specifications for height the element's containing box needs to have an explicit height in order for percentage height to work on the element (i.e. a numerical value of 100% height used on all parent containing boxes).

However why do the same rules not seem to apply for percentage widths? When I set a percentage width on an element with a containing box that has no explicit width, it still seems to change the width of the element. (see example)

.first {
    background-color: teal;
}
.second {
    background-color: gold;
    width: 30%;  /* the '.second' box becomes narrower! */
    height: 40%; /* <-- doesn't have any effect         */
}
<div class="first">
    ""
    <div class="second">
    ""
    </div>
</div>  
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
rrazd
  • 1,741
  • 2
  • 32
  • 47
  • So you want to know why you don't have to set a width for block level elements like the div? – arnolds Feb 05 '15 at 20:46
  • yes, how does the nested div with width 50% know what value it should take 50% of? Since the containing block has no explicit width set on it (i.e. no width 100% derived from the body and no explicit px width) – rrazd Feb 05 '15 at 20:50
  • That's because it's a block level element, all block level elements in HTML have a default width of 100% that's why they span across the width of the browser window. Inline elements like images, and links don't, they just extend to their contents length. – arnolds Feb 05 '15 at 20:57
  • 100% of what? If I make the body the containing box the .second does not fill 100% of the body as would be expected: .first { background-color: blue; width: 50% } .second { background-color: yellow; } – rrazd Feb 05 '15 at 21:12
  • of the parent element. http://jsfiddle.net/usvgfse2/1/ – arnolds Feb 05 '15 at 21:15

2 Answers2

16

Non-replaced block-level elements which are in normal flow take the width of their parent.

Well, that's a lie-to-children!

In order to understand what happens under the hood, we should start from how width of a non-replaced block-level element is calculated.

10.3.3 Block-level, non-replaced elements in normal flow

The following constraints must hold among the used values of the other properties:

'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block

[...] If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.

Due to the fact that the initial value of width property is auto, the width of a block-level element would be the same as its containing block.

<html> is a block-level element and it lives in the initial containing block.

The initial containing block is a rectangular box which takes the width of the viewport. Hence the width of <html> element would be equal to the width of the viewport.

On the other hand, the containing block of <body> element is generated by <html>. Therefore they would have equal widths as well.

<body> itself establishes a containing block for its block-level children. And that's why a <div> element in normal flow will take the width of the viewport.

W3C indicates it better:

With no positioning, the containing blocks (C.B.) in the following document:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
   <HEAD>
      <TITLE>Illustration of containing blocks</TITLE>
   </HEAD>
   <BODY id="body">
      <DIV id="div1">
      <P id="p1">This is text in the first paragraph...</P>
      <P id="p2">This is text <EM id="em1"> in the 
      <STRONG id="strong1">second</STRONG> paragraph.</EM></P>
      </DIV>
   </BODY>
</HTML>

are established as follows:

For box generated by    C.B. is established by
html                    initial C.B. (UA-dependent)
body                    html
div1                    body
p1                      div1
p2                      div1
em1                     p2
strong1                 p2

However that is not true for height of non-replaced block-level elements (which are still in normal flow!):

10.6.3 Block-level non-replaced elements in normal flow when 'overflow' computes to 'visible'

[...] If 'height' is 'auto', the height depends on whether the element has any block-level children and whether it has padding or borders.

[...] Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored, and relatively positioned boxes are considered without their offset).

The initial value of height is auto, therefore if the block-level element doesn't have any block-level children, padding or border, the computed value of height would be 0.

That's true even for <html> element.

Community
  • 1
  • 1
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
0

I think all block-elements has a 100% width if not anything else is specified. The height works differently, because if you don't set the height anywhere it just bases it's height on the total height of your content.

tomas
  • 245
  • 2
  • 10