简体   繁体   中英

Vertically align text of same-height blocks along a shared baseline (supporting mixed font size)

I have a single-line/row navigation/menu where some items have bigger font size but I want all items' text to be aligned with harmony, along the base line.

I also need the items to react to hover on the full height of the menu so user don't have to aim the smaller text (this is for sub-menu but not part of this question).

I tried with Flexbox but I can't mix align-items: stretch (full height) and align-items: baseline (text alignment)

Note: Text of menu items are in menu-item-label wrappers because I will add more stuff to the item (dropdown arrows, picto...) but it's the text alignment that counts.

 body { font-size: 24px; /* Big value to ease highlighting of mis-alignemnt */ }.some-existing-container { /* This container has some dimensions: I don't think it would cause conflict. */ width: 100%; height: 4em; display: flex; align-items: center; /* Not mandatory */ border: 1px solid blue; /* Highlighting */ }.menu { display: flex; align-items: baseline; border: 1px solid green; /* Highlighting */ }.menu-item { border: 1px dotted brown; /* Highlighting */ }.menu-item:hover { background-color: grey; /* Highlighting */ }.menu-item-label { border: 1px dotted pink; /* Highlighting */ }.other { margin-left: auto; /* Places this block to the right in.some-existing-container */ border: 1px solid purple; /* Highlighting */ }.bigger { font-size: 4rem; }.stretched { align-items: stretch; }
 <p>Variant 1: Texts are aligned but items does not occupies the whole height:</p> <div class="main"> <div class="some-existing-container"> <div class="menu"> <div class="menu-item"> <div class="menu-item-label"> Home </div> </div> <div class="bigger menu-item"> <div class="menu-item-label"> Item1 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item2 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item3 </div> </div> </div> <div class="other"> Other </div> </div> </div> <p>Variant 2: Items of same-and-full height but texts are not aligned:</p> <div class="main"> <div class="some-existing-container"> <div class="menu stretched"> <div class="menu-item"> <div class="menu-item-label"> Home </div> </div> <div class="bigger menu-item"> <div class="menu-item-label"> Item1 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item2 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item3 </div> </div> </div> <div class="other"> Other </div> </div> </div>

I would like to mix the two as the montage below:

所需渲染示例

Is it even possible (with or without JavaScript)?

I have also tried with Grid layout without success (see this JSFiddle ).

I would keep the baseline alignment and consider a pseudo elemen trick to increase the hoverable area:

 body { font-size: 24px; /* Big value to ease highlighting of mis-alignemnt */ }.some-existing-container { height: 4em; display: flex; align-items: center; border: 1px solid blue; }.menu { display: flex; align-items: baseline; border: 1px solid green; overflow:hidden; }.menu-item { border: 1px dotted brown; position:relative; z-index:0; }.menu-item::before { content:""; position:absolute; z-index:-1; top:-200px; bottom:-200px; left:0; right:0; }.menu-item:hover, .menu-item:hover::before{ background-color: grey; }.menu-item-label { border: 1px dotted pink; }.other { margin-left: auto; border: 1px solid purple; }.bigger { font-size: 4rem; }
 <div class="main"> <div class="some-existing-container"> <div class="menu"> <div class="menu-item"> <div class="menu-item-label"> Home </div> </div> <div class="bigger menu-item"> <div class="menu-item-label"> Item1 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item2 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item3 </div> </div> </div> <div class="other"> Other </div> </div> </div>

This is the result when I fixed your css a bit.

 body { font-size: 24px; /* Big value to ease highlighting of mis-alignemnt */ }.some-existing-container { /* This container has some dimensions: I don't think it would cause conflict. */ width: 100%; height: 4em; display: flex; align-items: center; /* Not mandatory */ border: 1px solid blue; /* Highlighting */ }.menu { display: flex; align-items: baseline; /* Add this css */ height: 4rem; /////////////// border: 1px solid green; /* Highlighting */ }.menu-item { border: 1px dotted brown; /* Highlighting */ /* Add this css */ display: flex; align-items: center; ////////////////// }.menu-item:hover { background-color: grey; /* Highlighting */ }.menu-item-label { border: 1px dotted pink; /* Highlighting */ }.other { margin-left: auto; /* Places this block to the right in.some-existing-container */ border: 1px solid purple; /* Highlighting */ }.bigger { font-size: 4rem; }.stretched { align-items: stretch; }
 <p>Variant 1: Texts are aligned but items does not occupies the whole height:</p> <div class="main"> <div class="some-existing-container"> <div class="menu"> <div class="menu-item"> <div class="menu-item-label"> Home </div> </div> <div class="bigger menu-item"> <div class="menu-item-label"> Item1 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item2 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item3 </div> </div> </div> <div class="other"> Other </div> </div> </div> <p>Variant 2: Items of same-and-full height but texts are not aligned:</p> <div class="main"> <div class="some-existing-container"> <div class="menu stretched"> <div class="menu-item"> <div class="menu-item-label"> Home </div> </div> <div class="bigger menu-item"> <div class="menu-item-label"> Item1 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item2 </div> </div> <div class="menu-item"> <div class="menu-item-label"> Item3 </div> </div> </div> <div class="other"> Other </div> </div> </div>

Have you tried using CSS Grid Layout? https://www.w3schools.com/css/css_grid.asp

Update:

Sorry, I did not noticed that you have tried Grid Layout already. But I do think that it is possible to achieve it with Grid Layout.

Would you mind posting the Grid Layout version of your code? I might be able to help you.

Thanks

  • Because your wrapper "menu" didn't have its own height, set height for it, ex:
    .menu {
      height: 4rem;
      align-items: stretch
    }
  • Next, "menu-item" you should add:
    .menu-item {
      display: flex;
      align-items: center;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM