2

I am having a problem trying to align the baselines of headings inside of a mega menu.

/* Presentational bits */

.add-divider {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
  padding-bottom: 0.65em;
  -webkit-box-align: baseline;
  -ms-flex-align: baseline;
  align-items: baseline;
}

.standard-list {
  list-style-type: none;
  padding-left: 0;
  list-style: none;
}


/* Core Styling */

.mega-menu-wrapper {
  list-style-type: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(23%, 1fr));
  grid-gap: 10px;
  align-items: baseline;
}
<nav>
  <ul class="mega-menu-wrapper">
    <li class="mega-menu-item">
      <h5 class="add-divider">Typical Section Header</h5>
      <ul class="standard-list">
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
      </ul>
    </li>
    <li>
      <h5 class="add-divider">Atypical Section Header with much longer content in it that breaks to another line</h5>
      <ul class="standard-list">
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
      </ul>
    </li>
    <li>
      <h5 class="add-divider">How to accomodate different sized sections Headers?</h5>
      <ul class="standard-list">
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
      </ul>
    </li>
    <li><h5 class="add-divider">The section dividers should line up</h5>
      <ul class="standard-list">
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
      </ul></li>
    <li>
      <h5 class="add-divider">No matter the content of the headers</h5>
      <ul class="standard-list">
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
        <li><a href="#">Link to nowhere</a></li>
      </ul>
    </li>
  </ul>
</nav>

As seen, I have a navigation, inside that navigation is an unordered list, and inside each list item is a heading and it's own unordered list of navigation items. Each of the headings have their own bottom border, for aesthetic purposes, and to divide the header from the links.

The problem is that I am unable to align these bottom borders, which are styles on the headings. I thought it would be a pretty simple task with CSS Grid, but perhaps I'm using the wrong thing to style this menu, or I am ignorant of some CSS Grid features.

All in all I just want to align the base lines of these headings, even if they are breaking to multiple lines.

I have looked at the following resources, and none of them line up with my use-case, but I can't be the only one having this problem, or it's easier to solve than I thought and I'm overlooking something. Either way, here's what I've tried to no avail:

Any help is much appreciated.

CodePen Example

Update

I'd like to be able to support a variable number of links, as this is a mega-menu, I don't know how many links the user will add into it.

I realize this may not be able to be done with the way my HTML is structured now. I am open to exploring new ways of structuring the HTML as long as I can have 4 columns of menu items before the 5th breaks to a new line.

mrClean
  • 415
  • 5
  • 18
  • This is not possible in **any** layout method. There is no CSS property to equalize heights of elements that do not share a parent. You need Javascript or a fundamental change in the HTML. – Paulie_D Sep 28 '18 at 16:26
  • @Paulie_D How would that HTML change look? I'm open to re-organizing the HTML to make the layout more flexible. – mrClean Oct 01 '18 at 17:31

2 Answers2

2

Since each heading is inside a different li you wont be able to align them without defining an height value.

However, you could fix this issue using some JavaScript:

(function() {
  var headings = document.querySelectorAll('.add-divider'),
      sizes = [];

  headings.forEach(function(el) {
    sizes.push(el.offsetHeight); 
  });

  for (let i = 0; i < headings.length; i++) {
    headings[i].style.minHeight = Math.max(...sizes) + 'px'; 
  }
})();

(The jQuery version)

$(function(){
  var sizes = [];

  $('.add-divider').each(function() {
    sizes.push($(this).outerHeight()); 

  }).css('minHeight', Math.max(...sizes) );
});

Your CodePen example updated

Quentin Veron
  • 3,079
  • 1
  • 14
  • 32
  • Do you have a non-JavaScript version of this answer? If not that's fine, it's just that this is a good solution, however, I don't like how the items that are broke on the next line have a "needless" height on them. I know if I want to fix that I get into matchHeight - https://github.com/liabru/jquery-match-height - territory, unless you have a solution. Anyway, if you don't have a non-JavaScript solution I will go ahead and accept your answer. – mrClean Sep 28 '18 at 17:22
  • Unfortunately, this can't be fix with plain CSS without changing the HTML structure. – Quentin Veron Sep 28 '18 at 17:26
  • Oh, interesting. Can you do an update where the HTML structure is changed, please? – mrClean Sep 28 '18 at 17:56
2

Here you are

CSS updated

/* Presentational bits */
.add-divider {
  margin-bottom: 7px;
  margin-top: auto; 
}

.standard-list {
  border-top: 1px solid rgba(0, 0, 0, 0.1);
  padding-top: 5px;
  padding-left: 0;
}

/* Core Styling */
.mega-menu-wrapper {
  display: flex;
  width: 600px;
  flex-wrap: wrap;
  align-items: stretch;
}

.mega-menu-wrapper li {
  width: 180px;
  flex-grow: 1;
  margin: 2px 10px;
  display:flex;
  flex-direction: column;
  justify-content: space-between;
}

.mega-menu-wrapper li ul{
  margin-bottom: auto;
}

Answer to comment #2

I'm afraid it is not 100% possible to have this layout in this "edge" case. But here are things you can do:

  • Use JS

    • target longest string
    • get it's height
    • set this height to other h tags
  • Still css but can be ugly

    • to any long h add class="long" and add provided css .mega-menu-wrapper li.long {flex-basis: 100%;}
  • Kinda "hack" - get count of longest list items and add empty ones (probably good if you use frontend framework - if you use one) Angular example:

list.component.html

...
  <li class="mega-menu-item">
      <h5 class="add-divider">Typical Section Header</h5>
      <ul class="standard-list">
        <li *ngFor="let i of arrayOfNumbers0toMax">
            <a href="{{linksAtN[i].link}}">{{linksAtN[i].linkName}}</a>
        </li>
      </ul>
    </li>
...

I also updated CSS in this answer and added

.mega-menu-wrapper li ul{
  margin-bottom: auto;
}

And removed display: flex of .add-divider

Also I'm appending link to CSS fixed example.

Chiffie
  • 581
  • 3
  • 18
  • I intentionally removed vendor prefixes and left only needed css for this layout - just add it again where needed. Also I want to warn you that IE10 and lower doesn't support flex display. But flex has support 95% of current browsers. More info [caniuse](https://caniuse.com/#feat=flexbox) – Chiffie Oct 01 '18 at 13:14
  • Thank you for your answer! This may be what I'm looking for if this solution also works for a variable number of links. Do you need to make a small tweak to support that? Let's say column 1 has 5, column 2 has 11, 3 has 5, 4 has 4, and 5 has 8 links. https://codepen.io/mrcleanandfresh/full/qJdYEP – mrClean Oct 01 '18 at 17:27