0

I have an unassuming nav menu:

<div>
    <ul>
        <li><a href="/real-estate"><span>Real Estate &amp;&nbsp;Development</span></a></li>
        <li><a href="/new-business"><span>New &amp; Expanding Business</span></a></li>
        { … }
    </ul>
</div>

This menu needs the following visual properties:

  • Items distributed horizontally within their container by putting equal space between them
  • Text in items can wrap to make items take up less horizontal space
  • All text is vertically centered.

I can't get all three of these at the same time.

This SCSS:

div > ul {
    display: flex;
    justify-content: space-between;

    > li {
        display: table;
        table-layout: fixed;
        word-wrap: break-word;

        > a {
            display: table-cell;
            text-align: center;
            vertical-align: middle;
        }
    }
}

…gets me great spacing with vertical centering, but the text doesn't wrap, so the items overflow the container:

Overflowy flex nav

If I delete the display: table stuff:

div > ul {
    display: flex;
    justify-content: space-between;

    > li {
        // DELETED display: table;
        // DELETED table-layout: fixed;
        word-wrap: break-word;

        > a {
            display: table-cell;
            text-align: center;
            vertical-align: middle;
        }
    }
}

…then I get good text wrapping, but the spacing between the items is all off:

Janky-spaced flex nav

I've tried lots of other combinations of CSS properties, but nothing has gotten me any closer than these two. Here's a pen with my code. Is there any incantation that will get me all the things I want from this menu?

EDIT: My Pen now includes a third attempt that uses another Flex container instead of display: table-cell. The spacing is better, but still not great. I guess this may just come down to the text-wrapping width issue described in this answer, and I may just have to hard code some line breaks or use JavaScript.

EDIT 2: The thing about that, though, is that the items aren't maxing out at a set size. On my third attempt there, the ones that wrap and end up bigger than the width of the wrapped text do not end up the same size as each other. And in fact the space-between isn't doing much of anything, because the top-level flex items are filling the entire space; the space-between them is 0px.

75th Trombone
  • 1,364
  • 15
  • 28
  • In the last example, it looks like the spacing between is fine. Do you mean you want each item to have an equal width? i.e. _"Real Estate & Development"_ is the same width as _"Global"_? – hungerstar Feb 27 '18 at 18:25
  • The spacing between them is not equal at all. Look at the difference between the left-edge-to-first-item spacing and the last-item-to-right-edge. Look at the gap between the first two items compared to the gap between Global and Career Center. – 75th Trombone Feb 27 '18 at 18:30
  • So that's a "no" on the equal width question? Why do you need `display: table`? – hungerstar Feb 27 '18 at 18:31
  • `display: table` makes the spacing nice and even, but doesn't allow wrapping. Removing it allows wrapping, but makes the spacing janky. And yeah, I don't want them the same width necessarily, I want them spaced evenly, as `justify-content: space-between` is supposed to do. But see my edit to my question for why I may be on a wild goose chase. – 75th Trombone Feb 27 '18 at 18:35
  • Yep, that edit post looks like your issue. Even though you're not setting a max-width, the text doesn't re-size after wrapping. – hungerstar Feb 27 '18 at 18:40
  • The thing about that though is that the menu items aren't maxing out at a set size. Several of the items end up wider than their post-text-wrap width, but they're not the same size. Maybe it's proportional based on how long the text was before wrapping? – 75th Trombone Feb 27 '18 at 18:48
  • Ya, something along those lines. Kind of like it will go on for x-length before wrapping and then stays at that size. – hungerstar Feb 27 '18 at 20:00

2 Answers2

1

Use flex instead of table-cell on the a elements, and then put width: min-content on the spans inside them:

div > ul {
    display: flex;
    justify-content: space-between;

    > li > a {
        display: flex;
        align-items: center;
        justify-content: center;
        text-align: center;

        span {
            width: min-content;
        }
    }
}

You might get more text wrapping than you bargained for this way, but you can control that with non-breaking spaces.

75th Trombone
  • 1,364
  • 15
  • 28
  • The min-content works perfectly, but as you mentioned there is more additional text-wrapping than required. I have the same scenario, however the non-breaking spaces is not an option due to the content being pulled in from elsewhere. – Dayley Aug 09 '23 at 11:21
0

Text should already wrap automatically inside flex items. It is working for me with the following code:

SCSS:

ul {
  padding: 0;
  list-style: none;
  display: flex;
  background-color: grey;
  height: 50px;
  align-items: center;
  justify-content: space-between;
  li {
    text-align: center;
    flex: 1;
  }
}

HTML:

<div>
    <ul>
        <li><a href="/real-estate"><span>Real Estate &amp;&nbsp;Development</span></a></li>
        <li><a href="/new-business"><span>New &amp; Expanding Business</span></a></li>
      <li><a href="/new-business"><span>New &amp; Expanding Business</span></a></li>
    </ul>
</div>

Fiddle

You can adjust spacing between items with justify-content:

.container {
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}

cssTricks page for Flexbox

You can make items take equal width by setting flex-basis: 0; flex-grow: 1; on the li elements.

Alex W
  • 37,233
  • 13
  • 109
  • 109
  • Your fiddle didn't have enough different sizes of nav items to see the uneven spacing. [Here's a fork that does.](https://jsfiddle.net/tqnevahj/1/) – 75th Trombone Feb 27 '18 at 19:09
  • Just updated. I think adding `flex-basis: 0; flex-grow: 1;` to your `li` elements should fix the issue with spacing. – Alex W Feb 27 '18 at 19:11
  • That didn't have good results on my actual website or [in my pen (Attempt Five)](https://codepen.io/75th/pen/eVQqQb?editors=1100), unfortunately. – 75th Trombone Feb 27 '18 at 19:29
  • @75thTrombone Try taking `display: table` off of `li` – Alex W Feb 27 '18 at 19:59