这个HTML5砖怎么会掉下来?

时间:2013-04-24 00:55:29

标签: css html5 layout

我准备了一个示例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>

更新

在再次阅读我的问题之后,我意识到这可能表明我正在努力实现的错误印象是修复一些HTML。 为了明确强调这一点,我不需要在这里改变任何东西。砖块的例子只是我正在观察的问题的一个有趣的演示。 我非常有兴趣在这样的安排中理解在插入内容时导致元素改变位置的原因

10 个答案:

答案 0 :(得分:4)

你有

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

答案 1 :(得分:4)

在使用表格,表格行和表格单元格多次显示时,我看到了浏览器之间的行为差​​异。首先,我从不使用它们,因为总有一个更好的解决方案。但是,对于你的问题:

当处理旨在表现得像表格的CSS时,思考一所旧学校会有所帮助。

事实证明,使小提琴中的POC正常行为的神奇CSS属性是vertical-align。事实上,这可以修复所有浏览器中奇怪插入的额外垂直空间,而不仅仅是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属性,例如漂浮,不必要。

干杯

答案 2 :(得分:1)

这是我能想到的最好的主意,我希望我能指出它或者它最接近它。
在您的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的孩子高,而不是内心的孩子#brick,也许这就是你想要的,但要注意它。

问题2 @ Chrome(如果您“解决”第一个问题则不存在)

我不确定我在这里说的是什么,但是......这可能是一个webkit错误吗? Opera也会这样吗? 编辑:Opera不像Chrome一样,它返回到正常的布局,所以也许它毕竟不是webkit的错误:/

所以你有一个表格和表格单元格,但是浏览器会认为“等等......如果这是一个表格,这是一个单元格......行在哪里!?”,所以它创造了一个“鬼行”,所以它可以很开心。但是,当你删除文本时,我不确定它是什么意思,因为它“正常”工作。如果您查看开发人员工具,您将看到没有实际的行元素或类似的东西 当您“重新添加”文本时,浏览器会因为表格布局而受到影响。所以它再次重新创建行(拉伸#pit),可能是因为“鬼行”没有被清除,或者因为#pit的高度从未再次重新计算而且它只在鬼行时递增产卵。

如果您想保留相同的CSS规则,则必须执行以下操作:

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

答案 3 :(得分:1)

有时,最简单的答案被忽略了。不是将内容重置为空(例如“”),而是简单地将空内容作为非中断空间启动,并将其重置回非中断空间。表格单元格没有内容时不会呈现。一个不间断的空间被单元格视为内容,因此它可以正确呈现。

JSFiddle here

这是一个问题:

您需要将此规则添加到#brick块:

vertical-align: top;

并且您需要向您的空表格单元格提供一些内容,这些内容单元格应该以这种方式呈现内容:

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

Voila,它固定在Chrome中,并在其他地方以相同的方式显示。这是桌子的老派问题。看起来Chrome决定忠实于他们最初在糟糕的日子里的表现。

或者,对于纯CSS解决方案,您也可以将内容规则添加到#brick块中:

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

这种方式完全相同。享受!

答案 4 :(得分: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>

然后用这样的CSS为每个div分配不同的高度。

.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;
} 

默认情况下,这些内部div与其基线垂直对齐。因此,没有任何文本,所有div都沿着单元格的底部对齐:

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

但是,如果您向其中任何一个添加文本,那么将按下该div,以便第一行文本的基线与其他div的底边对齐。

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

正如其他人所指出的,您可以通过设置不同的vertical-align属性来更改所发生的情况。例如,将vertical-align:top添加到 .cell 选择器会为您提供以下内容:

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

我觉得在codepen中使用这类东西最简单,你可以在制作它们时看到这些变化。 Here's an example试验。

答案 5 :(得分:0)

看起来chrome对于显示不满意:显示内部的table-cell:没有显示的表:table-row介于两者之间。

如果你添加它(并给砖一些宽度),它将停止下降:

#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; }

答案 6 :(得分:0)

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

以上导致它扩大(并且不合同)。这是预期的行为吗?不,因为它不会发生在IE或Firefox上,我认为这是一个Chrome错误,会误解display: table&amp; display: table-cell行为。在删除文本时,它似乎不会重新计算表格单元格的高度<div id="contrail">

Have a look at this fiddle - 我用实际的表替换了div。每次填充文本时,表格单元格的高度会扩大,但在文本清除时会收缩回原始大小。我会得出结论,这是一个Chrome错误,因为这个CSS显示模式的目的是模仿<table><td>的使用。

答案 7 :(得分:0)

我相信有一个奇怪的规则:

#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/

答案 8 :(得分:0)

我注意到只添加

   <p> around your text </p>

解决了问题

这是一个有效的jsfiddle

答案 9 :(得分:0)

答案:浏览器无法理解您的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