Абсолютно позиционированные родительский элемент и float: правый дочерний элемент растягивается

В IE6, IE7 и FF2 .outer div ниже растягивается до правого края документа. Вот полный тестовый пример:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <style>
  .outer { position:absolute; border:1px solid red; }
  .outer .floater { float:right; }
  </style>
</head>
<body>
  <div class="outer">
      <div class="floater">Lorem ipsum</div>
  </div>
</body>

Насколько я понимаю position:absolute, внешний div должен быть удален из потока документа и (без указания ширины) должен занимать минимальное пространство, необходимое для отображения его содержимого. Однако float:right на любом дочернем элементе нарушает это.

Ожидаемый результат (IE8, FF3 +, Chrome 2+, Safari 4, Opera 9+):

Ожидаемый результат - IE8, FF3 +, Chrome 2+, Safari 4, Opera 9 +

Фактический выход (IE6, IE7, FF2):

Фактический вывод - IE6, IE7, FF2

Как сделать так, чтобы внешний div не растягивался? Это происходит только в IE6, IE7 и Firefox 2.

Требования:

  • .outer не может иметь width набор (его необходимо оставить как "auto")
  • .outer должен оставаться в абсолютном положении
  • .floater должен оставаться смещенным вправо

Обновление:

Я воспроизвел поведение как "реальный" пример с помощью диалога jQuery. Характеристики такие же:

  1. Существует абсолютно позиционированный div (т.е. контейнер диалога, jQuery-UI создает его)
  2. Div из 1) имеет width="auto"
  3. Внутри этого диалогового окна есть элемент, плавающий вправо.

См. здесь. Опять же, IE6, IE7 и FF2 - единственные проблемные браузеры.

Это воспроизводит условия внутри моего приложения. Я попытался свести проблему к тому, что вы видите выше в этом обновлении, но мне кажется, что люди могут использовать реальный пример, в котором мои требования имеют смысл. Я надеюсь, что сделал это.


person Roatin Marth    schedule 08.10.2009    source источник
comment
есть ли внешние координаты или это не имеет значения?   -  person Dave    schedule 09.10.2009
comment
@ Дэйв: Да, на практике для .outer определены left и top. Однако это не влияет на поведение (т.е. ошибка присутствует с координатами или без них).   -  person Roatin Marth    schedule 09.10.2009
comment
Откуда берутся ваши требования? Они сами себя навязывают? После некоторых экспериментов я думаю, что лучше всего переписать html.   -  person idrumgood    schedule 09.10.2009
comment
@idrumgood: требования устанавливаются самостоятельно, однако разметка существует во многих местах, поэтому я бы предпочел исправить это, используя только css. Сказав это, если у вас есть предложение по изменению разметки, которое по-прежнему удовлетворяет требованиям, я был бы благодарен за это.   -  person Roatin Marth    schedule 09.10.2009
comment
У вас есть пример проблемы? Похоже, вы решили, каким должно быть решение, и теперь пытаетесь найти способ его реализовать. Может быть, в такой ситуации хорошо сделать шаг назад и сначала изучить проблему?   -  person codeinthehole    schedule 17.11.2009
comment
@codeinthehole: сначала изучите проблему ?? Как ты думаешь, что я делаю? Посмотрите на вопрос еще раз. Знаете ли вы, сколько времени потребовалось, чтобы сузить ошибку / поведение до этого одного простого примера? Какое-то время. Итак, да, я изучил проблему.   -  person Roatin Marth    schedule 20.11.2009
comment
@codeinthehole: я добавил пример.   -  person Roatin Marth    schedule 20.11.2009


Ответы (10)


Приносим извинения за отрицательный ответ, но я не думаю, что есть способ обойти это. Реализация CSS для этих старых браузеров просто неверна, когда дело доходит до случая, который вы описали, и я не верю, что есть какой-либо способ обойти это с помощью других свойств CSS в рамках ограничений, которые вы нам дали. В качестве ограниченного исправления теоретически вы можете установить max-width на внешнем div, чтобы ограничить степень его растяжения ... но, к сожалению, max-width не поддерживается во всех упомянутых «старых» браузерах.

Я знаю, что это не то, что вы хотите услышать, но я думаю, вам придется грызть пулю и либо изменить разметку, либо ослабить требования к стилю (например, отказаться от поплавка).

person Chris    schedule 17.11.2009
comment
Я согласен с этим. Я смотрел на это время от времени последние пару недель, так как это такая хорошая проблема, но я не думаю, что есть обходной путь, позволяющий IE6, IE7 и Firefox 2 обрабатывать плавающий div внутри абсолютно позиционированного div. без установленной ширины. Если бы это был я, я бы оставил все как есть для браузеров, которые работают, а затем применил бы хак для максимальной ширины только в тех браузерах, которые не обрабатывают это и называют это днем. - person Bertine; 26.11.2009

Вам нужно это, чтобы он не выходил за край страницы:

body {margin:0;padding:0}

Однако он по-прежнему будет занимать всю ширину страницы, он просто не будет переполняться

person James Goodwin    schedule 08.10.2009
comment
Да, меня не волнует переполнение страницы. Меня интересует только не растягивания абсолютно позиционированного элемента. - person Roatin Marth; 09.10.2009
comment
Совершенно необходимо, чтобы .floater был float:right? Будете ли вы размещать контент слева от него? Я только спрашиваю, потому что изменение его на float:left вместо этого исправляет все, и любые другие теги <div>, которые вам нужны в .outer, также могут быть перемещены влево .. - person James Goodwin; 09.10.2009
comment
@ Джеймс: да, .floater должно быть float:right. В этом суть проблемы. - person Roatin Marth; 09.10.2009

В этом случае float должен иметь ширину, а с другой точки зрения - top: 0; left: 0; для позиционированного элемента они не должны сохраняться в таком виде. примечание: это логика только для дизайна, если у вас нет кода, спросите :)

person Ibrahim AbuRajab    schedule 08.11.2009
comment
Хорошая ширина для поплавка. Однако это не имеет значения (родитель по-прежнему растягивается). - person Roatin Marth; 09.11.2009

.outer {переполнение: скрыто; ясно: правильно; позиция: абсолютная; граница: сплошной красный 1px; } .outer .floater {float: right; } Lorem ipsum Это действительно просто, вам нужно только установить свойства overflow и clear для каждого объекта, имеющего перемещаемые дочерние элементы.

Если родительский объект также является плавающим, вам нужно только установить объект в плавающий режим.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <style>
  .outer { overflow:hidden; clear:right; position:absolute; border:1px solid red; }
  .outer .floater { float:right; }
  .outer .floater .child { float:right; }
  </style>
</head>
<body>
  <div class="outer">
      <div class="floater">Lorem ipsum 
                <span class="child">HI!</span>
      </div>
  </div>
</body>

Если есть вопросы, просто задавайте!

С уважением и GL. ;)

person Raul Illana    schedule 09.11.2009
comment
Вы сами пробовали этот образец, и он сработал? Потому что я добавил overflow:hidden; clear:right; к .outer, и результат тот же: плавающий объект по-прежнему заставляет родительский элемент полностью растягиваться. - person Roatin Marth; 09.11.2009

Если вы измените float:right на clear:right, вы получите запрошенный вывод в своем примере, но он не будет работать должным образом, если у вас действительно есть контент за пределами div с плавающей точкой.

person awe    schedule 13.11.2009

Спецификация css2 содержит некоторую информацию о том, как пользовательский агент «должен» вычислять ширину, но реальность - это не спецификация: http://www.w3.org/TR/CSS2/visudet.html#Computing_widths_and_margins.

Я определенно рекомендую использовать строгий DOCTYPE вместо переходного, http://www.w3.org/QA/2002/04/valid-dtd-list.html#DTD.

Без указания поля для вашего .outer div пользовательский агент определит ширину, используя width: auto, который, похоже, зависит от пользовательского агента.

Почему вы не хотите указывать ширину родительского div?

Если можете, укажите ширину родительского div, даже если это width: 100%. Вы можете также поместить * { margin: 0; padding: 0; } в таблицу стилей, чтобы избежать различий между пользовательскими агентами в этих атрибутах, особенно если вы укажете ширину как 100% для .outer.

Это может быть тривиально, но вы можете сократить оператор .outer .floater до просто .floater.

Если вам нужен эффект «сужения по размеру» вокруг внутреннего плавающего элемента и необходимо поддерживать правильное положение плавающего элемента, тогда добавьте direction: rtl; в класс .floater; в противном случае вы сможете использовать float-left;

person dan_nl    schedule 15.11.2009
comment
Я не хочу указывать ширину родительского div, потому что я хочу, чтобы он был эластичным (т.е. растягивал / сжимал в соответствии с его содержимым). Вы касаетесь этого с помощью вашего комментария, уменьшенного до размера. Я рассмотрю другие ваши предложения и сообщу. - person Roatin Marth; 16.11.2009
comment
Может быть, немного больше информации об общем дизайне, который вы ищете с некоторым макетным контентом, может помочь нам найти что-то ... атм, на самом деле нет необходимости в div .outer, избавьтесь от класса .outer и. внешнюю ссылку .floater и сделайте ее просто .floater, а div .floater будет перемещаться вправо с эффектом сжатия, который вы ищете. - person dan_nl; 18.11.2009
comment
@dan_nl: Я добавил к вопросу полный пример дизайна. Требования есть не просто так. - person Roatin Marth; 20.11.2009
comment
Привет, Роатин, я подумал, что должно быть требование;) В этом маленьком диалоге много чего происходит ... если вы закомментируете ссылку jqueryui css и избавитесь от объявления класса .floater, похоже, это позволяет вам автоматически подобрать ищем. Когда вы возвращаете jquery css, проблема с автоподгонкой возвращается, поэтому, вероятно, есть float: прямо в этой таблице стилей (еще не было времени на это посмотреть). У вас должен быть .floater {float: right; } декларация? - person dan_nl; 20.11.2009
comment
@dan_nl: спасибо, что посмотрели. Re: ваши комментарии: если вы избавитесь от ссылки css, это означает, что контейнер больше не position:absolute. Это нарушает требование №2 (в стороне: в таблице стилей jquery нет float:right. Скорее, я использовал это для моего объявления .floater). Во-вторых, если вы избавитесь от поплавка, то я нарушу требование №3. - person Roatin Marth; 20.11.2009
comment
хорошо ... Я пытался сделать шаг назад и сосредоточиться на дизайне и функциональности диалогового окна, которые я видел на тестовой странице, и начал разбирать его так, чтобы он выглядел одинаково в FF3 и IE6. Следующим шагом было рассмотрение применения классов jqueryui, чтобы они не мешали дизайну, но похоже, что требования к стилю, которые у вас есть, усложняют его ... если вы можете отпустить некоторые из них, которые могут вы решение. В любом случае удачи. - person dan_nl; 20.11.2009

Да, для элементов с абсолютным позиционированием ширина не определена (как вверху и слева). Некоторые браузеры в этом случае используют эластичную ширину в стиле таблицы, а некоторые - 100%, но это зависит от браузера. В этом случае лучше всего быть откровенным.

Таблицы - действительно единственный хороший способ получить эластичную ширину кроссбраузерным способом. Одноклеточная таблица ничем не хуже DIV, если вы помните cellspacing=0.

<table cellspacing=0 cellpadding=0 style="position:absolute;top:0;right:0">
    <tr><td>Lorem ipsum</td></tr>
</table>
person jpsimons    schedule 16.11.2009
comment
Я знаю, что стол подойдет. Столы всегда работают;) Столы - это кошачье мяуканье. Я люблю столы. Однако в этом случае я бы действительно предпочел бы исправить это только в css. Разметка существует во многих местах кодовой базы, чтобы ее можно было исправить в HTML. Спасибо за предложение, это может быть единственное решение, защищенное от браузера. - person Roatin Marth; 16.11.2009
comment
Рискуя показаться слишком рьяным, таблицы на самом деле являются единственным хорошим способом получить эластичную ширину кроссбраузерным способом. не является правильным. Я понимаю, почему так много людей любят таблицы (это несложный взлом), но они предназначены для отображения табличных данных. Ничего больше. - person codeinthehole; 17.11.2009
comment
Уточните, пожалуйста ... как сделать так, чтобы блочные элементы соответствовали их содержанию без таблицы? Как вы думаете, почему таблицы предназначены только для табличных данных? - person jpsimons; 17.11.2009
comment
@darkporter: принятый подход к элементу получения блока, чтобы он соответствовал его содержимому (то есть ширине текучей среды), оставаясь в потоке документа, заключается в перемещении элемента (например, "left"). Если оставаться в потоке документа не важно, position:absolute работает отлично, кроме случаев, когда вы перемещаете дочерний элемент, как это сделал я!. @codeinthehole: в этом случае таблица имеет точные свойства как абсолютно позиционированный div, но не страдает от описанной проблемы. Винтовые таблицы предназначены для аргументов табличных данных. Это старый. Это сделано. Таблицы - это дерьмо. - person Roatin Marth; 17.11.2009
comment
Немного предыстории: исходная спецификация w3c (с 1994 года или когда-либо) предназначалась для таблиц для данных. Затем людям понадобился макет для своих ярких сайтов электронной коммерции, поэтому таблицы эволюционировали для этой цели. Затем, примерно в 2002 году, блочная модель CSS стала жизнеспособной моделью компоновки. Обе модели (макет стола и модель коробки) обладали возможностями, которых не было у другой, поэтому они сосуществуют до сих пор. Не беспокойтесь о спецификациях, есть комплименты. Фактическое использование отражается в спецификации. @codeinthehole прав в том, что блочная модель является предпочтительной из двух. - person jpsimons; 17.11.2009

Ваш div .outer пуст, поэтому мы получаем разные результаты. Как только вы добавляете в него контент, по крайней мере, в моем тесте он работает точно так же (моим тестом был Chrome 3.0 как «работающий по назначению» и IE7 как сломанный).


<div class="outer">
  <div class="floater">Lorem ipsum</div>
Lorem ipsum dolor sit amet consequetur elit ipsum dolor sit amet consequetur elit ipsum dolor sit amet consequetur elit ipsum dolor sit amet consequetur elit ipsum dolor sit amet consequetur elit ipsum dolor sit amet consequetur elit ipsum dolor sit amet consequetur elit 
</div>

Поскольку вы упомянули, что у div .outer есть контент, попробуйте удалить из него div с плавающей запятой, и он все равно получит очень похожий результат.

Изменить

Чтобы воспроизвести код без растягивания (поймите здесь, что у вас будут разные проблемы, которые нужно решить после того, как это будет работать одинаково, например, поля / отступы / вертикальное растяжение), вы можете ввести относительную «оболочку».


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <style>

  body { margin: 0; }
  #outer { position: absolute; border:1px solid red; }
  #wrapper { position: relative; }
  #floater { position: absolute; right:0; border: 1px blue solid;  }

  </style>
</head>
<body>

  <div id="outer">

    <div id="wrapper"> 
        <div id="floater">Lorem ipsumX</div> 
    </div>

    Lorem ipsum dolor sit amet consequetur elitipsum dolor sit amet consequetur elit
  </div>
</body>
person Francisco Aquino    schedule 17.11.2009
comment
Спасибо, что посмотрели на это. Результаты: 1) ваш первый пример не имеет значения: (как я и ожидал, так как производственный код имеет много содержимого после поплавка, но все равно демонстрирует такое же растяжение). 2) ваш второй пример (введение относительной оболочки) не имеет значения :(. Причина, по которой он работает для вас, заключается в том, что вы обошли мое требование, чтобы floater оставался смещенным вправо. Вы просто расположен абсолютно правее (right:0), что создает больше проблем с коллизией текста. В любом случае спасибо. - person Roatin Marth; 20.11.2009

Поскольку в вашем рабочем примере я вижу, что вы используете jquery, вы можете сначала вычислить ширину контейнера, прежде чем перемещать плавающий объект следующим образом:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
  <style>
  .outer { position:absolute; border:1px solid red;}
  </style>
</head>
<body>
  <div class="outer">
    <div class="floater">Lorem ipsum</div>
  </div>

  <script type="text/javascript">
    $(".outer")
      .css("width", $(".outer").width());
    $(".floater")
      .css("float", "right");
  </script>

</body>

Установка ширины внешнего div заставляет его вести себя во всех других браузерах.

person JamesPlayer    schedule 20.11.2009

У меня нет IE6, IE7 или FF2 для тестирования, поэтому я собираюсь нанести удар в темноте на этом. Если мне не изменяет память, вы захотите float:left на .outer. Это минимизирует ширину .outer при сохранении ваших внутренних пропорций div.

person mattbasta    schedule 22.11.2009