使用最大宽度的CSS网格布局,实现内容居中

7

我正在学习CSS Grid(非常迟到,我知道)。我挑战自己将一个相对标准的基于浮动的布局转换成网格,但无法理解最后一部分。

我的目标是拥有一个布局,其中内容(标志+导航和侧边栏+内容)居中,并具有max-width。例如,标志+导航应该具有600px的max-width。另外,我要求在变量高度的标志/导航行上覆盖全视口的实心填充背景。

第一列(标志和侧边栏)应缩小以适应其内容 - 因此第一列的宽度仅为标志/侧边栏之间的宽度。然后导航/内容应填充由max-width允许的其余空间。

以下是我最好的尝试。主要内容的宽度不会填满max-width。相反,主要内容的宽度为Logo + 250px的宽度(由网格列定义)。

我希望实现的是 - 将标志+导航的max-width定义为特定宽度(比如600px),并使标志列缩小以适应其内容。

body {
  margin: 40px;
}

.fill {
  grid-column-start: 1;
  grid-column-end: 6;
  grid-row-start: 1;
  grid-row-end: 1;
  background-color: gray;
}

.logo {
  grid-area: logo;
  font-size: calc(1rem + 4vw);
}

.sidebar {
  grid-area: sidebar;
}

.content {
  grid-area: content;
}

.nav {
  grid-area: nav;
  text-align: right;
}

.footer {
  grid-area: footer;
}

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: auto min-content 120px 120px auto;
  grid-template-areas: "... logo nav nav ..." "... sidebar content content ..." "... footer  footer  footer ...";
  background-color: #fff;
  color: #444;
}

.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 10px;
}

.header,
.footer {
  background-color: #999;
}
<div class="wrapper">
  <div class="fill"></div>
  <div class="box logo">Logo</div>
  <div class="box nav">Nav</div>
  <div class="box sidebar">Sidebar</div>
  <div class="box content">Content
    <br /> More content than we had before so this column is now quite tall.</div>
  <div class="box footer">Footer</div>
</div>

CSS Grid能否实现这一点,如果可以的话,如何实现?

你的问题自最初发布以来已经发生了根本性的变化,因此我的答案现在已经不完整。 - Michael Benjamin
可能是重复的问题: https://stackoverflow.com/q/53110368/3597276 - Michael Benjamin
2个回答

4

你可以使用grid-template-columns: auto 1fr创建一个两列网格,使得第一列的宽度与内容相同 (取决于logo/sidebar的宽度),而第二列则占用剩余的空间(请注意我已将max-width: 600px设置给了网格容器).

我还有一个要求,即使用实心填充背景覆盖整个视口的宽度(与可变高度的logo/nav行的高度相匹配)

为此,您可以执行以下操作:

  1. 首先,通过设置grid-rowgrid-column属性,在第一行中固定logonav

  2. 现在使用一个重叠在第一行上方的伪元素来对wrapper进行覆盖 (但是使用z-index属性将其堆叠在下面)。

  3. margin-left属性设置为calc(-50vw + 50%),并将width设置为100vw,以跨越整个视口拉伸实心填充背景

请查看以下演示:

body {
  margin: 40px;
}

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: auto 1fr; /* 2-column grid */
  /* background-color: #fff;*/
  color: #444;
  max-width: 600px; /* max-width of the layout */
  margin: 0 auto; /* center in the viewport */
}
.logo {
  font-size: calc(1rem + 4vw);
  grid-row: 1; /* fix the logo in the first row */
  grid-column: 1; /* fix the logo in the first column */
}
.nav {
  text-align: right;
  grid-row: 1;  /* fix the nav in the first row */
  grid-column: 2;  /* fix the nav in the second column */
}

.footer {
  grid-column: span 2; /* footer spans the two columns */
}

.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 10px;
}

.header,
.footer {
  background-color: #999;
}

.wrapper:after { /* position this in the first row */
  content: '';
  display: block;
  grid-row: 1;
  grid-column: 1/ 3;
  width: 100vw;
  margin-left: calc(-50vw + 50%);
  background: gray;
  z-index: -1; /* push it behind the first row */
}
<div class="wrapper">
  <div class="box logo">Logo</div>
  <div class="box nav">Nav</div>
  <div class="box sidebar">Sidebar</div>
  <div class="box content">Content
    <br /> More content than we had before so this column is now quite tall.</div>
  <div class="box footer">Footer</div>
</div>


我仍然希望标志/导航背后的实心填充可以延伸到整个页面的宽度,并与标志/导航行的高度相匹配。这是否可能? - Brett DeWoody
标志/导航行的高度是否固定? - Michael Benjamin
@BrettDeWoody 我认为你不能同时匹配 nav 的高度并强制 nav + logo 具有 max-width,除非也许 logo + nav 的高度是固定的... - kukkuz
@Michael_B Logo/导航栏行的高度是可变的,就像演示中一样(基于vw)。最终它将包含一个随着屏幕宽度调整大小的图像。 - Brett DeWoody
1
@kukkuz 很酷,我没想到伪元素可以与网格一起使用。 - Brett DeWoody

1

居中

水平居中网格容器相对简单。在父元素上使用flex对齐属性:

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

最大宽度

您可以使用max-widthflex属性在网格容器上创建最大宽度。

.wrapper {
  flex: 600px 0 1;
}

这个规则的意思是:

  • flex-basis: 600px(初始宽度)
  • flex-grow: 0(该项不能超过600像素扩展)
  • flex-shrink: 1(该项可以收缩)

这个命令本质上等同于 max-width: 600px


双栏布局

您写道:

第一栏(标志和侧边栏)应缩小以适应其内容 - 因此,第一栏的宽度仅为标志/侧边栏中较宽的宽度。 而导航/内容应占用剩余的最大宽度空间。

请尝试:

.wrapper {
  flex: 600px 0 1;
  display: grid;
  grid-template-columns: min-content 1fr;
}

body {
  margin: 40px;
  display: flex;
  justify-content: center;
}

.wrapper {
  flex: 600px 0 1;
  display: grid;
  grid-gap: 10px;
  grid-template-columns: min-content 1fr;
  grid-template-areas: "logo  nav" 
                       "sidebar content" 
                       "footer footer";
  background-color: #fff;
  color: #444;
}

.logo {
  grid-area: logo;
  font-size: calc(1rem + 4vw);
}

.sidebar {
  grid-area: sidebar;
}

.content {
  grid-area: content;
}

.nav {
  grid-area: nav;
  text-align: right;
}

.footer {
  grid-area: footer;
}

.fill {
  background-color: gray;
}


.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 10px;
}

.header,
.footer {
  background-color: #999;
}
<div class="wrapper">
  <div class="box logo">Logo</div>
  <div class="box nav">Nav</div>
  <div class="box sidebar">Sidebar</div>
  <div class="box content">Content
  <br /> These lines wrap when the text hits 600px maximum width. These lines wrap when the text hits 600px maximum width. These lines wrap when the text hits 600px maximum width. These lines wrap when the text hits 600px maximum width. These lines wrap when the text hits 600px maximum width. These lines wrap when the text hits 600px maximum width.</div>
  <div class="box footer">Footer</div>
</div>


这实际上让我找到了解决我的问题的方法,但我发现根据https://developer.mozilla.org/en-US/docs/Web/CSS/flex的说明,flex属性的语法是错误的。我已经提交了一个修复。 - undefined
@eflat,通常我们会看到flex的值按照flex-growflex-shrinkflex-basis的顺序列出。但是,虽然不常见,flex-basisflex-growflex-shrink的顺序也是完全有效的(请参阅上面链接中的“正式语法”部分。特别注意双竖线的含义)。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接