沿共享基线垂直对齐相同高度块的文本(支持混合字体大小)
Vertically align text of same-height blocks along a shared baseline (supporting mixed font size)
我有一个 single-line/row navigation/menu,其中一些项目的字体更大,但我希望所有项目的文本沿着基线和谐对齐。
我还需要这些项目对悬停在菜单的整个高度上做出反应,这样用户就不必瞄准较小的文本(这是针对子菜单的,但不是这个问题的一部分)。
我尝试使用 Flexbox,但我不能混合使用 align-items: stretch
(全高)和 align-items: baseline
(文本对齐)
注意:菜单项的文本在 menu-item-label
包装器中,因为我将向项目添加更多内容(下拉箭头、图片...),但重要的是文本对齐方式。
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>
我想将两者混合为下面的蒙太奇:
有没有可能(有或没有JavaScript)?
我也尝试过网格布局但没有成功(参见 this JSFiddle)。
您尝试过使用 CSS 网格布局吗?
https://www.w3schools.com/css/css_grid.asp
更新:
抱歉,我没有注意到您已经尝试过网格布局。
但我确实认为可以通过网格布局来实现它。
您介意发布您的代码的网格布局版本吗?我也许可以帮助你。
谢谢
- 因为您的包装器“菜单”没有自己的高度,请为其设置高度,例如:
.menu {
height: 4rem;
align-items: stretch
}
- 接下来,您应该添加“菜单项”:
.menu-item {
display: flex;
align-items: center;
}
我会保持基线对齐并考虑使用伪元素技巧来增加悬停区域:
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>
这是我稍微修正一下你的 css 后的结果。
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>
我有一个 single-line/row navigation/menu,其中一些项目的字体更大,但我希望所有项目的文本沿着基线和谐对齐。
我还需要这些项目对悬停在菜单的整个高度上做出反应,这样用户就不必瞄准较小的文本(这是针对子菜单的,但不是这个问题的一部分)。
我尝试使用 Flexbox,但我不能混合使用 align-items: stretch
(全高)和 align-items: baseline
(文本对齐)
注意:菜单项的文本在 menu-item-label
包装器中,因为我将向项目添加更多内容(下拉箭头、图片...),但重要的是文本对齐方式。
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>
我想将两者混合为下面的蒙太奇:
有没有可能(有或没有JavaScript)?
我也尝试过网格布局但没有成功(参见 this JSFiddle)。
您尝试过使用 CSS 网格布局吗? https://www.w3schools.com/css/css_grid.asp
更新:
抱歉,我没有注意到您已经尝试过网格布局。 但我确实认为可以通过网格布局来实现它。
您介意发布您的代码的网格布局版本吗?我也许可以帮助你。
谢谢
- 因为您的包装器“菜单”没有自己的高度,请为其设置高度,例如:
.menu {
height: 4rem;
align-items: stretch
}
- 接下来,您应该添加“菜单项”:
.menu-item {
display: flex;
align-items: center;
}
我会保持基线对齐并考虑使用伪元素技巧来增加悬停区域:
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>
这是我稍微修正一下你的 css 后的结果。
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>