如何在弹性项目及其容器周围创建“折叠”边框?

Posted

技术标签:

【中文标题】如何在弹性项目及其容器周围创建“折叠”边框?【英文标题】:How to create "collapsed" borders around flex items and their container? 【发布时间】:2016-06-11 05:46:48 【问题描述】:

我有以下布局:

#limited-width 
  width: 100%;
  max-width: 200px;
  margin: 0 auto;
  font-size: 18px;

ul 
  display: flex;
  flex-flow: row wrap;
  list-style: none;
  padding: 0;
  margin: 20px;

ul > li 
  display: block;
  text-align: center;
  flex: 1 0 auto;
  max-width: 100%;
  box-sizing: border-box;
  margin: 0;
  padding: 4px 7px;
  border: 2px solid rgba(0,0,0,.3);
  background-color: rgba(0,0,0,.03);
<div id="limited-width">
  <ul>
    <li>Apple</li>
    <li>Orange</li>
    <li>Pineapple</li>
    <li>Banana</li>
    <li>Tomato</li>
    <li>Pear</li>
    <li>Lemon</li>
  </ul>
</div>

如您所见,ul 内的列表项有一个宽度为2px 的边框,但正因为如此,元素之间的边框加倍了。我正在寻找一种方法来使元素之间的边框宽度相同,同时使用 flexbox 保持外部边框相同(类似于border-collapse 在表格上的工作方式)。这可能吗?如果可以,怎么做?

【问题讨论】:

【参考方案1】:

有两种主要方法可以实现这一目标。在每种方法下,您都会找到一个工作演示,您可以展开它来查看它的行为方式。将鼠标悬停在元素上会给它们一个红色边框,以便您更轻松地选择最适合您的方法。

父子边框对齐

你需要像这样定义边框:

ul, ul > li 
  border-style: solid;
  border-color: rgba(0,0,0,.3);

ul       border-width: 2px  0   0  2px 
ul > li  border-width:  0  2px 2px  0  

这里的关键在border-width 属性中:

在容器上,topleft 的值设置为所需大小,而 rightbottom 设置为 0 在项目上,rightbottom 的值设置为所需大小,而 topleft 设置为 0

通过这样做,边框将以某种方式叠加起来,从而在元素和容器周围形成一个折叠良好、一致的边框。

:hover  border-color: red 
#limited-width 
  width: 100%;
  max-width: 200px;
  margin: 0 auto;
  font-size: 18px;

ul, ul > li 
  border-style: solid;
  border-color: rgba(0,0,0,.3);

ul 
  display: flex;
  flex-flow: row wrap;
  list-style: none;
  padding: 0;
  margin: 20px;
  border-width: 2px 0 0 2px;

ul > li 
  display: block;
  text-align: center;
  flex: 1 0 auto;
  max-width: 100%;
  box-sizing: border-box;
  margin: 0;
  padding: 4px 7px;
  border-width: 0 2px 2px 0;
  background-color: rgba(0,0,0,.03);
<div id="limited-width">
  <ul>
    <li>Apple</li>
    <li>Orange</li>
    <li>Pineapple</li>
    <li>Banana</li>
    <li>Tomato</li>
    <li>Pear</li>
    <li>Lemon</li>
  </ul>
</div>

边框减半

如果您出于任何目的想要为每个元素设置不同的边框,这可能是一种适合您需求的折衷方案。给定所需的border-width2px,CSS 如下:

ul, ul > li 
  border: 1px solid rgba(0,0,0,.3);

此方法在父项及其子项上设置所需边框宽度的一半,使最终边框2px 变粗。小心使用这种带有小数像素的方法(例如1.5px),你可以使用run into issues。

使用border-color-更改规则时,半角会很明显,但如果您想要更好看的边框,这比第一种方法要好得多。

:hover  border-color: red 
#limited-width 
  width: 100%;
  max-width: 200px;
  margin: 0 auto;
  font-size: 18px;

ul, ul > li 
  border: 1px solid rgba(0,0,0,.3);

ul 
  display: flex;
  flex-flow: row wrap;
  list-style: none;
  padding: 0;
  margin: 20px;

ul > li 
  display: block;
  text-align: center;
  flex: 1 0 auto;
  max-width: 100%;
  box-sizing: border-box;
  margin: 0;
  padding: 4px 7px;
  background-color: rgba(0,0,0,.03);
<div id="limited-width">
  <ul>
    <li>Apple</li>
    <li>Orange</li>
    <li>Pineapple</li>
    <li>Banana</li>
    <li>Tomato</li>
    <li>Pear</li>
    <li>Lemon</li>
  </ul>
</div>

【讨论】:

如果您希望其中一项具有不同的背景和边框颜色,例如处于活动状态?这个模型在这里不足。我的解决方法:jsbin.com/kageqe/5/edit?html,css,output【参考方案2】:

我有同样的问题,但我做了这个(见下面的演示)。 我向每个块添加负'margin-left'和负'margin-top'等于边框的宽度。然后我在容器中添加相同但正的“padding-left”和“padding-top”,以补偿偏移量。哇啦啦!现在我们在 flex 项和它们的容器周围得到了“折叠”的边框。

.catalog-list 
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  padding-top: 1px;
  padding-left: 1px;
  box-sizing: border-box;
  max-width: 800px;
  margin: auto;
  box-shadow: inset 0 0 0 1px #8c8c8c;


.catalog-item 
  width: calc(25% + 1px);
  margin-top: -1px;
  margin-left: -1px;
  padding: 20px;
  border: 1px solid #8c8c8c;
  box-sizing: border-box;
  transition: all 0.2s;
  box-sizing: border-box;


.catalog-item:hover 
  border-color: transparent;
  box-shadow: 0 0 15px -2px #8c8c8c;
<div class="catalog-list">
  <div class="catalog-item"></div>
  <div class="catalog-item"></div>
  <div class="catalog-item"></div>
  <div class="catalog-item"></div>
  <div class="catalog-item"></div>
  <div class="catalog-item"></div>
</div>

【讨论】:

【参考方案3】:

在我的例子中,边框需要为 1px,这使得它更加困难。我在https://codepen.io/Hawkun/pen/rsIEp/ 找到了一个解决方案,它使用阴影来模拟边框,实际上效果很好。

下面是实际代码。它不使用 flexbox,但如果你将阴影应用到你的 flex 内容,你就可以开始了。

body 
  font-family: sans-serif;
  background-color: #eee;
  padding: 20px;


.info 
  color: darkred;
  font-weight: bolder;


.container 
  background-color: white;
  float: left; /* Makes the container height the same as its children. */
  padding: 10px;
  margin-bottom: 40px;


.container div 
  padding: 20px;
  float: left;
  background-color: #def;
  
  
  /* And here comed the trick: */

  box-shadow: 
1px 0 0 0 #888, 
0 1px 0 0 #888, 
1px 1px 0 0 #888,   /* Just to fix the corner */
1px 0 0 0 #888 inset, 
0 1px 0 0 #888 inset;



#container1 
  width: 100%;


#container2 
  width: 50%;


#container2 div 
  width: 70%;
<p>The first container:</p>

<div id="container1" class="container">
  <div>Hello, this is the first floated div</div>
  <div>And this is the second</div>
  <div>And finally the third one</div>
</div>

<p>The second container:</p>

<div id="container2" class="container">
  <div>Hello, this is the first floated div</div>
  <div>And this is the second</div>
  <div>And finally the third one</div>
</div>

【讨论】:

这个答案与Flexbox无关。 ...然而正如 Jon Onstott 所说,它适用于 flexbox。 我试图对此做出回应,但我做不到(限制太短)。所以我对主要问题做出回应:***.com/a/68074775/4832358【参考方案4】:

这是我的解决方案:

window.addEventListener('load', function() 

    var containsFlex = document.getElementsByClassName('containsFlex');
    var i = containsEdit.length;
    while (i--) containsEdit[i].style.borderWidth = "1px 0 0 0"; 


问题在于 FLEX 的编程代码出现在 CSS 中设置宽度的代码之后,因此任何通过 CSS 设置这些项目的尝试都会失败。但是,使用上面的代码(或变体),可以创建可接受的结果。

[我在工作,所以我不能写一个完整的帖子。向所有人道歉]

【讨论】:

【参考方案5】:

这是我的另一个想法,它可以在 flex box 换行时保持边框“折叠”。它使用顶部和左侧的背景颜色以及右侧和底部的边框。可能很难让它在背景图像上工作。

.container 
  display: flex;
  flex-flow: row wrap;
  border-style: solid;
  border-width: 0 2px 2px 0;
  border-color: black;
  background-color: black;


.container>div 
  flex: 1 0 auto;
  margin: 2px 0 0 2px;
  background-color: white;
<div class="container">
  <div>Eh?</div>
  <div>Bee.</div>
  <div>This div contains a whole bunch of stuff.</div>
  <div>This div contains a whole bunch of stuff.</div>
  <div>This div contains a whole bunch of stuff.</div>
  <div>Sea!</div>
  <div>This div contains a whole bunch of stuff.</div>
  <div>This div contains a whole bunch of stuff.</div>
  <div>This div contains a whole bunch of stuff.</div>
</div>

【讨论】:

【参考方案6】:

我刚刚遇到了这个问题,这是我的解决方案。我的情况是我需要连续渲染每 4 个项目。

.container 
  display: flex;
  flex-wrap: wrap;


.item 
  flex: 0 0 25%;
  border-right: 1px solid black;


.item:nth-child(4n) 
  border-right: none;


.item:nth-child(n+5) 
  border-top: 1px solid black;

这样,border-right 只显示在同一行的前 1-3 个项目上。从第 5 项(第 2 行)开始,它们都有一个边框顶部。

它产生与 Ivan 的答案相似的结果。但我认为这种方法要简单得多。

【讨论】:

【参考方案7】:

我希望此评论可能会有所帮助,但我的意愿是对 @jon-onstott 做出回应

您的回答帮助我解决了一个类似的案例。我注意到您使用了嵌入阴影(我想知道这是否就是您不需要修复其余角落(左上角、右上角和左下角)的原因,但我很确定如果您的所有阴影都是一开始。

我必须解决的另一点(就我而言)是我用于阴影的颜色使用了透明度(不是 100% 不透明),因此同级框弄乱了颜色。如果需要显示阴影,我使用带有负值的插入剪辑路径修复了它。

我没有显示任何代码,因为它解决了问题中没有提到的情况*,但我仍然认为这可以帮助任何错误地结束这里的人(起初)寻找一些类似的解决方案问题。

*:我的案例是一组格式良好的盒子,它们具有确定的列和行的大小。这就是为什么我知道哪些盒子需要显示阴影。尝试在 flexbox 中解决我的问题没有任何意义,因为 flexbox 的形状取决于容纳它的可用空间。

【讨论】:

【参考方案8】:

使用:last-of-type,您可以“折叠”最后一个边框。也许添加一个box-sizing:border-box;

【讨论】:

以上是关于如何在弹性项目及其容器周围创建“折叠”边框?的主要内容,如果未能解决你的问题,请参考以下文章

如何在表格的 tbody/thead 部分周围创建边框?

CSS/HTML:在输入字段周围创建发光边框

Python - 如何删除选定ListBox项目周围的边框?

如何在 QWebEngineView 周围显示边框?

如何使用 css 在我的文本周围创建边框 [重复]

如何删除一组子项周围的默认边框?