创建导航栏的 3 种方法(CSS 网格布局)
今天,让我们使用 CSS 网格布局构建三种不同的导航栏布局,我将向您展示无需实际触及标记即可轻松更改项目的排列。
阅读全文或在 Youtube 上观看我的代码(TL;DW):
结果
标记
标记基本上是一个<header>
元素
- 徽标(羽毛)
- 三个导航项目和
- 用户菜单的突出显示项。
由于我们要制作三个不同的布局版本,因此 for 循环可以防止我们自己复制粘贴。
main
// generates the navbar three times
// each with different version classes
// version-1, version-2 & version-3
- for (let i=0; i<3; i++)
header(class="version-" + (i+1))
.logo
i.fas.fa-feather-alt
nav
ul.nav
li
a(href="#")
i.far.fa-chart-bar
| Dashboard
li
a(href="#")
i.far.fa-edit
| Projects
li
a(href="#")
i.far.fa-envelope-open
| Posts
a.user(href="#")
i.far.fa-user
| Jane Doe
基础知识、背景和变量
让我们首先设置一些定义背景和前景色的基本变量,以及一些在多个位置使用的过渡参数:
:root {
--background-color: #2b2b2b;
--foreground-color: rgba(255, 255, 255, 0.7);
--transition: 250ms ease-out;
}
每个导航栏也有自己的突出显示颜色,这就是为什么--color
变量在每个版本自己的 CSS 类的范围内定义的原因:
header {
&.version-1 {
--color: #ba4aff;
}
&.version-2 {
--color: #008aff;
}
&.version-3 {
--color: #22d1d3;
}
}
我们还要重置每个元素的 padding、margin 和 box-sizing。或者,您可以引入一个预先制作好的规范化/重置 CSS 文件,例如 normalize.css 或 sanitize.css。
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
作为一个额外的好处,这里是背景的代码,它只是三个不同的渐变以不同的角度堆叠在一起:
main {
background:
linear-gradient(322deg,
#ba4aff, rgba(#ba4aff, 0) 70%),
linear-gradient(178deg,
#008aff, rgba(#008aff, 0) 70%),
linear-gradient(24deg,
#00ffc6, rgba(#00ffc6, 0) 35%);
}
标题网格配置(外网格)
我们将使用两个嵌套的网格布局。<header>
元素上的外层布局仅用于提供导航栏的总体布局,以便标明徽标、导航栏和用户菜单的位置:
header {
display: grid;
gap: 0.5rem;
padding: 0.5rem;
width: 100%;
min-width: 750px;
border-radius: 0.5rem;
background: var(--background-color);
box-shadow: 2px 2px 8px 0px var(--background-color);
font-family: "Lato", sans-serif;
}
基本原则是为每个版本的导航栏提供不同的网格布局列和区域配置。模板区域是网格布局中一个命名的部分,可以通过提供区域名称来将元素分配给它。这就是它能够纯粹基于 CSS 代码更改元素位置的原因,因为只有通过切换或更改grid-template-areas
浏览器中的值才能调整元素的位置,而标记内部的顺序变得无关紧要:
header {
// logo (left), nav items (left), user menu (right)
&.version-1 {
grid-template-columns: min-content auto max-content;
grid-template-areas: "logo nav user";
> * {
place-self: start;
}
}
// logo (left), nav items (centered), user menu (right)
&.version-2 {
grid-template-columns: min-content auto max-content;
grid-template-areas: "logo nav user";
> * {
align-self: center;
}
.user {
justify-self: end;
}
.nav {
justify-content: center;
}
}
// user menu, nav items (centered), logo (right)
&.version-3 {
grid-template-columns: max-content min-content auto min-content;
grid-template-areas: "user nav . logo";
> * {
justify-self: end;
align-self: center;
}
}
}
密切关注中的价值观grid-template-columns
。
min-content
主要用于徽标,因为它应该始终占用尽可能少的空间。max-content
主要用于用户菜单,因为有两个单词,min-content
单词会产生自动换行,因为在这种情况下,带有的列会被最小化。max-content
其行为方式是最大化内容的空间,但仅使用所需的空间。auto
在我们的例子中,这意味着它占用了剩余的空间,这正是我们想要的导航项。
所以最后,我们需要做的就是将提到的那些标识符分配给grid-template-areas
导航栏的各个部分,这就是设置导航栏基本布局所需要的。
header {
.logo {
grid-area: logo;
}
.nav {
grid-area: nav;
}
.user {
grid-area: user;
}
}
导航网格配置(内网格)
导航项的网格(.nav
)是嵌套在外部网格内的网格布局,它定义了<header>
元素中的常规排列(徽标、导航项、用户菜单)。它使用 CSS 网格的自动流动机制。这意味着没有定义列的明确顺序,但是网格容器(.nav
)的每个直接后代元素都有自己的列。我们可以告诉网格布局如何处理未分配给网格中某个单元格或单元格组的元素。grid-auto-flow: column
告诉它为每个未分配的元素创建一个新列。将其设置为row
将导致它创建一个新行。grid-auto-columns
是用来告诉网格自动生成的列的大小的,这在我们的例子中非常棒,因为我们可以简单地告诉它,以适应内容而不包装它。
header {
.nav {
grid-area: nav;
display: grid;
grid-auto-flow: column;
grid-auto-columns: max-content;
gap: 0.5rem;
place-self: center;
height: 100%;
list-style: none;
> li {
display: inline-block;
}
}
}
链接和图标样式
现在,让我们深入了解一下样式的细节。标题导航栏中的每个链接都是一个弹性框,其内容垂直居中,并带有一些填充和圆角。
标记使用了一些 Font-awesome 图标,因此每个<i>
标签都被赋予了突出显示的颜色并渲染得稍微小一些,这样它就不会“压倒”文本。
header {
a {
// align content vertically
display: flex;
align-items: center;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
text-decoration: none;
color: var(--foreground-color);
> i {
margin-right: 0.5em;
color: var(--color);
font-size: 0.7em;
transition: all var(--transition);
}
}
}
链接悬停效果
对于悬停效果,我们将使用一个很棒的clip-path
效果。每个链接都会被赋予一个::after
伪元素,该伪元素以高亮颜色作为背景色,并clip-path
略微裁剪右下角。如果链接未悬停,它会位于左侧(不可见),悬停时它会向右移动,以覆盖链接区域。该z-index
设置确保高亮不会覆盖文本。
header {
a {
transition: all var(--transition);
position: relative;
overflow: hidden;
z-index: 1;
--slantness: 4rem;
&::after {
content: '';
position: absolute;
z-index: -1;
width: calc(100% + var(--slantness));
top: 0%;
bottom: 0%;
left: calc((100% + var(--slantness)) * -1);
clip-path: polygon(
0% 0%, 100% 0%,
calc(100% - var(--slantness)) 100%, 0% 100%
);
background: var(--color);
opacity: 0;
transition: all var(--transition);
}
&:hover {
color: white;
> i {
color: var(--background-color);
}
&::after {
opacity: 1;
left: 0%;
}
}
}
徽标和用户菜单
这个标志其实就是一个来自 Font Awesome 的羽毛图标,悬停时会变色。为了让它看起来更美观,左上角和右下角做了圆润处理,与羽毛的形状相得益彰,悬停时效果也很好。
header {
.logo {
grid-area: logo;
place-self: center;
margin-right: 1rem;
padding: 0.25rem;
border-radius: 0.25rem;
border-top-left-radius: 50%;
border-bottom-right-radius: 50%;
color: var(--color);
font-size: 2rem;
transition: all var(--transition);
&:hover {
background: var(--color);
color: var(--background-color);
}
}
}
为了让用户菜单稍微突出一些,我们用高亮颜色在内部添加了一个轻微的盒子阴影。使用边框也可以达到同样的效果,但盒子阴影的优点在于它不会影响盒子模型,从而保持元素的大小与其他元素一致。
header {
.user {
box-shadow: inset 0px 0px 0px 1px var(--color);
}
}