Почему мой экран: элемент table-cell не заполняет свободное пространство?

Обновление - я решил отказаться от решения JavaScript. Единственный способ убедиться, что он всегда работает, - это положить его в setInterval() каждые несколько секунд. Не хочу этого делать. Я знаю, что этот CSS возможен, я видел, как он работает. Я снова открою награду за 150, если она закончится.


У меня есть модальное всплывающее окно, состоящее из двух разделов: слева и справа. В обоих разделах приведена надпись выше и содержание ниже. Метка фиксируется на определенном количестве пикселей, но нижняя область должна быть в состоянии заполнить оставшееся пространство, поэтому я использую display:table с левой и с правой стороны и display: table-cell на внутренних участках, чтобы достичь эффект "заполнить оставшееся пространство". Он отлично работает в Chrome и Safari.

Здесь CSS:

#tagBoxLeft,#tagBoxRight {
    display: table;
    height: 100%;
    width: 50%;
    position: absolute;
    right: 0;
    opacity: 0;
}
#tagBoxLeft { left: 0 }
#tagBoxDescription {
    display: table-row;
    -webkit-border-top-left-radius: 20px;
    width: 100%;
    word-break: break-all;
    word-wrap: break-word;
    -webkit-box-shadow: 0 1px 0 #FFF;
    -moz-box-shadow: 0 1px 0 #FFF;
    box-shadow: 0 1px 0 #FFF;
}
.nano {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: table-cell;
}
#taglabel {
    display: table-row;
    z-index: 10000;
    border-top: 1px solid #FFF;
    width: 100%;
    height: 39px;
}

И это просто делает кучу divs в таблицу, чтобы они могли иметь высоты, которые относительно друг друга. Также обратите внимание, что левая и правая стороны относятся к окну браузера, поэтому я не могу просто использовать проценты.

Однако в Firefox и Opera секции сторон #tagBoxLeft и #tagBoxRight отказываются принимать height:100%;, пока они имеют display:table;. Поэтому он не будет приводить в действие нижние разделы. Я знаю, что Firefox и Opera поддерживают это нормально (см. http://jsfiddle.net/Qxswa/). Но почему все мое содержимое переполняется в Firefox и Opera?

Вот скриншот проблемы:

введите описание изображения здесь

Ответ 1

Здесь альтернатива использованию display:table и друзей, которая использует часто забытую способность абсолютно позиционированных элементов для установки как своих верхних, так и нижних (и левого и правого) значений. Он по существу "прилипает" к верхнему и нижнему краям, придавая вам высоту относительно контейнера, но без явной установки высоты.

UDPATED: Как упоминал Джексон, версия этого кода, основанная только на CSS, не содержит фиксированную панель с автоматической высотой в столбце. Простой бит JS исправит это - вам просто нужно установить разумную высоту по умолчанию для пользователей без JS. JS нужно запускать только при загрузке модального, а не с интервалом.

Здесь обновленная скрипта: http://jsfiddle.net/cxY7D/5

и здесь упрощенный HTML:

<div id="modal">
      <div class="left">
          <div class="description">
            <h1>#tag_name</h1>
            <dl>
             <dt>Tags</dt> <dd>27</dd>
            </dl>
          </div>
          <div class="contents">
            <div class="header">            
              <h2>Featured</h2>
            </div>
            <ol>
              <li>Something Something</li>
              <li>...</li>
            </ol>
          </div>
      </div>
      <div class="right">
        <div class="contents">
          <div class="header">
            <h2>Recent</h2>
          </div>
          <ol>
            <li>Something Something</li>
            <li>...</li>
          </ol>
        </div>
      </div>
  </div>

и CSS:

body {
      background:#444;
    }
     #modal {
       background:#FFF;
       position: absolute;
       top: 4em;
       bottom: 4em;
       left: 6em;
       right: 6em;
     }

     #modal .left,
     #modal .right {
       position:absolute;
       top: 0;
       bottom: 0;
     }

     #modal .left {
       background:#ACF9E4;
       left: 0;
       right:50%;
     }

     #modal .right {
       background:#FCFFCD;
       right: 0;
       left:50%;
     }

     #modal .contents {
      position:absolute;
      top: 0;
      bottom: 0;
      width: 100%;
      overflow-y:auto;
     }

     #modal .description {
       height: 8em;
     }

     #modal .description + .contents {
       top: 10em;
   }

     #modal .header,
     #modal .description,
     .contents li {
       border-bottom:1px solid #CCC;
       padding: 1em;
     }

     #modal .description dt {
       float: left;
       padding-right: 1em;
     }

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

JS (предполагая jQuery)

$(function(){
    $('#modal').on('display', function(){
        //Calculate the height of the top left panel, and provide the remaining space to the bottom left
        var leftColumn = $(this).find('.left'),
            descriptionHeight = leftColumn.find('.description').height('auto').outerHeight(); //Set the height to auto, then read it

        leftColumn.find('.contents').css('top', descriptionHeight)//Apply the height to the scrolling contents pane     
    });

    $('#modal').trigger('display');
});​

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

Вот ответ, который я дал, используя подобную технику, и больше объяснений ханов и whys: The Impossible Layout?. Просмотрите статью "А" отдельно для обсуждения, а также некоторые простые исправления, которые заставляют ее работать в IE6 (если вам это интересно).

Ответ 2

Есть ли причина, по которой вы не можете просто использовать JavaScript для вычисления правильной высоты и применить ее в строке? Это не так хорошо и просто, но было бы тривиально, что вы описываете.

var boxHeight = $('#tagBox').height();
var leftLabelHeight = $('#tagBoxDescription').height();
$('#tagBoxPopular').css('height', boxHeight - leftLabelHeight + 'px');

var rightLabelHeight = $('#taglabel').height();
$('#tagBoxStream').css('height', boxHeight - rightLabelHeight + 'px');

Ответ 3

Я открываю ваш сайт на firefox, а ссылки хештегов, которые я вижу с хром, исчезли. Вы делаете некоторые попытки исправить прямо сейчас? Если вы вернете ссылки для версии ff, я могу помочь вам отладить это.

UPDATE:

То, что я вижу, представляет собой чрезвычайно сложное сочетание отображения: таблицы и отображения: таблицы-ячейки с абсолютным и статическим позициями в сочетании с процентными высотами и многими другими перекрестно-браузерными летучими смесями.

Выполняя множество исправлений и исправлений, я смог получить следующее:

screenshot of patched up version under firefox

Очевидно, что есть много ошибок, но по крайней мере вы получаете полосы прокрутки.

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

Здесь у нас есть два варианта:

1.- Сохраните свой оригинальный подход css/html и устраните неисправность панели прокрутки JS.
2. Перейдите на гораздо более простой вариант css/html

Приветствия G

Ответ 4

Вы можете посмотреть, как вы используете <section>. Это не то же самое, что <div>.

W3C - Использование элементов раздела HTML5 и элементов заголовка.

<header> появляется одинаково. Они оба являются элементами потока и не предназначены как контейнеры содержимого, а как элементы семантического структурирования для контейнеров содержимого.

Я использовал Firebug и изменил как <header>, так и <section> на display:block на догадку. Началось формирование вещей; однако после этих изменений я не смог получить эффект прокрутки. Затем я изменил <header> в сафари на display:inline. Разумеется, оба окна браузера выглядели так: enter image description here

Ответ 5

Вам нужно, чтобы скрыть #tagboxleft и #tagboxright. Это можно сделать, установив #tagbox в overflow:hidden, однако это скроет часть кнопки закрытия. поэтому вам нужен еще один div, завернутый вокруг левого и правого, но не x с overflow:hidden.

Так же:

<div id="tagbox">
    <div id="tagboxX"></div>
    <div id="tagboxleftright" style="overflow:hidden"> <!-- This is the wrapper div around tagbox left & right. Of course, move overflow:hidden to the style sheet -->
        <div id="tagboxLeft"></div>
        <div id="tagboxRight"></div>
    </div>
</div>

Это работало в Firefox, и оно должно работать в Internet Explorer.