CSS 具有最大宽度、居中内容的网格布局

CSS Grid Layout with Max-Width, Centered Content

我正在学习 CSS 网格(我知道早就该学习了)。我挑战自己将相对标准的基于浮动的布局转换为网格,但无法弄清楚最后一部分。

我的目标是让内容(徽标 + 导航和侧边栏 + 内容)居中,并带有 max-width。例如,徽标 + 导航应具有 600 像素的 max-width。我还需要有一个覆盖整个视口宽度的实心填充背景(匹配可变高度 logo/nav 行的高度)。

第一列(徽标和边栏)应缩小以适合其内容 - 因此第一列的宽度仅与 logo/sidebar 之间的宽度一样宽。然后 nav/content 应填充 max-width.

允许的剩余 space

以下是我最好的尝试。主要内容的宽度没有填满一个max-width。相反,主要内容的宽度是徽标的宽度 + 250px(由网格列定义的宽度)。

我希望实现的是 - 将 Logo + Nav 的 max-width 定义为特定宽度(例如 600px),并缩小 Logo 列以适应其内容。

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-template-columns: auto 1fr 的 2 列 网格 ,以便 第一列 占据其内容的宽度(与logo/sidebar之间的宽度一样宽)并且第二列占据了剩余的space(注意我已将 max-width: 600px 设置为 网格容器 )。

I also have a requirement of having a solid fill background covering the full-width of the viewport (matching the height of the variable height logo/nav row)

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

  1. 首先修复logonav在第一行通过设置grid-rowgrid-column 属性

  2. 现在使用 伪元素 wrapper 与第一行重叠(但 stacked 下面使用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>

居中

网格容器水平居中比较简单。在父级上使用 flex 对齐属性:

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

最大宽度

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

.wrapper {
  flex: 600px 0 1;
}

这条规则说:

  • flex-basis: 600px(起始宽度)
  • flex-grow: 0(项目不能超过 600px)
  • flex-shrink: 1(项目可以缩小)

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


2 列布局

您写道:

The first column (logo and sidebar) should shrink to fit their content - so the first column is only as wide as the wider between logo/sidebar. The nav/content should then fill the remaining space allowed by the max-width.

试试这个:

.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>