使用CSS Grid创建导航栏

8
我正在使用CSS网格创建导航栏。
我决定使用网格来重新排列部分(项目),而无需修改HTML(只需修改CSS)。
然后,我创建了一个带有3个区域的网格:logo、菜单和切换器。
我添加了一些间隔,以防止每个项目粘在一起。

enter image description here

到目前为止一切都很好,直到我尝试删除一个/一些部分,即使该部分已经消失,间隙仍然存在
然后我尝试删除间隙并将其替换为每个部分的边距。但是该边距不会在网格的开头/结尾处折叠。它的行为与常规块元素不同。
我知道使用flexbox比使用grid更实用,但我更喜欢grid,因为可以重新排列部分而无需修改html。可以将徽标移动到顶部或其他位置。这是使用flex无法实现的。
有人能解决我的grid-gap问题吗?或者您对创建导航栏有不同的方法吗?
请查看我的sandbox

.navbar {
  background: pink;
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: max-content auto max-content;
  grid-template-areas: "logo menus toggler";
  justify-items: stretch;
  align-items: stretch;
  column-gap: 20px;
}

.logo {
  background: green;
  grid-area: logo;
  width: 60px;
}

.menus {
  background: lightsalmon;
  grid-area: menus;
  display: flex;
  flex-direction: row;
  justify-content: start;
}

.menus * {
  padding: 5px;
}

.toggler {
  background: lightskyblue;
  grid-area: toggler;
}
<p>navbar with complete sections:</p>
<nav class="navbar">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without logo:</p>
<nav class="navbar">
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without toggler:</p>
<nav class="navbar">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
</nav>

4个回答

3
在这种情况下,您可以依赖隐含列。您只需定义一个明确的列,并且仅在元素存在时创建新列。您还可以轻松地解决问题并交换位置。

.navbar {
  background: pink;
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: 1fr; /* only column intially */
  grid-auto-flow:dense;
  justify-items: stretch;
  align-items: stretch;
  column-gap: 20px;
}

.logo {
  background: green;
  width: 60px;
  grid-column:-3; /* create an implicit one at the beginning */
}

.menus {
  background: lightsalmon;
  display: flex;
  flex-direction: row;
  justify-content: start;
  grid-column: 1; /* take the explicit one */
}

.menus * {
  padding: 5px;
}

.toggler {
  background: lightskyblue;
  grid-column:2; /* create an implicit one at the end */
}
<p>navbar with complete sections:</p>
<nav class="navbar">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without logo:</p>
<nav class="navbar">
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without toggler:</p>
<nav class="navbar">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
</nav>

<hr>
<p>navbar without toggler and log at the end </p>
<nav class="navbar">
  <div class="logo" style="grid-column:2">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
</nav>

<hr>

<p>navbar without logo and toogler at the beginning </p>
<nav class="navbar">
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler" style="grid-column:-3">
    X
  </div>
</nav>


3

在这种情况下,你可以尝试使用以下代码替代 column-gap: 20px;

nav > div:not(:first-child){
  margin-left:20px;
}

它为第一级div添加边距,并将第一个div从选择中排除。

.navbar {
  background: pink;
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: max-content auto max-content;
  grid-template-areas: "logo menus toggler";
  justify-items: stretch;
  align-items: stretch;
}

nav > div:not(:first-child){
  margin-left:20px;
}

.logo {
  background: green;
  grid-area: logo;
  width: 60px;
}

.menus {
  background: lightsalmon;
  grid-area: menus;
  display: flex;
  flex-direction: row;
  justify-content: start;
}

.menus * {
  padding: 5px;
}

.toggler {
  background: lightskyblue;
  grid-area: toggler;
}
<p>navbar with complete sections:</p>
<nav class="navbar">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without logo:</p>
<nav class="navbar">
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without toggler:</p>
<nav class="navbar">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
</nav>


1
这可以通过网格来实现,你完全正确,网格的优势在于似乎能够重新排列html元素。我认为问题在于你的列间距适用于所有三种情况,因为它是你的导航栏类的一部分。
.navbar {
    column-gap: 20px;
}

在下面的示例中,我使用相同的类创建了两个grid-area容器。我将column-gap应用于顶部容器,但未应用于底部容器。
我还在左侧的蓝色div上使用了justify-self: end,以向您展示列之间没有间隙,尽管您也可以使用chrome dev工具查看顶部网格具有间隙,而底部网格没有。

.container {
  display: grid;
  grid-template-areas: "left center right";
  margin-bottom: 40px;
}
.top {
  column-gap: 20px;
}
.bottom{
  column-gap: 0;
}

.d1 {
  grid-area: left;
  background: red;
}

.d2 {
  grid-area: center;
  background: red;
}

.d3 {
  grid-area: right;
  background: red;
}

.d4 {
  grid-area: left;
  background: blue;
  justify-self: end;
}

.d5 {
  grid-area: center;
  background: blue;
}

.d1,
.d2,
.d3,
.d4,
.d5 {
  width: 200px;
  height: 50px;
}
<div class="container top">
  <div class="d1"></div>
  <div class="d2"></div>
  <div class="d3"></div>
</div>

<div class="container bottom">
  <div class="d4"></div>
  <div class="d5"></div>
</div>


0
你可以为每个不同的导航创建CSS规则,因为如果你对每个导航使用相同的类,grid-template-columns和grid-template-areas就会有些固定。
grid-template-columns: max-content auto max-content;
grid-template-areas: "logo menus toggler";

我们正在寻找三列之间的间隔。

如果您编辑每个导航以与每个元素的列内容匹配,它将正确显示,无需任何破解。

.navbar1 {
  background: pink;
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: max-content auto max-content;
  grid-template-areas: "logo menus toggler";
  justify-items: stretch;
  align-items: stretch;
  column-gap: 20px;
}

.navbar2 {
  background: pink;
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: auto max-content ;
  grid-template-areas: "menus toggler";
  justify-items: stretch;
  align-items: stretch;
  column-gap: 20px;
}

.navbar3 {
  background: pink;
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: max-content auto;
  grid-template-areas: "logo menus";
  justify-items: stretch;
  align-items: stretch;
  column-gap: 20px;
}

.logo {
  background: green;
  grid-area: logo;
  width: 60px;
}

.menus {
  background: lightsalmon;
  grid-area: menus;
  display: flex;
  flex-direction: row;
  justify-content: start;
}

.menus * {
  padding: 5px;
}

.toggler {
  background: lightskyblue;
  grid-area: toggler;
}
<p>navbar with complete sections:</p>
<nav class="navbar1">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without logo:</p>
<nav class="navbar2">
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without toggler:</p>
<nav class="navbar3">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
</nav>


但是它需要额外的配置。我的目标是为我的消费者创建一个具有丰富特性的导航栏,只需最少的配置。 - Heyyy Marco

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