【问题标题】:Center-align an item in a row of two items with CSS Grid or Flexbox使用 CSS Grid 或 Flexbox 将一行中的两个项目居中对齐
【发布时间】:2022-02-05 20:04:04
【问题描述】:

是否可以在不调整标记并使用 CSS Grid 或 Flexbox 的情况下实现以下布局?

+-------------------------+
||           ||          ||
|+-+         +-----------+|
|                         |
|                         |
|                         |
+-------------------------+

该行中有两个项目,第一个向左对齐,第二个与页面中心对齐,并将剩余宽度填充到右侧。我尝试了各种方法,例如没有宽度的空的第三个网格项目等,但没有运气。这是我最后一次尝试,很好地说明了这个问题。

header {
  display: grid;
  grid-template-columns: auto auto;
  justify-items: stretch;
}

ul {
  display: flex;
}

li:last-child {
  margin-left: auto;
}


/* for demo only */

ul {
  padding: 0;
  margin: 0;
  list-style: none;
}

li {
  padding: 5px;
  background: #aaa;
}

p {
  text-align: center;
}
<header>
  <span>Title</span>
  <nav>
    <ul>
      <li>Link 1</li>
      <li>Link 2</li>
      <li>Link 3</li>
    </ul>
  </nav>
</header>
<p>| true center |</p>

【问题讨论】:

  • the second aligned to the center of the page and filling the remaining width, with a right aligned child --> 对不起,但这没有意义...对齐到中心并填充剩余宽度?
  • @TemaniAfif 是的,我已经更新了描述以使其更清晰。
  • 好吧,这仍然令人困惑:) the second aligned to the center of the page and filling the remaining width to the right --> 如何将某些东西对齐到中心并同时填充宽度?这不合逻辑
  • @TemaniAfif 好吧,这就是问题所在。如果您运行 sn-p,示例应该是不言而喻的。
  • 不能单独使用 Grid/Flexbox,可以使用定位或 JS。

标签: html css flexbox css-grid


【解决方案1】:

这种布局将是 CSS 网格 subgrid 功能的完美用例场景,它允许网格容器的子代以外的子元素识别顶级网格容器线。

很遗憾,目前还没有主流浏览器支持此功能。 Technical development has been deferred,目前正在考虑使用CSS Grid Layout Module Level 2

更多:Positioning content of grid items in primary container (subgrid feature)

没有subgrid,布局仍然可以使用 Flex 和 Grid,但它可能会变得有些复杂,并且在某些情况下可能会中断。例如,使用 Flex/Grid,可以将两个外部项目固定到边缘,没问题。但根据屏幕大小和其他因素,两个内部项目可能居中、接近中心或偏离中心。

如果您在某些情况下可以接受一点偏心,那么 Flex/Grid 可能适合您。事实上,您可以通过媒体查询、负边距、transform 属性的translate() 函数或它们的组合来解决问题。再次,它变得复杂。

仅使用 CSS,最简单的解决方案是使用绝对定位。

(不更改 HTML。)

header, nav {
  position: relative;
}

ul {
  display: flex;
  justify-content: center;
}

li:last-child {
  position: absolute;
  right: 0;
}

span {
  position: absolute;
  left: 0;
}


/* for demo only */
ul {
  padding: 0;
  margin: 0;
  list-style: none;
}
li {
  padding: 5px;
  background: #aaa;
}
p {
  text-align: center;
}
<header>
  <span>Title</span>
  <nav>
    <ul>
      <li>Link 1</li>
      <li>Link 2</li>
      <li>Link 3</li>
    </ul>
  </nav>
</header>
<p>| true center |</p>

顺便说一句,由于您使用的是语义上有价值的nav 元素,因此实际上没有必要使用无序列表。这是一个更简单的版本:

header, nav {
  position: relative;
}

nav {
  display: flex;
  justify-content: center;
}

nav > div:last-child {
  position: absolute;
  right: 0;
}

header > div {
  position: absolute;
  left: 0;
}


/* for demo only */
nav > div {
  padding: 5px;
  background: #aaa;
}
p {
  text-align: center;
}
<header>
  <div>Title</div>
  <nav>
      <a>Link 1</a>
      <a>Link 2</a>
      <a>Link 3</a>
  </nav>
</header>
<p>| true center |</p>

【讨论】:

  • 感谢您提及subgrid,在阅读之后,这似乎是未来实现这一目标的正确方法。
【解决方案2】:

这是一个hacky的想法:

header {
  display: flex;
}
header span {
  min-width:0;
  width:0;
  flex-basis:0%;
  white-space:nowrap;
}
nav {
   margin-left: auto;
   flex-basis:100%;
}
ul {
  display: flex;
}

li:first-child {
  margin-left: auto;
}
li:nth-child(2) {
  margin-right:auto;
}

li:last-child {
  position:absolute;
  right:0;
}

/* for demo only */

ul {
  padding: 0;
  margin: 0;
  list-style: none;
  position:relative;
}

li {
  padding: 5px;
  background: #aaa;
}

p {
  text-align: center;
}
<header>
  <span>Title Title</span>
  <nav>
    <ul>
      <li>Link 1</li>
      <li>Link 2</li>
      <li>Link 3</li>
    </ul>
  </nav>
</header>
<p>| true center |</p>

【讨论】:

  • 这与我最初的示例没有什么不同。链接没有以页面为中心,这是最初的问题。
  • @DanChristian 我更新了我的代码,你可以再检查一下
【解决方案3】:

我在第二个 li 上添加了一个 .spacer 类,以便给它一个 flex-grow 并让它自动占据所有空白空间,因此将最后一个元素推到右侧。

还将标题样式更改为grid-template-columns: 1fr 1fr;,这样两个元素都占宽度的一半。

header {
  display: grid;
  grid-template-columns: 0.71fr 1fr;
  justify-items: stretch;
}

ul { display: flex; }
li.spacer{flex-grow: 1;} /* or li:nth-child(2) if you cannot add a class to the html tags */

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li a{ padding: 5px; background: #aaa; }
p  { text-align: center; }
<header>
	<span>Title</span>
	<nav>
		<ul>
			<li><a href="#">Link 1</a></li>
			<li class="spacer"><a href="#">Link 2</a></li>
			<li><a href="#">Link 3</a></li>
		</ul>
	</nav>
</header>
<p>| true center |</p>

【讨论】:

  • 很遗憾没有。除了右对齐的最后一个孩子之外,链接需要左对齐。
  • 我更新了代码。我为 li.spacer 添加了 css - 为了给它一个 flex-grow 以便自动占用所有空白空间,因此将最后一个元素推到右边。
  • 这与我最初的示例没有什么不同。链接没有以页面为中心,这是最初的问题。
  • 您最好给我们一张图片,说明您希望如何呈现链接并将其添加到您的答案中
  • 链接1和链接2要与页面中心对齐,即sn-p中的“真中心”段落标签表示。
【解决方案4】:

我发现这个解决方案最简单、最清晰。

header {
  display: grid;
  grid-template-columns: 1fr auto 1fr; /* magic here */
  align-items: center; /* optional */
}

ul { display: flex; }

span { justify-self: start; } /* magic here */
.right-link { justify-self: end; } /* magic here */

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
a{ padding: 5px; background: #aaa; }
p  { text-align: center; }
<header>
    <span>Title</span>
    <nav>
        <ul>
            <li><a href="#">Link 1</a></li>
            <li><a href="#">Link 2</a></li>
        </ul>
    </nav>
  <a href="#" class="right-link">Link 3</a>
</header>
<p>| true center |</p>

【讨论】:

    猜你喜欢
    • 2015-10-26
    • 1970-01-01
    • 2017-12-11
    • 2020-07-27
    • 2016-09-08
    • 2016-01-31
    • 1970-01-01
    • 2020-02-20
    相关资源
    最近更新 更多