开发者

Mysterious CSS vertical space

From this simple html.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>Hello</title>
  <style type="text/css" media="screen">
    .t1 {
      padding: 0px;
      margin: 0px;
    }
    .popup {
      display: inline-block;
      position: relative;
      width: 0px;
      padding: 0px;
      margin-left: -0.5em;
    }
    .hint {
      position: absolute;
      z-index: 1;
      width: 20em;
      background-color: white;
      border: 1px solid green;
      padding: 0.5em;
      margin-top: 1em;
    }
    .list {
      padding: 0px;
      padding-left: 1em;
      margin: 0px;
    }
  </style>
</head>

<body>

<!-- properly layout -->
<div style="height: 10em;">
  <span class="t1">MyObject o = www.mycompany.project.ObjectFactory.</span>
  <div class="popup">
    <div class="hint">
      <ul class="list">
        <li>NewSimpleObject(int x);</li>
        <li>NewComplexObject(int x, int y);</li>
        <li>NewComplicateObject(int x, int y, intz);</li>
      </ul>
    </div>
    <div>&nbsp;</div>  <!-- no idea why, but ending space is required for proper layout -->
  </div>
</div>

<!-- incorrect layout -->
<div style="height: 10em;">
  <span class="t1">MyObject o = www.mycompany.project.ObjectFactory.</span>  
  <!-- mysterious vertical space appear here -->
  <div class="popup">
    <div class="hint">
      <ul class="list">
        <li>NewSimpleObject(int x);</li>
        <li>NewComplexObject(int x, int y);</li>
        <li>NewComplicateObject(int x, int y, intz);</li>
      </ul>
    </div>
    <!-- <div>&nbsp;</div>  -->
  </div>
</div>

</body>

</html>

Here is the result:

alt text http://img23.imageshack.us/img23/6224/resultrendering.png

The result is similar across browser. So I believe this is not a browser bug.

Where does the vertical space between the text-line and the popup-hint in the second rendering come from ? And how can the <div>&nbsp;</div> solve this problem ?

UPDATED:

Conclude from Richard M answer. Box with no content has no dimension (with an exception of Inline). The <div>&nbsp;</div> make "popup" dimension exists.

The better solution, according to Richard, is to use inline instead of inline-block. Since the vertical dimension of inline is the same regardless of its content existence

For some reason I don't know yet, the margin-top: 1em is no longer necessary when switch to "inline"

UPDATED 2:

OH NO.. This issue cannot be concluded yet. The change that Richard M suggest (use inline and remove margin-top) would work only with Webkit Browser (Chrome, Safari) On IE and Firefox , the popup box align to the left rather than to the text line.

The first sample in the question (inline-block & non-empty content) is probably the most reliable option for now.

UPDATED 3:

Conclusion ! The true cause of this issue originate from the fact that non-inline block with no content has no dimension. Richard M suggest using inline to avoid this issue. Unfortunately, I've found this solution inconsistence across browsers. I came up with another option in opposite direction, using inline-block with forced dimension via height: 1px; This work correctly in any browser.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>Hello</title>
  <style type="text/css" media="screen">
    .t1 {
      padding: 0;
      margin: 0;
      width: 0em;
    }
    .popup {
      display: inline-block;
      padding: 0;
      margin: 0; 
      position: relative;
      width: 0;
      height: 1px;  <!-- force vertical dimension -->
    }
    .hint {
      position: absolute;
      z-index: 1;
      padding: 0;
      margin: 0;
      margin-top: 1px;  <!-- compensate for the setup dimension -->
      width: auto;
      white-space: nowrap;
      background-color: white;
      border: 1px solid green;
    }
    .list {
      padding: 0;
      padding-left: 1em;
 开发者_如何学运维     margin: 0.5em;
    }
  </style>
</head>

<body>

  <!-- properly layout -->
  <div style="height: 10em;">
    <span class="t1">MyObject o = www.mycompany.project.ObjectFactory.</span><!-- 
      whitespace is not welcome
    --><div class="popup">
      <div class="hint">
        <ul class="list">
          <li>NewSimpleObject(int x);</li>
          <li>NewComplexObject(int x, int y);</li>
          <li>NewComplicateObject(int x, int y, int z);</li>
        </ul>
      </div>
    </div><!--
      whitespace is not welcome
    --><span>(1, 2, ...</span>
  </div>

</body>

</html>


It has to do with the fact that the div with the class popup is not the one with the position: absolute, but its child, hint.

From the browser's perspective, the popup div, when containing only hint, has no content, and thus, no dimensions. The <div>&nbsp;</div> gives it content and causes the hint popup to start properly on the top edge of the div- but why that is, still escapes me, even though I'm sure there is a perfectly logical explanation for it :)


Your .hint div has a 1em top margin to "push" it down below the line of text, however in your second instance your .popup div doesn't contain anything (as absolutely positioned elements take up no space). An inline-block div with no content has no height or width and sits on the baseline of a line of text. So, you are "pushing" off the bottom rather than the top of the line, and hence the additional 1em vertical space. I don't really understand why you're using inline-block, inline would work just as well given the content of the div is absolutely positioned.


In response to your question edits: Using display inline as I suggested should work, but you need to set the left and top values of your absolutely positioned .hint div to zero. Also, you'll need to remove your <div>&nbsp;</div> element otherwise you'll end up with a line break where it occurs (because it's not inline).


Could it be the real intention is:

<div style="clear:both;"></div>

instead of just:

<div>&nbsp;</div>


You can adjust your margin-top on the hint. You can set it to a negative value if needed to correct the alignment.


If you delete the margin-top: 1em; the second layout will work.

EDIT: replace margin-top: 1em; with overflow: auto; and you don't need the div anymore.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜