4

I have a Flex-Box Container that contains various items. I want all items to have the same width, but I also want to avoid clipping.

My HTML Structure goes a bit like this (Compiled with Blade):

<div class="container-tease">
    @foreach($users as $user)
        <section class="tease tease-user">
            <img class="avatar" src="{{ $user->avatar }}">
            <div class="summary">
                <h3 class="name">{{ $user->name }}</h3>
                <span class="email">{{ $user->email }}</span>
            </div>
        </section>
    @endforeach
</div>

With the following CSS (Compiled with SASS):

.container-tease
{
    font-family: 'Source Sans Pro', sans-serif;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    justify-content: flex-start;

    .tease
    {
        margin: 10px;
        padding: 7px;

        &.tease-user
        {
            display: flex;
            align-items: center;

            background-color: #EEE;
            border: 1px solid #AAA;
            border-radius: 8px;

            .avatar
            {
                border-radius: 24px;
                background-color: white;
                width: 48px; height: 48px;
            }

            .summary
            {
                margin-left: 10px;
                margin-right: 5px;

                .name
                {
                    margin: 0 0 5px 0;
                    font-size: 20px;
                    line-height: 20px;
                    white-space: nowrap;
                }

                .email
                {
                    margin-left: 2px;
                    font-size: 14px;
                    line-height: 14px;
                    color: #888;
                }
            }
        }
    }
}

When viewed, it appears like this:

First Incorrect Flex-Box Design

Of course, this isn't what I want.

I'd like these items to all share the same width, like this:

Correct Flex-Box Design

Now bare in mind that I'm not asking for a two-column solution, nor a browser-based responsive solution. The deciding factor for the width here are the items themselves, not how wide the browser is.

For example, if I remove the long names/emails from the example, it should look like this:

enter image description here

I've tried doing things like flex: 1 0 200px for each item, but that ends up looking like this:

enter image description here

The last row of items don't share the same width, and partial clipping occurs on Lance's item.

Hopefully I've made clear of what exactly I want. I don't mind having to specify a width in the CSS, if it is only a minimum width.

Here's what I have on Code Pen. Feel free to play around with that.

I'd like to stick to a CSS solution, but I'll accept a JavaScript solution if it does what I want.

Boom
  • 2,465
  • 4
  • 19
  • 21

2 Answers2

0

Currently, this is not possible with Flexbox.

However, the CSS working group is aware of this problem, and desires to fix it in Flexbox Level 2.

See Specification Issues and Planning » css-flexbox-2

Solve the “items on the last line get way too big when you're flexing” problem. More generally, “make items have a consistent flexed size, regardless of how much extra space is on each line”.

  • Possible solution - fill out the last line with “phantom copies” of the last item, flex with them in, then remove them.
  • Possible solution - calculate minimum values of 1fr and alignment free space across the entire flexbox (instead of per-line) and use that.
Oriol
  • 274,082
  • 63
  • 437
  • 513
0

The trick is to add enough empty elements at the end of the list to evenly divide the space (as mentioned in https://stackoverflow.com/a/22018710/526741). Any rows with no content (eg, only empty .tease .tease-user elements) would be collapsed.

flex:1 0 200px ensures that each element is at least 200 pixels wide, but can grow, if there's room. It also keeps all of the boxes the same width.

overflow:hidden is the only way I can think of right now that prevents a single box from growing when the other boxes don't. You can use some clever text wrapping to make sure everything is still readable. Or remove this and deal with the occasional row with boxes of different sizes (only when the contents are too long for the box).

.container-tease {
  display:flex;
  flex-wrap:wrap;
}
.tease-user {
  flex:1 0 200px;
  overflow:hidden;
  outline:1px solid orange;
}
<div class="container-tease">
  <section class="tease tease-user">
    <div class="summary">
      <h3 class="name">Bill Murray</h3>
      <span class="email">murray.bill@att.net</span>
    </div>
  </section>
  <section class="tease tease-user">
    <div class="summary">
      <h3 class="name">Lance Armstrong</h3>
      <span class="email">lance.armstrong@gmail.com</span>
    </div>
  </section>
  <section class="tease tease-user">
    <div class="summary">
      <h3 class="name">Jackie Chan</h3>
      <span class="email">chan@gmail.com</span>
    </div>
  </section>
  <section class="tease tease-user">
    <div class="summary">
      <h3 class="name">James Bond</h3>
      <span class="email">bond.007@misix.gov</span>
    </div>
  </section>
  <section class="tease tease-user">
    <div class="summary">
      <h3 class="name">Issac Newton</h3>
      <span class="email">inewton@cambridge.edu</span>
    </div>
  </section>
  <section class="tease tease-user">
    <div class="summary">
      <h3 class="name">Pope Francis</h3>
      <span class="email">theoneandonly@bible.org</span>
    </div>
  </section>
  <section class="tease tease-user">
    <div class="summary">
      <h3 class="name">Issac Newton</h3>
      <span class="email">inewton@cambridge.edu</span>
    </div>
  </section>
  <section class="tease tease-user"></section>
  <section class="tease tease-user"></section>
  <section class="tease tease-user"></section>
  <section class="tease tease-user"></section>
  <section class="tease tease-user"></section>
</div>
Community
  • 1
  • 1
0b10011
  • 18,397
  • 4
  • 65
  • 86