Skip to content

导航栏原始代码\themes\butterfly\layout\includes\header\nav.pug

pug
nav#nav
  span#blog-info
    a.nav-site-title(href=url_for('/'))
      if theme.nav.logo
        img.site-icon(src=url_for(theme.nav.logo) alt='Logo')
      if theme.nav.display_title
        span.site-name=config.title
    if globalPageType === 'post' && theme.nav.display_post_title
      a.nav-page-title(href=url_for('/'))
        span.site-name=(page.title || config.title)
        span.site-name
          i.fa-solid.fa-circle-arrow-left
          span= '  ' + _p('post.back_to_home')

  #menus
    if theme.search.use
      #search-button
        span.site-page.social-icon.search
          i.fas.fa-search.fa-fw
          span= ' ' + _p('search.title')
    if theme.menu
      != partial('includes/header/menu_item', {}, {cache: true})

      #toggle-menu
        span.site-page
          i.fas.fa-bars.fa-fw

添加抽屉菜单5.5.2

#blog-info内添加抽屉菜单,用于快速导航到博主的相关链接

对比导航栏原始代码,修改如下

diff
nav#nav
  span#blog-info
+   span.site-page.nav-shortcuts
+     i.nav-shortcuts-icon.fa-brands.fa-bluesky
+     .nav-shortcuts-menu
+       each group in theme.nav.menu
+         .menu-group
+           .menu-group-title=group.title
+           .menu-group-list
+             each item in group.item
+               a.list-item(href=url_for(item.link), title=item.name)
+                 img.list-item-icon(src=item.icon alt=item.name)
+                 span.list-item-text=item.name
-   a.nav-site-title(href=url_for('/'))
+   a.site-page.nav-site-title(href=url_for('/') title ='首页')
+     i.fa-solid.fa-house
-     if theme.nav.logo
-       img.site-icon(src=url_for(theme.nav.logo) alt='Logo')
-     if theme.nav.display_title
-       span.site-name=config.title
-   if globalPageType === 'post' && theme.nav.display_post_title
-     a.nav-page-title(href=url_for('/'))
-       span.site-name=(page.title || config.title)
-       span.site-name
-         i.fa-solid.fa-circle-arrow-left
-         span= '  ' + _p('post.back_to_home')

  #menus
    if theme.search.use
      #search-button
        span.site-page.social-icon.search
          i.fas.fa-search.fa-fw
          span= ' ' + _p('search.title')
    if theme.menu
      != partial('includes/header/menu_item', {}, {cache: true})

      #toggle-menu
        span.site-page
          i.fas.fa-bars.fa-fw
css
/* 非顶部快捷按钮正常显示,默认会移除 */
#page-header.nav-fixed #nav #blog-info>a:first-child {
    display: inline;
}

#blog-info {
    display: flex; /* 内部元素横向排列 */
    overflow: visible !important; /* 溢出部分可见,不遮挡弹出菜单 */
}

/* 移除blog-info默认hover效果 */
#blog-info:hover {
    color: inherit !important;
}

#blog-info .nav-shortcuts {
    margin-right: 6px;
    height: 36px;
    vertical-align: middle;
    font-size: 17.5px;
    position: relative; /* 子绝父相 */
}

#blog-info .nav-site-title {
      height: 36px;
      vertical-align: middle;
      font-size: 17.5px;
}

#blog-info .nav-shortcuts .nav-shortcuts-menu {
    position: absolute;
    left: 0;
    top: 45px;
    font-size: 12px;
    opacity: 0;
    transform: scale(.8);
    transform-origin: top left;
    transition: 0.1s;
    color: #999;
    background-color: var(--card-bg);
    box-shadow: var(--card-box-shadow);
    border-radius: 12px;
    pointer-events: none; /* 阻止鼠标事件 */
}

#blog-info .nav-shortcuts .nav-shortcuts-menu::before {
    position: absolute;
    top: -25px;
    left: 0;
    width: 100%;
    height: 30px;
    content: "";
}

#nav #blog-info .nav-shortcuts:hover {
    color: var(--light-blue); /* 抽屉按钮hover颜色统一 */
}

#blog-info .nav-shortcuts:hover .nav-shortcuts-menu {
    opacity: 1; /* 显示时的透明度 */
    transform: scale(1); /* 缩放动画效果结束帧 */
    transition: 0.3s;
    top: 55px;
    pointer-events: auto; /* 恢复鼠标事件 */
}

#blog-info .nav-shortcuts .nav-shortcuts-menu .menu-group-title {
    margin: 8px 0 0 16px;
}

#blog-info .nav-shortcuts .nav-shortcuts-menu .menu-group-list {
    display: flex;
    width: 340px; /* 限制列表盒子宽度 */
    flex-wrap: wrap; /* 超出宽度换行 */
    flex-direction: row; /* 项目水平排列 */
    justify-content: space-between; /* 项目之间留间距 */
}

#blog-info .nav-shortcuts .nav-shortcuts-menu .menu-group:last-child .menu-group-list {
    margin: 0 0 8px; /* 增加底部高度 */
}

#blog-info .nav-shortcuts .nav-shortcuts-menu .menu-group-list a:hover {
    background: var(--text-bg-hover);
}

#blog-info .nav-shortcuts .nav-shortcuts-menu .menu-group-list .list-item {
    display: flex;
    width: 150px; /* 限制列表项目盒子宽度 */
    margin: 4px 8px;
    padding: 4px 8px !important;
    border-radius: 8px !important;
    align-items: center; /* 使内部元素垂直居中 */
}

#blog-info .nav-shortcuts .nav-shortcuts-menu .menu-group-list .list-item .list-item-icon {
    width: 24px;
    height: 24px;
    border-radius: 24px;
    background: white;
}

#blog-info .nav-shortcuts .nav-shortcuts-menu .menu-group-list .list-item .list-item-text {
    font-size: var(--global-font-size);
    color: var(--font-color);
    margin-left: .5rem;
    white-space: nowrap;
}

#blog-info .nav-shortcuts .nav-shortcuts-menu .menu-group-list a:hover .list-item-text {
    color: white;
}

在主题配置文件里配置抽屉链接

yml
nav:
  # Navigation bar logo image
  logo: 
  display_title:
  display_post_title:
  # Whether to fix navigation bar
  fixed: true
  menu:
    - title: 网页
      item:
        - name: 个人主页
          link: https://xdog.top/
          icon: https://cloud.tencent.com/favicon.ico
        - name: 我的导航
          link: https://nav.xdog.top
          icon: https://cloud.tencent.com/favicon.ico
    - title: 项目
      item:
        - name: 示例项目
          link: https://example.com/
          icon: https://cloud.tencent.com/favicon.ico

菜单栏居中5.5.2

分析导航栏原始代码可知,#nav是flex布局,子元素#menus靠右宽度是内容宽度,子元素#blog-info有一个默认属性flex=1,靠左占满导航栏剩余空间。

那么给#nav新增第三个子元素#nav-right,将#menus内的#search-button#toggle-menu移入#nav-right,然后分配flex=1并靠右显示即可让#menus自动居中。

diff
nav#nav
  span#blog-info
    a.nav-site-title(href=url_for('/'))
      if theme.nav.logo
        img.site-icon(src=url_for(theme.nav.logo) alt='Logo')
      if theme.nav.display_title
        span.site-name=config.title
    if globalPageType === 'post' && theme.nav.display_post_title
      a.nav-page-title(href=url_for('/'))
        span.site-name=(page.title || config.title)
        span.site-name
          i.fa-solid.fa-circle-arrow-left
          span= '  ' + _p('post.back_to_home')

  #menus
-   if theme.search.use
-     #search-button
-       span.site-page.social-icon.search
-         i.fas.fa-search.fa-fw
-         span= ' ' + _p('search.title')
    if theme.menu
      != partial('includes/header/menu_item', {}, {cache: true})

-     #toggle-menu
-       span.site-page
-         i.fas.fa-bars.fa-fw

+ #nav-right
+   if theme.search.use
+     #search-button
+       span.site-page.social-icon.search
+         i.fas.fa-search.fa-fw
+         span= ' '
+   if theme.menu
+     #toggle-menu
+       span.site-page
+         i.fas.fa-bars.fa-fw
css
#nav-right {
    flex: 1; /* 数值参考 #blog-info */
    display: flex; /* 转化为flex容器以支持justify-content */
    justify-content: right; /* 靠右显示 */
}

#nav.hide-menu #nav-right {
    flex: none; /* 恢复移动端布局 */
}

菜单栏动态标题5.5.2

需求:下划时标题从下往上出现,菜单往上消失;上划时标题往下消失,菜单从上往下出现。 分析主题可知:非顶部存在.nav-fixed,只有上划时.nav-visible才会出现。

对比导航栏原始代码

diff
nav#nav
  span#blog-info
    a.nav-site-title(href=url_for('/'))
      if theme.nav.logo
        img.site-icon(src=url_for(theme.nav.logo) alt='Logo')
      if theme.nav.display_title
        span.site-name=config.title
    if globalPageType === 'post' && theme.nav.display_post_title
      a.nav-page-title(href=url_for('/'))
        span.site-name=(page.title || config.title)
        span.site-name
          i.fa-solid.fa-circle-arrow-left
          span= '  ' + _p('post.back_to_home')

  #menus
    if theme.search.use
      #search-button
        span.site-page.social-icon.search
          i.fas.fa-search.fa-fw
          span= ' ' + _p('search.title')
    if theme.menu
      != partial('includes/header/menu_item', {}, {cache: true})
+     a.site-name.page-name(href="javascript:btf.scrollToDest(0, 500)" title="返回顶部")=(page.title || config.title)

      #toggle-menu
        span.site-page
          i.fas.fa-bars.fa-fw
css
/* 默认状态 */
div#menus {
    position: relative; /* 子绝父相 */
    display: flex; /* 使脱标标题居中 */
    justify-content: center; /* 使脱标标题居中 */
}
.site-name.page-name {
    position: absolute; /* 标题脱标,相对#menus定位 */
    transform: translateY(60px);
    transition: .3s;
    opacity: 0; /* 隐藏 */
    pointer-events: none; /* 阻止鼠标事件 */
    text-overflow: ellipsis; /* 文字溢出显示省略号 */
    overflow: hidden; /* 溢出隐藏 */
    white-space: nowrap; /* 不换行 */
}

/* 顶部下划状态 */
.nav-fixed .menus_items {
    transform: translateY(-60px); /* 菜单往上消失 */
    transition: .3s;
}
.nav-fixed .site-name.page-name {
    transform: translateY(0); /* 标题从下往上出现 */
    opacity: 1;
    transition: .3s;
    pointer-events: auto; /* 恢复鼠标事件 */
}

/* 上划状态 */
.nav-fixed.nav-visible .menus_items {
    transform: translateY(0); /* 菜单往下出现 */
    transition: .3s;
}
.nav-fixed.nav-visible .site-name.page-name {
    transform: translateY(60px); /* 标题往下消失 */
    opacity: 0;
    transition: .3s;
    pointer-events: none; /* 阻止鼠标事件 */
}

/* 限制不同视口下标题宽度 */
.hide-menu .site-name.page-name {
    display: none;
}
@media screen and (min-width: 768px) {
.site-name.page-name {
    max-width: 15.5rem;
}
}
@media screen and (min-width: 900px) {
.site-name.page-name {
    max-width: 25.5rem;
}
}
@media screen and (min-width: 1200px) {
.site-name.page-name {
    max-width: 45.5rem;
}
}

导航栏两边与内容对齐

  1. 修改themes\butterfly\layout\includes\header\nav.pug#nav下插入一个#nav-group子元素盒子作为下面元素的父元素,方便调整导航栏左右宽度
pug
nav#nav
  #nav-group
    span#blog-info
      a(href=url_for('/') title=config.title)
        if theme.nav.logo
          img.site-icon(src=url_for(theme.nav.logo))
        if theme.nav.display_title
          span.site-name=config.title
      
    #menus
      if (theme.algolia_search.enable || theme.local_search.enable || theme.docsearch.enable)
        #search-button
          a.site-page.social-icon.search(href="javascript:void(0);")
            i.fas.fa-search.fa-fw
            span=' '+_p('search.title')
      !=partial('includes/header/menu_item', {}, {cache: true})

      #toggle-menu
        a.site-page(href="javascript:void(0);")
          i.fas.fa-bars.fa-fw
  1. css调整
css
/* 限制导航栏内容最大宽度 */
#nav-group {
    max-width: 1400px;
    width: 100%;
    display: flex;
    align-items: center;
}

/* 导航栏两边留出相同宽度 */
@media screen and (min-width: 1400px) {
    #nav {
        padding: 0 calc((100% - 1400px + 2rem)/ 2)
    }
}
@media screen and (max-width: 1400px) {
    #nav {
        padding: 0 16px;
    }
}