我想把A号、B号和C号放在中间.

我怎么才能让D个人完全向右转呢?

之前:

enter image description here

之后:

enter image description here

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

推荐答案

以下是实现此布局的五个选项:

  • CSS定位
  • 带有不可见DOM元素的Flexbox
  • 带有不可见伪元素的Flexbox
  • Flexbox和flex: 1
  • CSS网格布局

Method #1: CSS定位 Properties

在flex容器上涂抹position: relative.

position: absolute应用于D项.

现在,这个项目是绝对定位在flex容器内.

更具体地说,D项从文档流中删除,但保持在nearest positioned ancestor的范围内.

使用CSS偏移属性topright将此元素移动到位.

li:last-child {
  position: absolute;
  top: 0;
  right: 0;
  background: #ddd;
}
ul {
  position: relative;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p {
  text-align: center;
  margin-top: 0;
}
span {
  background-color: aqua;
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>

One caveat对于这种方法来说,有些浏览器可能无法从正常流程中完全删除绝对定位的flex项.这会以非标准、意外的方式更改路由.更多详情:100


Method #2: Flex Auto Margins & Invisible Flex Item (DOM element)

auto margins和一个新的,不可见的弹性项目的组合,可以实现布局.

新的弹性项与项D相同,并放置在另一端(左侧边缘).

更具体地说,因为弹性对齐基于自由空间的分布,所以新项目是保持三个中间框水平居中的必要平衡.新项目的宽度必须与现有的D项目相同,否则中间的方框不会精确居中.

新项目将以visibility: hidden从视图中删除.

简而言之:

  • 创建D元素的副本.
  • 把它放在列表的开头.
  • 使用flex auto边距保持ABC居中,两个D元素从两端创造相等的平衡.
  • visibility: hidden应用于副本D

li:first-child {
  margin-right: auto;
  visibility: hidden;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
  <li>D</li><!-- new; invisible spacer item -->
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>


Method #3: Flex Auto Margins & Invisible Flex Item (pseudo-element)

此方法类似于#2,不同之处在于它在语义上更清晰,并且必须知道D的宽度.

  • 创建一个宽度与D相同的伪元素.
  • 将它放在容器的开头,编号为::before.
  • 使用flex auto边距来保持ABC完全居中,伪元素和D元素从两端创建相等的平衡.

ul::before {
  content:"D";
  margin: 1px auto 1px 1px;
  visibility: hidden;
  padding: 5px;
  background: #ddd;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>


Method #4: Add flex: 1 to left and right items

从上面的方法#2或#3开始,不用担心左右两个项目的宽度相等来保持平衡,只需给每个项目flex: 1分即可.这将迫使它们都消耗可用空间,从而使中间的项目居中.

然后,您可以将display: flex个项目添加到单个项目中,以便对齐它们的内容.

NOTE about using this method with 100:目前在Chrome、Firefox、Edge以及可能的其他浏览器中,速记规则flex: 1分解为:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

当容器上使用min-height时,flex-basis上的percentage unit (%)会导致此方法中断.这是因为,作为一般规则,子对象的百分比高度需要父对象的显式属性设置.

这是一条可以追溯到1998年(CSS Level 2年)的旧CSS规则,在某种程度上在许多浏览器中仍然有效.有关完整的详细信息,请参见herehere.

以下是user2651804 comments 中发布的问题说明:

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container>div {
  background: orange;
  margin: 5px;
}

#flex-container>div:first-child {
  flex: 1;
}

#flex-container::after {
  content: "";
  flex: 1;
}
<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>

解决方案是不使用百分比单位.试试px,或者干脆什么都不做(which is what the spec actually recommends,尽管事实上至少有一些主要浏览器出于任何原因附加了一个百分比单位).

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container > div {
  background: orange;
  margin: 5px;
}


/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */

#flex-container > div:first-child {
  flex: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex: 1;
  flex-basis: 0;
}


/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY

#flex-container > div:first-child {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}
 */
<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>


Method #5: CSS网格布局

这可能是最干净、最有效的方法.不需要绝对定位、伪元素或其他黑客手段.

只需创建一个包含多列的网格.然后将项目放置在中间和结束列中.基本上,只需将第一列留空即可.

ul {
  display: grid;
  grid-template-columns: 1fr repeat(3, auto) 1fr;
  grid-column-gap: 5px;
  justify-items: center;
}

li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p  { text-align: center; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>

Html相关问答推荐

窗口对象中是否有对<;html&>根元素的引用?

react :事件和转发器在特定代码段中不起作用

在FlexBox中将div拉伸到父div的完全高度

如何在将文本垂直居中的同时将文本右对齐?

为什么前端框架可以创建自定义属性,而我却被期望在挖掘之前添加数据

单独处理Button:Focus的多行按钮

如何突破安莉得分

try 更新我的Node.js应用程序中的用户,但我收到错误.然而,当我使用postman 时,更新工作正常

如何使用 HTML 将对象数组发送到 Nodejs Express

MUI 日期 Select 器要包含的日期

添加带有悬停动画的喜欢图标

一旦大于最大限制,JQuery 取消 Select 复选框

如何将内容放置在侧边栏旁边?

在DIV上应用梯度模糊未如预期工作

使用 R markdown 在 html 中包含图像

Mediawiki css/html 信息框创建空白行

在 SQL 中合并 HTML 表中的单元格

我正在使用 react-router-dom 并创建了一个固定的导航栏,它在每个网页上不断改变大小,我不知道为什么

如何在没有 JS 的情况下创建带搜索的 Select 菜单

当我希望它只横向滚动时,可滚动菜单也会上下移动