使CSS Flex元素忽略容器元素

5
我正在努力创建一个类似于Chosen的组件,但我在使用flex布局时遇到了问题。问题在于伪文本框中的每个“chip”需要放在一个不包含实际文本输入的容器中,但我需要这些“chip”被视为与input相同基础上的flex元素。我的HTML结构如下:
<div class="box">
  <div class="chipContainer">
    <div class="chip">Chip1</div>
    <div class="chip">Chip2</div>
    <div class="chip">Chip3</div>
    <div class="chip">Chip4</div>
  </div>
  <input class="textbox" type="text">
</div>

这个Plunker示例更加完整,并且其样式与我当前所使用的相当接近。

.box {
  background: #fff;
  border: 1px solid #ccc;
  width: 500px;
  overflow: auto;
  padding: 2px;
  display: flex;
  flex-wrap: wrap;
}
.chip {
  display: inline-block;
  border: 1px solid #ccc;
  background: #eee;
  padding: 2px;
  margin-right: 1px;
  flex: auto;
}
.textbox {
  border: none;
  background: #fdd;
  font-size: 18px;
  flex: auto;
}
.textbox:focus {
  outline: none;
}
.chipContainer {
  display: inline;
}
<div class="box">
  <div class="chipContainer">
    <div class="chip">Chip1</div>
    <div class="chip">Chip2</div>
    <div class="chip">Chip3</div>
    <div class="chip">Chip4</div>
  </div>
  <input class="textbox" type="text">
</div>
<br>
<div class="box">
  <div class="chipContainer">
    <div class="chip">Chip1</div>
    <div class="chip">Chip2</div>
    <div class="chip">Chip3</div>
    <div class="chip">Chip4</div>
    <div class="chip">Chip5</div>
    <div class="chip">Chip6</div>
    <div class="chip">Chip7</div>
    <div class="chip">Chip8</div>
    <div class="chip">Chip9</div>
    <div class="chip">Chip10</div>
    <div class="chip">Chip11</div>
  </div>
  <input class="textbox" type="text">
</div>

如您所见,当足够多的芯片已添加到.box容器中时,.chipContainer将开始包裹它们,但.chipContainer仍然是块级元素,并将input推到一个全新的行。

这个Plunker示例演示了我的目标。一旦删除.chipContainer,布局就可以相当容易地实现,但在组件结构中,.chipContainer是一个非常重要的元素,如果可能的话,我更愿意不删除它来解决这个问题。

.box {
  background: #fff;
  border: 1px solid #ccc;
  width: 500px;
  overflow: auto;
  padding: 2px;
  display: flex;
  flex-wrap: wrap;
}
.chip {
  display: inline-block;
  border: 1px solid #ccc;
  background: #eee;
  padding: 2px;
  margin-right: 1px;
  flex: auto;
  min-width: 50px;
  max-width: 60px;
}
.textbox {
  border: none;
  background: #fdd;
  font-size: 18px;
  flex: auto;
  min-width: 250px;
}
.textbox:focus {
  outline: none;
}
.chipContainer {
  display: inline;
}
<div class="box">
  <div class="chip">Chip1</div>
  <div class="chip">Chip2</div>
  <div class="chip">Chip3</div>
  <div class="chip">Chip4</div>
  <input class="textbox" type="text">
</div>
<br>
<div class="box">
  <div class="chip">Chip1</div>
  <div class="chip">Chip2</div>
  <div class="chip">Chip3</div>
  <div class="chip">Chip4</div>
  <div class="chip">Chip5</div>
  <div class="chip">Chip6</div>
  <div class="chip">Chip7</div>
  <div class="chip">Chip8</div>
  <div class="chip">Chip9</div>
  <input class="textbox" type="text">
</div>

2个回答

10

显示模块等级3介绍了display: contents:

该元素本身不生成任何框,但其子元素和伪元素仍像正常情况下一样生成框。为了进行框生成和布局,必须将该元素视为在文档树中用其子元素和伪元素替换。

所以你只需要

.chipContainer {
  display: contents;
}

.box {
  background: #fff;
  border: 1px solid #ccc;
  width: 500px;
  overflow: auto;
  padding: 2px;
  display: flex;
  flex-wrap: wrap;
}
.chip {
  display: inline-block;
  border: 1px solid #ccc;
  background: #eee;
  padding: 2px;
  margin-right: 1px;
  flex: auto;
  min-width: 50px;
  max-width: 60px;
}
.textbox {
  border: none;
  background: #fdd;
  font-size: 18px;
  flex: auto;
}
.textbox:focus {
  outline: none;
}
.chipContainer {
  display: contents;
}
<div class="box">
  <div class="chipContainer">
    <div class="chip">Chip1</div>
    <div class="chip">Chip2</div>
    <div class="chip">Chip3</div>
    <div class="chip">Chip4</div>
  </div>
  <input class="textbox" type="text">
</div>
<br>
<div class="box">
  <div class="chipContainer">
    <div class="chip">Chip1</div>
    <div class="chip">Chip2</div>
    <div class="chip">Chip3</div>
    <div class="chip">Chip4</div>
    <div class="chip">Chip5</div>
    <div class="chip">Chip6</div>
    <div class="chip">Chip7</div>
    <div class="chip">Chip8</div>
    <div class="chip">Chip9</div>
    <div class="chip">Chip10</div>
    <div class="chip">Chip11</div>
  </div>
  <input class="textbox" type="text">
</div>

然而,请注意它目前还没有广泛支持。


看起来这正是我想要的,尽管浏览器支持有所不足。谢谢! - Zikes
1
除了“不被广泛支持”这一点有点轻描淡写外,我认为截至2016年1月21日,它仅在Firefox中得到支持(即使使用最新版本,Chrome、IE、Safari或Opera都不支持)。 - Sarus

0

您可以使用flex-growflex-basis来实现:

但是,这些属性的值应该根据.chipContainer子元素的数量而变化。

这个想法是(使用您的示例),.chipContainer.box的一个弹性项,同时也是其子元素的弹性容器。作为一个弹性项,它应该比.textbox大4个尺寸,因为有四个.chip,所以我们使用flex-grow:4flex-basis:4px

.textbox.chip应该具有相同的大小,因此它们都具有flex-basis:1pxflex-grow:1

.box, .chipContainer
{
    display: flex;
}

.textbox, .chip
{
    flex-grow: 1;
    flex-basis: 1px;
    border-width: 0;
}

.chipContainer
{
    flex-grow: 4;
    flex-basis: 4px;
}
<div class="box">
  <div class="chipContainer">
    <div class="chip">Chip1</div>
    <div class="chip">Chip2</div>
    <div class="chip">Chip3</div>
    <div class="chip">Chip4</div>
  </div>
    <input type="text" class="textbox" />
</div>

这种方法唯一的问题是,在Chrome上,输入文本的边框会导致计算失败,并且它比其他框多4个像素,我从所有项目中删除了边框,所以它们现在具有相同的宽度。

这似乎没有考虑到变量数量的.chip元素,或者将它们包装在.box中。 - Zikes
好的,这是我能想到的唯一解决方案,你可以使用JavaScript或任何服务器语言来设置基础并进行增长。 - Luizgrs
我认为我可以通过设置基础并动态增长来应对,但包装是必不可少的。 - Zikes
明白了,我之前漏掉了你问题中的那个点,现在我重新读了一遍,发现是包装问题。 - Luizgrs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接