浮动元素旁的空白处出现意外结果

问题描述 投票:0回答:2

我在这样的布局上遇到问题:

.wrapper {
  clear: both;
  background-color: #ccc;
}

.wrapper+.wrapper {
  margin-top: 50px;
}

.side,
.main {
  height: 100px;
  padding: 10px;
  box-sizing: border-box;
  margin-top: 20px;
}

.box {
  padding: 10px;
}

.top {
  background: yellow;
}

.side {
  width: 100px;
  float: left;
  background: lightblue;
}

.main {
  margin-left: 100px;
  background: lightgreen;
}
<div class="wrapper">
  <div class="top"></div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

<div class="wrapper">
  <div class="top">
    <div class="box">top</div>
  </div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

.main.side元素需要对齐。如您在上面的代码段中所见,除非.top元素没有高度,否则一切都很好,在这种情况下,margin-top规则会导致它们倾斜。以下所有“解决”问题,但每个都有缺点:

  • .wrapper上添加边框(我也许可以使用透明边框,但是我真的不喜欢这样,因为它感觉像是脏东西,我宁愿不添加边框。出于某种原因,边框需要具有至少1px的宽度,否则将无法正常工作)

.wrapper {
  clear: both;
  background-color: #ccc;
  border: 1px solid #000;
}

.wrapper+.wrapper {
  margin-top: 50px;
}

.side,
.main {
  height: 100px;
  padding: 10px;
  box-sizing: border-box;
  margin-top: 20px;
}

.box {
  padding: 10px;
}

.top {
  background: yellow;
}

.side {
  width: 100px;
  float: left;
  background: lightblue;
}

.main {
  margin-left: 100px;
  background: lightgreen;
}
<div class="wrapper">
  <div class="top"></div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>
  • overflow: hidden添加到.wrapper(这会隐藏某些元素的某些部分,并导致其他元素放置在错误的位置)
  • overflow: auto添加到.wrapper(在某些情况下,这将添加滚动条)

后两段在我的代码段中并不明显,但在实际应用中,它们会引起here所述的问题。

我非常怀疑这个问题与Why doesn't the height of a container element increase if it contains floated elements?CSS container doesn't stretch to accommodate floats有关,但是我尝试了许多建议,但似乎都无法解决问题-也许是因为我的一个div浮动了,而另一个却没有。

由于这是大型应用程序的一部分,所以我不想大幅度地更改布局,只需具有一些css即可使.main.side保持对齐,而与这些元素之前的内容无关。

html css css-float
2个回答
1
投票

您可以将主要元素设置为inline-block,然后使用calc设置宽度。这不会对您的布局产生太大影响,您将获得正确的输出:

.main {
  width:calc(100% - 100px);
  display:inline-block;
  background: lightgreen;
}

完整代码:

.wrapper {
  background-color: #ccc;
  clear: both;
}
.wrapper+.wrapper {
  margin-top: 50px;
}

.side,
.main {
  height: 100px;
  padding: 10px;
  box-sizing: border-box;
  margin-top: 20px;
}

.box {
  padding: 10px;
}

.top {
  background: yellow;
}

.side {
  width: 100px;
  float: left;
  background: lightblue;
}

.main {
  width:calc(100% - 100px);
  display:inline-block;
  background: lightgreen;
}
<div class="wrapper">
  <div class="top"></div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

<div class="wrapper">
  <div class="top">
    <div class="box">top</div>
  </div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

另一个hacky的想法是确保您的顶部元素永远不会为空:

.top:empty {
  font-size:0;
}
.top:empty::before {
  content: "\80"; /* a random character */
}

完整代码

.wrapper {
  background-color: #ccc;
  clear: both;
}

.wrapper+.wrapper {
  margin-top: 50px;
}

.side,
.main {
  height: 100px;
  padding: 10px;
  box-sizing: border-box;
  margin-top: 20px;
}

.box {
  padding: 10px;
}

.top {
  background: yellow;
}

.side {
  width: 100px;
  float: left;
  background: lightblue;
}

.main {
  margin-left: 100px;
  background: lightgreen;
}

.top:empty {
  font-size:0;
}
.top:empty::before {
  content: "\80"; /* a random character */
}
<div class="wrapper">
  <div class="top"></div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

<div class="wrapper">
  <div class="top">
    <div class="box">top</div>
  </div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

您也可以考虑相同的技巧,但在主包装器上使用伪元素:

.wrapper::before {
  content: "\80"; /* a random character */
  display:block;
  font-size:0;
}

完整代码

.wrapper {
  background-color: #ccc;
  clear: both;
}

.wrapper+.wrapper {
  margin-top: 50px;
}

.side,
.main {
  height: 100px;
  padding: 10px;
  box-sizing: border-box;
  margin-top: 20px;
}

.box {
  padding: 10px;
}

.top {
  background: yellow;
}

.side {
  width: 100px;
  float: left;
  background: lightblue;
}

.main {
  margin-left: 100px;
  background: lightgreen;
}

.wrapper::before {
  content: "\80"; /* a random character */
  display:block;
  font-size:0;
}
<div class="wrapper">
  <div class="top"></div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

<div class="wrapper">
  <div class="top">
    <div class="box">top</div>
  </div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

您还可以使包装器inline-block的宽度等于100%,并且其行为几乎与块元素相同:

.wrapper {
  background-color: #ccc;
  display:inline-block;
  width:100%;
  vertical-align:top; /* avoid some unwanted white space issue*/
}

.wrapper+.wrapper {
  margin-top: 50px;
}

.side,
.main {
  height: 100px;
  padding: 10px;
  box-sizing: border-box;
  margin-top: 20px;
}

.box {
  padding: 10px;
}

.top {
  background: yellow;
}

.side {
  width: 100px;
  float: left;
  background: lightblue;
}

.main {
  margin-left: 100px;
  background: lightgreen;
}
<div class="wrapper">
  <div class="top"></div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

<div class="wrapper">
  <div class="top">
    <div class="box">top</div>
  </div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

为进行说明,您面临着the specification中所述的边距合并问题:

两个边距在且仅在以下情况下邻接:

  • 均属于参与相同块格式上下文的流内块级框
  • 没有线框,没有间隙,没有填充,也没有边框将它们分隔开(请注意,为此目的,某些零高度的线框(请参见9.4.2)将被忽略。)
  • 都属于垂直相邻的盒子边缘,即形成以下形式之一:
    • 盒子的上边距和第一个流入子元素的上边距

1
投票

您可以使用网格更加优雅地进行此操作。这是网格代码:

.wrapper {
    display: grid;
    grid-template-areas:
        "top top"
        "side main";
    grid-template-columns: 100px 1fr;
}

.top{grid-area:top}
.side{grid-area:side}
.main{grid-area:main}

注意我还可以注释掉其他几个元素,并且仍然保留所需的布局。

.wrapper {
  /*clear: both;*/
  background-color: #ccc;
}

.wrapper+.wrapper {
  margin-top: 50px;
}

.side,
.main {
  height: 100px;
  padding: 10px;
  box-sizing: border-box;
  /*margin-top: 20px;*/
}

.box {
  padding: 10px;
}

.top {
  background: yellow;
}

.side {
  /*width: 100px;
  float: left;*/
  background: lightblue;
}

.main {
  /*margin-left: 100px;*/
  background: lightgreen;
}

.wrapper {
    display: grid;
    grid-template-areas:
        "top top"
        "side main";
    grid-template-columns: 100px 1fr;
}

.top{grid-area:top}
.side{grid-area:side}
.main{grid-area:main}
<div class="wrapper">
  <div class="top"></div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>

<div class="wrapper">
  <div class="top">
    <div class="box">top</div>
  </div>
  <div class="side">side</div>
  <div class="main">main</div>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.