CSS 如何在 flex 项目及其容器周围创建“折叠”边框?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35678353/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create "collapsed" borders around flex items and their container?
提问by SeinopSys
I have the following layout:
我有以下布局:
#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>
As you can see, the list items inside the ul
have a border with the width of 2px
, but because of this, the border between elements doubles. I'm looking for a way to make the borders the same width between elements, while also keeping the border on the outside the same (similar to how border-collapse
works on tables) using flexbox. Is this possible, and if so, how?
如您所见, 里面的列表项ul
有一个宽度为 的边框2px
,但正因为如此,元素之间的边框加倍了。我正在寻找一种方法来使元素之间的边框具有相同的宽度,同时还border-collapse
使用 flexbox保持外部边框相同(类似于表格的工作方式)。这是可能的,如果是,如何?
回答by SeinopSys
There are two primary ways to achieve this. Under each method you will find a working demo that you can expand to see how it behaves. Hovering over elements will give them a red border to make choosing the approach that works best for you easier.
有两种主要方法可以实现这一点。在每种方法下,您都会找到一个工作演示,您可以展开该演示以查看其行为。将鼠标悬停在元素上会给它们一个红色边框,以便更轻松地选择最适合您的方法。
Parent-child border alignment
父子边框对齐
You need to define the border like this:
您需要像这样定义边框:
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 }
The key here is in the border-width
property:
这里的关键在于border-width
属性:
- On the container, the values for the
top
andleft
are set to the desired size while theright
andbottom
are set to0
- On the items, the values for the
right
andbottom
are set to the desired size while thetop
andleft
are set to0
- 在容器中,所述的值
top
和left
被设置到所需的大小,而right
与bottom
被设置为0
- 上的项目,对于的值
right
和bottom
被设置为当所需的大小top
和left
设置为0
By doing this, the borders will add up in a way that they form a nicely collapsed, consistent border around the elements and the container.
通过这样做,边框将以一种方式加起来,它们在元素和容器周围形成一个很好的折叠的、一致的边框。
: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>
Halving borders
将边界减半
In case you want to have distinct borders for each element for any purpose, this is a compromise that might suit your needs. Given a desired border-width
of 2px
the CSS is as follows:
如果您想出于任何目的为每个元素设置不同的边框,这是一种可能适合您需求的折衷方案。一个所希望border-width
的2px
的CSS如下:
ul, ul > li {
border: 1px solid rgba(0,0,0,.3);
}
This method sets half of the desired border width on both the parent and its children, making the final border 2px
thick. Be wary of using this method with fractional pixels (e.g. 1.5px
) as you can run into issues.
此方法在父级及其子级上设置所需边框宽度的一半,使最终边框2px
变粗。对分数像素(例如1.5px
)使用此方法时要小心,因为您可能会遇到问题。
When using border-color
-changing rules the half-width will be apparent, but if you want nicer looking borders this is a much better approach than the first.
当使用border-color
-change 规则时,半角会很明显,但如果你想要更好看的边框,这是比第一种更好的方法。
: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>
回答by Ivan
I had same question, but I made this(see demo below). I add to each block negative 'margin-left' and negative 'margin-top' equal to the width of the border. Then I add the same but positive 'padding-left' and 'padding-top' to the container, to compensate for the offset. Woo-a-la! Now we get “collapsed” borders around flex items and their container.
我有同样的问题,但我做了这个(见下面的演示)。我向每个块添加负的“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>
回答by Jon Onstott
In my case, the borders need to be 1px which makes it more difficult. I found a solution at https://codepen.io/Hawkun/pen/rsIEp/which uses shadows to simulate borders, which actually works well.
就我而言,边框需要为 1px,这使得它变得更加困难。我在https://codepen.io/Hawkun/pen/rsIEp/找到了一个解决方案,它使用阴影来模拟边框,实际上效果很好。
Here is the code in action. It doesn't use flexbox but if you apply the shadow to your flex content, you're good to go.
这是正在运行的代码。它不使用 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>
回答by wotboy
Here's another idea I had that will keep borders "collapsed" when flex boxes wrap. It uses background color for top and left and borders for right and bottom. It might be hard to make it work over a background image.
这是我的另一个想法,当弹性盒包装时,它会保持边框“折叠”。它使用顶部和左侧的背景颜色和右侧和底部的边框。可能很难让它在背景图像上工作。
.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>
回答by speciale
With :last-of-type
you can "collapse" the last border. Maybe adding a box-sizing:border-box;
有了:last-of-type
你可以在“崩溃”最后的边界。也许添加一个box-sizing:border-box;