【问题标题】:Creating navbar with CSS grid使用 CSS 网格创建导航栏
【发布时间】:2021-04-19 23:35:18
【问题描述】:

我正在创建一个使用 CSS 网格制作的导航栏。

我决定用网格制作它,这样我就可以重新排列部分(项目)不修改 html(只需修改 CSS)。

然后我创建了包含 3 个区域的网格:徽标、菜单、切换器。

我加了一点空隙,这样每个项目就不会粘在一起了。

到目前为止一切顺利,直到我尝试删除一个/一些部分,差距仍然存在,即使该部分已经消失。

然后我尝试消除间隙并用每个部分的边距替换。 但是边距不会在网格的开始/结束处折叠。它的行为与常规块元素不同。

我知道使用 flexbox 比使用网格更实用,但我更喜欢网格,因为无需修改 html 即可重新排列该部分。可以将徽标移动到顶部或其他位置。 flex 是不可能的。

谁能解决我的网格间隙问题?或者,也许您有不同的方法来创建导航栏?

见我的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>

【问题讨论】:

    标签: html css css-grid


    【解决方案1】:

    在这种情况下,您可以依赖隐式列。您只定义一个显式列,并且仅当元素存在时才创建新列。您也可以轻松交换有问题的职位

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

    【讨论】:

    • 您的解决方案是我需要的最接近的要求。谢谢。
    【解决方案2】:

    在这种情况下,您可以试试这个,而不是 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>

    【讨论】:

      【解决方案3】:

      这完全可以用网格来完成,而且你完全正确地认为网格能够看似重新排列 html 元素的优势。我认为问题在于您的列间隙适用于所有三种情况,因为它是您的导航栏类的一部分

      .navbar {
          column-gap: 20px;
      }
      

      在下面的示例中,我使用同一个类创建了两个网格区域容器。我将 column-gap 应用于顶部容器,而不是底部容器。

      我还用 justify-self: end 为左边的蓝色 div 显示列之间没有间隙,虽然你也可以使用 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>

      【讨论】:

        【解决方案4】:

        您可以为每个不同的导航创建 css 规则,因为如果您为每个导航类使用相同的类,那么网格模板列和网格模板区域在某种程度上已经融入其中。

        grid-template-columns: max-content auto max-content;
        grid-template-areas: "logo menus toggler";
        

        正在寻找三列之间的差距。

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

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

        【讨论】:

        • 但它需要额外的配置。我的目标是为我的消费者创建一个功能丰富且配置最少的导航栏。
        猜你喜欢
        • 2021-12-09
        • 2018-12-06
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 2020-08-21
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多