I have the following layout:
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>
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.
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:
top
and left
are set to the desired size while the right
and bottom
are set to 0
right
and bottom
are set to the desired size while the top
and left
are set to 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>
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:
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.
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.
: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>
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.
.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>
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.
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.
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>
With :last-of-type
you can "collapse" the last border. Maybe adding a box-sizing:border-box;