Как этот кирпич HTML5 падает?

Я подготовил образец jsfiddle, чтобы показать проблему, с которой я сейчас сталкиваюсь с моим макетом: когда я динамически вставляю содержимое в конкретный элемент (кирпич), элемент опускается вместе со своим родителем таким образом, что вне моего понимания HTML/CSS. Когда я удаляю содержимое, исходный макет восстанавливается, если я не использую Chrome... тогда он сохранит свою позицию и снова упадет при добавлении нового содержимого.

Доказательство концепции: http://jsfiddle.net/GADk9/

Флажок в примере просто переключает текст внутри кирпича, не более того. Интересно, откуда взялся этот край (это?).

Вот полный документ HTML5:

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>HTML5 Falling Brick - What is this?</title>
<style>
#brick {
    background-color: lightgray;
    border: solid black medium;
    border-radius: 1em;
    color: red;
    font-size: 2em;
    height: 100%;
    text-align: center;
}
#contrail { background-color: lightblue; width: 20em; }
#pit { display: table; }
#pit>* { display: table-cell; }
#pit>*>* { height: 4em; }
</style>
</head>
<body>
    <div>
        <label>Click me twice
            <input onchange="document.getElementById('brick').innerHTML = this.checked ? 'FALL!!!' : ''" type='checkbox'></input>
        </label>
    </div>
    <div id='pit'>
        <div>
            <div>
            </div>
        </div>
        <div id='contrail'>
            <div>
                <div id='brick'></div>
            </div>
        </div>
    </div>
</body>
</html>

Update

После того, как я снова прочитал свой вопрос, я понимаю, что может показаться неправильным впечатление, что то, что я на самом деле пытаюсь выполнить, - это исправление некоторого HTML. Чтобы особо подчеркнуть этот факт, мне здесь ничего не нужно менять. Пример с кирпичом - просто забавная демонстрация проблемы, которую я наблюдаю. Мне действительно интересно понять , что заставляет элементы изменять свою позицию при вставке содержимого в такой схеме.

Ответы

Ответ 1

Это проще понять, если вы упростите разметку только на пару ячеек, каждая из которых содержит div.

<div class="cell left">
  <div class="inner"></div>
</div>
<div class="cell middle">
  <div class="inner"></div>
</div>
<div class="cell right">
  <div class="inner"></div>
</div>

Затем присвойте каждому div разную высоту некоторым CSS следующим образом.

.cell {
  display:table-cell;
  background-color:black;
  width:200px;
}

.inner {
  background-color:silver;
}

.left .inner {
  height:80px;
}
.middle .inner {
  height:140px;
}
.right .inner {
  height:100px;
} 

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

       +------+
       |      |
       |      +------+
+------+      |      |
|      |      |      |
|      |      |      |
+------+------+------+

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

       +------+
       |      |
       |      |
+------+      |      
|      |      +------+
|      |      |Text  |
+------+------+      |
              |      |
              +------+

Как было указано другими, вы можете изменить то, что происходит, установив другое свойство vertical-align. Например, добавление vertical-align:top в селектор .cell даст вам что-то вроде этого:

+------+------+------+
|      |      |Text  |
|      |      |      |
+------+      |      |
       |      +------+
       |      |
       +------+           

Я считаю, что проще всего поиграть с такими вещами в кодефене, где вы можете видеть изменения, как вы их делаете. Здесь пример для экспериментов.

Ответ 2

У вас есть

<div id='pit'>
    <div>
        <div>
        </div>
    </div>
    <div id='contrail'>
        <div>
            <div id='brick'></div>
        </div>
    </div>
</div>

И вы используете

#pit { display: table; }
#pit>* { display: table-cell; }
#pit>*>* { height: 4em; }

Теперь вот наша проблема, поскольку она говорит, что #pit - это таблица, а #pit>* - это таблица-ячейка, которая каждый раз сбрасывает height: 4em;.

Теперь вот мое решение.

#pit { display: block; }
#pit>* { display: table; }
#pit>*>* { height: 4em; display: table-cell;}

http://jsfiddle.net/AAbhishekk/GADk9/28/

Ответ 3

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

Когда вы работаете с CSS, который должен вести себя как таблицы, это помогает думать о маленькой старой школе.

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

Посмотрите на эту крошечную версию скрипта: http://jsfiddle.net/rtzeK/

#brick {
    background-color: lightgray;
    border: solid black medium;
    border-radius: 1em;
    color: red;
    font-size: 2em;
    height: 100%;
    text-align: center;
}
#contrail { background-color: lightblue; width: 20em; }
#pit { display: table; }
#pit>* { display: table-cell; vertical-align: top; }
#pit>*>* { height: 4em; }

В скрипте, с которой я связан, я просто устанавливаю отображаемые дочерние элементы: table-cell имеет дополнительное свойство, vertical-align: top. Как оказалось, вы можете установить его в середине или снизу, все с тем же эффектом. Это останавливает неправильное поведение - очевидно, Chrome нужно сказать, как вести себя в этом сценарии.

Я немного странно понимаю, как Chrome плохо себя ведет, и это кажется ошибкой. Тем не менее, я возвращаюсь к своему предыдущему заявлению об исключении этих значений свойств отображения, таких как чума. Комбинации дисплея: встроенный, встроенный блок, блок, в сочетании с относительным и абсолютным позиционированием, используемым надлежащим образом между родителями и детьми, оказывают другие неприятные свойства css, например. float, не нужно.

Приветствия

Ответ 4

Это лучшая идея, которую я могу придумать. Надеюсь, я пригвошу ее или что она как минимум близка к ней.
В ваших правилах CSS вы:

#pit { display: table; }
#pit>* { display: table-cell; }
#pit>*>* { height: 4em; }

который сообщает браузеру, что #pit является таблицей, и что все ее дочерние элементы являются ячейками (в то время как внуки - это то, что они есть, поскольку показ не выполняется CSS)

Здесь я вижу 2 проблемы:

Проблема 1

Внутри #pit у вас есть:

<div>
    <div>
    </div>
</div>
<div id='contrail'>
    <div>
        <div id='brick'></div>
    </div>
</div>

Обратите внимание на детей, потому что у вас есть 2, а селектор #pit>* говорит КАЖДЫЙ #pit РЕБЕНОК Я бы изменил для этого правила CSS:

#pit { display: table; }
#pit>#contrail { display: table-cell; }
#pit>#contrail>* { height: 4em; }

Но будьте осторожны с тем, что вы хотите, потому что это делает детей от #pit>#contrail 4em high, а не внутреннего ребенка #brick, возможно, это то, что вы хотите, но обратите внимание на него.

Проблема 2 @Chrome (нет, если вы "решаете" первую проблему)

Я не уверен, что я здесь говорю, но... может ли это быть ошибкой webkit? это происходит и с Opera?
EDIT: Opera не ведет себя как Chrome, она возвращается к нормальному макету, поэтому, возможно, это не ошибка веб-кита:/

Итак, у вас есть таблица и ячейки таблицы, но браузер затем думает "Подождите... если это таблица, и это ячейка... Где строка!?", поэтому она создает "призрак", поэтому он может быть счастлив. Однако я не уверен, что "это" думает, когда вы удаляете текст, потому что он "работает" нормально. Если вы посмотрите на инструменты разработчика, вы увидите, что нет элемента строки или чего-либо подобного.
Когда вы "повторно добавляете" текст, браузер - ум = удар, потому что макеты таблиц. Таким образом, он снова создает строку снова (растягивание #pit), возможно, потому, что "строки-призраки" не очищаются или потому, что высота #pit никогда не пересчитывается снова и она увеличивается только тогда, когда появляется строка-призрак.

Если вы хотите оставить одни и те же правила CSS, вам нужно будет сделать что-то вроде:

#pit { display: table; }
#pit>* { display: table-row; }
#pit>*>* { height: 4em; display: table-cell; }

Ответ 5

Иногда самые легкие ответы игнорируются. Вместо того, чтобы сбросить содержимое до нуля (например, ""), просто запустите пустое содержимое как неразрывное пространство, а reset верните его в неразрывное пространство. Ячейки таблицы не отображаются, когда у них нет содержимого. Неразрывное пространство считается содержимым ячейки, и поэтому оно корректно отображается.

JSFiddle здесь

Здесь rub:

Вам нужно добавить это правило в блок #brick:

vertical-align: top;

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

<div id='contrail'>
    <div>
        <div id='brick'>&nbsp;</div>
    </div>
</div>

Voila, она исправлена ​​в Chrome и отображается одинаково везде. Это проблема старой школы со столами. Кажется, Хром решил быть верным тому, как они изначально вели себя в плохие старые дни.

В качестве альтернативы, для чисто CSS-решения вы можете добавить правило контента в блок #brick:

vertical-align: top;
content: '&nbsp;';

Это работает точно так же. Наслаждайтесь!

Ответ 6

Похоже, хром недоволен отображением: table-cell внутри дисплея: таблица без отображения: таблица-строка где-то посередине.

Если вы добавите его (и придадите кирпичу ширину), он перестанет падать:

#brick {
    background-color: lightgray;
    border: solid black medium;
    border-radius: 1em;
    color: red;
    font-size: 2em;
    height: 100%;
    width: 200px;
    text-align: center;
}
#contrail { background-color: lightblue; width: 20em; }
#pit { display: table; }
#pit>* { display: table-row; }
#pit>*>* { display: table-cell; }
#pit>*>* { height: 4em; }

Ответ 7

#pit { display: table; }
#pit>* { display: table-cell; }

Вышеприведенное приводит к тому, что оно расширяется (& not contract). Это ожидаемое поведение? Нет, поскольку это не происходит в IE или Firefox, я считаю, что это ошибка Chrome, которая неправильно интерпретирует поведение display: table и display: table-cell. Кажется, он не пересчитывает высоту таблицы-ячейки, в вашем случае <div id="contrail">, когда текст удаляется.

Посмотрите на эту скрипту - Я заменил divs фактическими таблицами. Каждый раз, когда текст заполняется, высота ячейки таблицы расширяется, но при удалении текста он сжимается до исходного размера. Я бы сделал вывод, что это ошибка Chrome, поскольку цель этого режима отображения CSS заключается в том, чтобы имитировать использование <table><td>.

Ответ 8

Я считаю, что было странное правило:

#brick {
    background-color: lightgray;
    border: solid black medium;
    border-radius: 1em;
    color: red;
    font-size: 2em;
    line-height:2em;
    height: 100%;
    text-align: center;
    margin:0;
    padding:0;
    height:2em;
}
#contrail { background-color: lightblue; width: 20em; }
#pit { display: table; }
#pit>* { display: table-cell; }

http://jsfiddle.net/GADk9/77/

Ответ 9

Я заметил просто добавление

   <p> around your text </p>

решил проблему

здесь работает jsfiddle

Ответ 10

Ответ. Браузер не понимает вашу комбинацию макета html/css, потому что она не отформатирована в официальных спецификациях. Неправильно отформатированный HTML сделает элементы браузера ненадлежащим образом.

Ячейка таблицы ДОЛЖНА иметь строку родительской таблицы:

http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-td-element

Ячейка таблицы НЕ допускается как прямой дочерний элемент элемента таблицы:

http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#the-table-element