css - 可变宽度的弹性项目之间的等距分隔符
问题描述
我需要设计一个由 CMS 动态呈现的导航(所以我无法控制 HTML 标记)。菜单有一个未知的、可变数量的项目,并且所有项目都有一个可变的、未知的宽度。我需要将这些菜单项布置在一行中,它们之间的间距是等距的(很容易用 flexbox 完成),并且在间距的中间有一个视觉分隔符(这是我未解决的问题)。
下面是我到目前为止的代码。HTML 只是一个示例输出,我无法修改它。我也不允许使用 JS。CSS来自我自己,我可以完全控制它。
.mainnav {
width: 100%;
display: flex;
justify-content: space-between;
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid black;
}
.mainnav__item {
flex: 0 0 auto;
background-color: yellow;
position: relative;
white-space: nowrap;
}
.mainnav__item + .mainnav__item::before {
content: '';
width: 1px;
height: 100%;
background-color: red;
position: absolute;
left: -50%;
top: 0;
}
<ul class="mainnav">
<li class="mainnav__item">
<a class="mainnav__link" href="#">Short</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Looooooooooooooong</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Mediuuum</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">whatever else</a>
</li>
</ul>
我的问题是红色分隔线。它应该正好在中间,但我不知道如何计算水平位置。
谁能告诉我分隔符放置的唯一 CSS 解决方案?
该解决方案应该适用于常见的最新浏览器(当前版本的 [Android|Win] Chrome、[macOs|iOs] Safari、Firefox、Edge),但也适用于 IE11
解决方案
一种想法是在元素中考虑display:contents;
1li
并保持伪元素流入(删除position:absolute
)。这将使伪元素和a
成为弹性项目而不是li
元素,因此space-between
将完成这项工作。
只需注意浏览器支持,因为它是一项新功能。
.mainnav {
width: 100%;
display: flex;
justify-content: space-between;
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid black;
}
.mainnav__item {
flex: 0 0 auto;
position: relative;
white-space: nowrap;
display:contents;
}
.mainnav__item a {
background:yellow;
}
.mainnav__item + .mainnav__item::before {
content: '';
width: 1px;
display:block;
background-color: red;
}
<ul class="mainnav">
<li class="mainnav__item">
<a class="mainnav__link" href="#">Short</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Looooooooooooooong</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Mediuuum</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">whatever else</a>
</li>
</ul>
1元素本身不会生成任何 box,但它的子元素和伪元素仍然会生成 box 并且文本会正常运行。出于框生成和布局的目的,该元素必须被视为 已在元素树中被其内容替换(包括其源文档子项及其伪元素,例如 ::before 和 ::after伪元素,通常在元素的子元素之前/之后生成)。参考
另一个想法是调整flex-grow
和使用边框而不是依赖space-between
:
.mainnav {
display: flex;
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid black;
}
.mainnav__item {
flex: 0 0 auto;
position: relative;
white-space: nowrap;
flex-grow:2; /*middle elements need to grow twice that edge element*/
text-align:center;
border-left:1px solid red;
border-right:1px solid red;
}
.mainnav__item a {
background:yellow;
}
.mainnav__item:first-child {
flex-grow:1;
text-align:left;
border-left:none;
}
.mainnav__item:last-child {
flex-grow:1;
text-align:right;
border-right:none;
}
<ul class="mainnav">
<li class="mainnav__item">
<a class="mainnav__link" href="#">Short</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Looooooooooooooong</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">Mediuuum</a>
</li>
<li class="mainnav__item">
<a class="mainnav__link" href="#">whatever else</a>
</li>
</ul>
推荐阅读
- reactjs - mui 使用入口点插入范围阴影 DOM 样式时选择未设置样式的下拉选项
- r - 将 sjPlot::tab_model 表的列表保存在 word 文件或 RMarkdown 文件中
- r - 在雷达图中编辑 R 绘图轴标签
- c# - xamarin 表单中的 POST 请求
- linux - 是否可以从 Flutter linux 应用程序生成 linux .rpm 包?
- ios - 将 UITextInput 和 UITextView 放在 Container 或 UITableView 中?
- xcodebuild - 防止 `xcodebuild clean` 更新 SPM 依赖项
- amazon-web-services - Lambda 函数显示从存储桶获取对象时出错然后超时
- asp.net - 无法加载 Microsoft.Bcl.AsyncInterfaces
- python - QListWidget 复选框与项目选择同步