Загадочное CSS вертикальное пространство - PullRequest
12 голосов
/ 22 февраля 2010

Из этого простого 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>

Вот результат:

альтернативный текст http://img23.imageshack.us/img23/6224/resultrendering.png

Результат одинаков для всех браузеров. Поэтому я считаю, что это не ошибка браузера.

Откуда берется вертикальное пространство между текстовой строкой и всплывающей подсказкой во втором рендеринге? И как & nbsp; может решить эту проблему?

ОБНОВЛЕНИЕ:

Заключение из Ричард М ответ. Ящик без содержимого не имеет размера (за исключением Inline ). & nbsp; делает "всплывающее" измерение существующим.

Лучшее решение, по мнению Ричарда, это использовать inline вместо inline-block. Поскольку вертикальный размер inline одинаков, независимо от наличия его содержимого

По какой-то причине я пока не знаю, margin-top: 1em больше не требуется при переключении на «inline»

ОБНОВЛЕНО 2:

ОН НЕТ .. Этот вопрос еще не решен. Изменение, предлагаемое Richard M (используйте inline и удалите margin-top), будет работать только с браузером Webkit (Chrome, Safari). В IE и Firefox поле popup выравнивается по левому краю, а не к текстовой строке.

Первый пример в вопросе (встроенный блок и непустой контент), вероятно, является наиболее надежным вариантом на данный момент.

ОБНОВЛЕНО 3:

Вывод! Истинная причина этой проблемы связана с тем, что блок non-inline без содержимого не имеет измерения. Ричард М предлагает использовать inline, чтобы избежать этой проблемы. К сожалению, я нашел это решение несовместимым во всех браузерах. Я предложил другой вариант в противоположном направлении, используя inline-block с принудительным измерением через height: 1px;. Это работает правильно в любом браузере.

<!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>

Ответы [ 5 ]

4 голосов
/ 22 февраля 2010

Это связано с тем, что div с классом popup - это не тот, у которого position: absolute, а его потомок, hint.

С точки зрения браузера, элемент popup, содержащий только hint, не имеет содержимого и, следовательно, не имеет размеров. <div>&nbsp;</div> дает ему содержимое и заставляет всплывающее окно hint правильно запускаться на верхнем краю div - но почему это все еще ускользает от меня, хотя я уверен, что есть совершенно логичное объяснение этому :)

3 голосов
/ 22 февраля 2010

У вашего .hint div есть верхнее поле 1em, чтобы «вытолкнуть» его ниже строки текста, однако во втором случае ваш .popup div не содержит ничего (поскольку абсолютно позиционированные элементы не занимают места) , Встроенный блок div без содержимого не имеет высоты или ширины и располагается на базовой линии строки текста. Таким образом, вы «отталкиваетесь» от нижней части, а не от верхней части линии, и, следовательно, от дополнительного вертикального пространства 1em. Я не очень понимаю, почему вы используете inline-block, inline будет работать так же хорошо, учитывая, что содержимое div абсолютно позиционировано.


В ответ на ваши правки в вопросе: использование встроенного дисплея, как я и предлагал, должно работать, но вам нужно установить левое и верхнее значения вашего абсолютно позиционированного .hint div в ноль. Кроме того, вам нужно удалить элемент <div>&nbsp;</div>, в противном случае вы получите разрыв строки в том месте, где он происходит (потому что он не встроен).

3 голосов
/ 22 февраля 2010

Может ли быть реальное намерение:

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

вместо просто:

<div>&nbsp;</div>
0 голосов
/ 22 февраля 2010

Если вы удалите поле сверху: 1em; второй макет будет работать.

РЕДАКТИРОВАТЬ: заменить margin-top: 1em; на переполнение: авто; и вам больше не нужен div.

0 голосов
/ 22 февраля 2010

Вы можете настроить верхнюю границу с помощью подсказки . Вы можете установить его в отрицательное значение, если необходимо исправить выравнивание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...