Reputation: 187
I am working on some css3 for a website I'm building. I'm attempting to make a "container" class that uses flexbox to make all its children have equal width. This works properly, but when I put a "container" and a normal element inside another "container", the two children are not of equal width.
I'm not sure why this isn't working, as it works for any element that is not a container.
HTML:
<div class="container">
<div class="container">
<div class="content-box">
One Sixth
</div>
<div class="content-box">
One Sixth
</div>
<div class="content-box">
One Sixth
</div>
</div>
<div class="content-box">
One half
</div>
</div>
CSS:
.container {
display: flex;
align-items: flex-start;
}
.container > * {
flex-basis: 100%;
min-width: 0;
}
.container > :not(:first-child) {
margin-left: 2%;
}
Codepen example: https://codepen.io/NetworkOverflow/pen/XLbdqa
Upvotes: 3
Views: 11877
Reputation: 7690
The problem is when you put a container inside of a container it's adding the margin so you see double the space on the right.
I would set your container to justify-content: space-between;
which pushes content elements to the outside edges. I'm using flex:1
instead of flex-basis
to tell the browser that each element should take up the same amount of space.
Your CSS becomes:
.container {
display: flex;
align-items: flex-start;
justify-content: space-between;
}
.container > * {
flex: 1;
margin-left: 2%;
min-width: 0;
}
.container > *:first-child {
margin-left:0;
}
/* not needed
.container > :not(:first-child) {
margin-left: 2%;
}
*/
Depending on the usage, it's sometimes helpful to add "sizing" classes that force a flex-basis
based on the number of items. Here's a codepen example.
.third {
flex-basis: calc(33.3333% - 2%);
}
.half {
flex-basis: calc(33.3333% - 2%);
}
Upvotes: 5
Reputation: 371231
You're paying a price for setting all elements to flex-basis: 100%
.
Because you're telling all elements, regardless of the number of siblings they may have, to occupy the full width of the container, you're forcing flex-shrink
to calculate the space necessary to accommodate them all.
This involves a relatively complex flexbox algorithm, which gets even more complex when you factor in padding and box-sizing: border-box
, both of which exist in your code.
The algorithm is explained here: How does flex-shrink factor in padding and border-box?
The quickest and easiest solution would be to specify the actual width of the containers.
For the row illustrating the problem (with a container, and a container within a container), instead of setting them to flex-basis: 100%
, which triggers flex-shrink
, set them to flex-basis: 50%
. Now the flex-shrink
process is avoided and you get what you want.
I added this to your code:
.container > .demo50 {
flex-basis: 50%;
}
div.content {
float: left;
width: 100%;
height: 100%;
background-color: var(--background-color2);
padding: 2% 10%;
}
div.banner {
background-color: var(--scheme-color2);
box-shadow: 0px 0px 50px 10px rgba(23, 196, 167, 0.5);
padding: 1rem;
text-align: center;
margin-bottom: 2em;
}
.content-box {
background-color: var(--background-color1);
box-shadow: 0px 0px 10px 5px rgba(84, 84, 84, 1);
padding: 1rem;
overflow-wrap: break-word;
margin-bottom: 2em;
}
.container {
display: flex;
align-items: flex-start;
}
.container > * {
flex-basis: 100%;
min-width: 0;
}
.container > :not(:first-child) {
margin-left: 2%;
}
.two-thirds {
flex-basis: calc(100% / 3 * 2);
}
.container > .demo50 {
flex-basis: 50%;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--background-color1: #707070;
--background-color2: #424242;
--background-color3: #afafaf;
--scheme-color1: #20f9d5;
--scheme-color2: #17c4a7;
--scheme-color3: #89e5d6;
--text-color: #e3edeb;
}
body {
font-family: "Open Sans", sans-serif;
color: var(--text-color);
}
<div class="content">
<div class="container">
<div class="banner">
<h1>Example</h1>
</div>
</div>
<div class="container">
<div class="content-box">
<p>Using 'flex-basis: 100%' seems to work perfectly well for evenly sizing and spacing elements in a row. However, when you put a .container inside a .container and attempt to do something like you see two rows below, the .container element and the
element that follows do not space themselves at half and half width.</p>
</div>
</div>
<div class="container">
<div class="content-box">
One Half
</div>
<div class="content-box">
One Half
</div>
</div>
<div class="container">
<div class="container demo50">
<div class="content-box">
One Sixth
</div>
<div class="content-box">
One Sixth
</div>
<div class="content-box">
One Sixth
</div>
</div>
<div class="content-box demo50">
One half
</div>
</div>
<div class="container">
<div class="content-box">
One Third
</div>
<div class="content-box">
Two Thirds
</div>
<div class="content-box">
Three Thirds
</div>
</div>
<div class="container">
<div class="content-box two-thirds">
Two Thirds
</div>
<div class="content-box">
One Third
</div>
</div>
<div class="container">
<div class="content-box">
One Third
</div>
<div class="content-box two-thirds">
Two Thirds
</div>
</div>
</div>
Upvotes: 1