本站当前使用主题(2026-8-28)为Blowfish-第一次修改 完成 侧边栏去除 尺寸适应及导航闭环
Bludit Blowfish 主题深度改造复盘笔记|去侧边栏+全屏内容+导航下拉分类闭环
此主题是作者移植的,主题本身很优秀 但不适合我对过度复杂内容及多栏布局的审美 所以我决定宽屏
一、改造背景 & 原始问题
本次针对 Bludit CMS Blowfish 主题 进行布局重构与导航功能闭环优化,原始存在三大核心问题:
- 右侧侧边栏冗余:默认自带右侧边栏,挤占主体内容宽度,文章/首页阅读区域狭窄,视觉体验差。
- 顶部导航功能残缺:主题原生导航仅输出「静态页面」,无法展示博客分类栏目,无CMS级栏目管理能力。
- 分类展示逻辑冲突:原生分类仅在侧边栏插件输出,删除侧边栏后所有分类栏目直接消失,无替代展示方案。
二、分步改造流程 & 踩坑复盘(核心可复用)
阶段1:彻底移除右侧边栏,拓宽全站内容宽度
bludit-blowfish/
├── index.php
找到 sidebar.php 引入代码 注释,此时侧边栏就会消失 但还只是第一步
1.1 问题根源
仅注释 sidebar.php 引入代码无效,Bootstrap栅格空DOM容器仍占位,内容宽度无法自适应拓宽。
1.2 最终解决方案(修改 index.php 布局栅格)
- 文章页(带目录):原有 3(目录)+6(内容)+3(侧边空列) → 改为 3(目录)+9(内容),删除右侧空列
- 首页/普通页面(无目录):原有 8(内容)+3(侧边空列+偏移) → 改为 12(全屏内容),彻底删除右侧栅格容器
1.3 无效方案弃用记录
网上通用的「阅读宽度优化CSS」无效,原因是主题DOM选择器不匹配,直接舍弃,无需冗余样式代码。
阶段2:顶部导航改造,实现分类栏目动态调用
2.1 核心难点(高频踩坑点)
- Bludit 子模板
navbar.php作用域受限,无法直接调用Categories::getAll(),直接白屏(PHP致命错误)。 - 子模板无法直接读取
$dbCategories全局变量,报错空白。 - 子模板调用插件
siteSidebar()方法会导致程序状态错乱、全站白屏。
2.2 最终最优兼容方案(纯 navbar.php 单文件实现,不改动index)
通过 $GLOBALS['plugins'] 全局读取插件,复用原生Categories插件输出,正则解析分类列表,规避所有模板作用域报错问题:
- 不调用危险模板类、不修改主文件、无PHP报错
- 自动剥离分类文章计数后缀
(1)(3) - 自动匹配当前分类页面,实现导航active高亮
阶段3:导航栏目下拉收纳闭环(解决导航撑爆问题)
3.1 需求
分类数量不固定,平铺导航会冲破页面,需单按钮下拉收纳所有栏目,永久适配任意数量分类。
3.2 实现逻辑
- 先PHP收集所有分类存入数组,不直接平铺输出
- 套用 Bootstrap4 Dropdown 结构,顶部仅展示「分类 ≡」按钮
- 所有分类收纳下拉菜单内,彻底解决导航溢出问题
阶段4:自定义JS+CSS修复交互与样式BUG
4.1 交互问题
主题未加载Bootstrap Popper核心JS,原生下拉点击无响应。
解决方案:手写极简独立JS,无需依赖第三方库,实现:点击展开/收起、点击页面空白关闭下拉、无障碍属性适配。
4.2 样式问题
默认下拉白背景、浅色文字,深色主题下完全看不清。
解决方案:重写下拉全套样式,适配Blowfish深色主题,优化hover、active高亮状态,视觉统一。
三、最终完成效果(全部达标)
- 布局优化:彻底移除右侧侧边栏,首页、文章页内容全屏拓宽,阅读体验大幅提升。
- 导航功能闭环:顶部导航 = 博客入口 + 静态页面 + 分类下拉菜单 + 社交图标 + 搜索+主题切换,完整CMS导航结构。
- 无限适配栏目:任意数量分类均收纳下拉内,导航永不撑爆、永不错位。
- 动态自动更新:后台新增/删除/修改分类,导航自动同步,无需手动改代码。
- 状态正常:访问对应分类页面,下拉条目自动高亮,交互逻辑完整。
- 全兼容:不破坏主题原主题色切换、移动端折叠、插件钩子、页面布局逻辑。
四、可复用核心代码清单
4.1 index.php 布局优化核心(去侧边栏、拓宽内容)
修改Bootstrap栅格:无目录页面 col-md-8 → col-md-12,有目录页面 col-md-6 → col-md-9,删除右侧边栏栅格容器。
4.2 navbar.php 分类下拉完整代码
<?php
// 从已启用的Categories插件提取分类链接,复用插件本身输出
$catUlHtml = '';
$plugins = $GLOBALS['plugins'];
$navCatItems = [];
if (isset($plugins['siteSidebar'])) {
foreach ($plugins['siteSidebar'] as $plugin) {
$pluginOut = $plugin->siteSidebar();
if (strpos($pluginOut,'plugin-categories') !== false) {
if(preg_match('/<ul>(.*?)<\/ul>/s',$pluginOut,$matches)){
$catUlHtml = $matches[1];
}
break;
}
}
}
if (!empty($catUlHtml)) {
preg_match_all('/<li>\s*<a\s+href="([^"]+)">([^<]+)<\/a>/',$catUlHtml,$liMatches,PREG_SET_ORDER);
if (!empty($liMatches)) {
foreach ($liMatches as $item) {
$catHref = $item[1];
$catRawTitle = $item[2];
$catTitle = preg_replace('/\s*\(\d+\)$/','',$catRawTitle);
$activeClass = '';
if (isset($WHERE_AM_I, $url) && $WHERE_AM_I === 'category') {
$slugCheck = explode('/', rtrim($catHref,'/'));
$slugCheck = end($slugCheck);
if ($url->slug() === $slugCheck) {
$activeClass = ' active';
}
}
$navCatItems[] = [
'href' => $catHref,
'title' => $catTitle,
'active' => $activeClass
];
}
}
}
// 渲染Bootstrap4下拉组件,只占导航栏一个位置
if (!empty($navCatItems)):
?>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="catDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
分类 ≡
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="catDropdown">
<?php foreach ($navCatItems as $c): ?>
<a class="dropdown-item<?php echo $c['active']; ?>" href="<?php echo htmlspecialchars($c['href'],ENT_QUOTES); ?>">
<?php echo blowfish_text($c['title']); ?>
</a>
<?php endforeach; ?>
</div>
</li>
<?php endif; ?>
4.3 自定义下拉JS(页面底部 </body> 前插入,无依赖)
<script>
// 极简dropdown兼容脚本,适配Bootstrap4下拉DOM结构
document.addEventListener('DOMContentLoaded', function () {
const toggle = document.getElementById('catDropdown');
const menu = toggle?.nextElementSibling;
if(!toggle || !menu) return;
function closeDropdown(){
toggle.setAttribute('aria-expanded','false');
menu.classList.remove('show');
}
toggle.addEventListener('click', function(e){
e.preventDefault();
const expanded = toggle.getAttribute('aria-expanded') === 'true';
if(expanded){
closeDropdown();
}else{
toggle.setAttribute('aria-expanded','true');
menu.classList.add('show');
}
});
// 点击页面空白区域关闭下拉
document.addEventListener('click',function(e){
if (!toggle.contains(e.target) && !menu.contains(e.target)){
closeDropdown();
}
});
});
</script>
4.4 深色主题下拉适配CSS(追加到style.css末尾)
/* 下拉菜单基础样式,适配深色导航 */
.dropdown-menu {
background-color: #22262a !important;
border: 1px solid rgba(255,255,255,0.12);
}
/* 下拉条目文字颜色 */
.navbar-dark .dropdown-item {
color: rgba(255,255,255,0.85);
}
/* hover悬浮效果 */
.navbar-dark .dropdown-item:hover {
background-color: rgba(255,255,255,0.08);
color: #ffffff;
}
/* 当前激活分类高亮 */
.dropdown-item.active {
background-color: rgba(255,255,255,0.16);
color: #ffffff;
}
/* 下拉展开强制显示 */
.dropdown-menu.show {
display: block;
}
4.5 直接调用分类插件且动态输出栏目
demo1
<?php
// 从已启用的Categories插件提取分类链接,复用插件本身输出,避免类调用报错
$catUlHtml = '';
if (isset($plugins['siteSidebar'])) {
foreach ($plugins['siteSidebar'] as $plugin) {
$pluginOut = $plugin->siteSidebar();
// 匹配categories插件输出
if (strpos($pluginOut,'plugin-categories') !== false) {
// 只提取 <ul>...</ul> 部分
if(preg_match('/<ul>(.*?)<\/ul>/s',$pluginOut,$matches)){
$catUlHtml = $matches[1];
}
break;
}
}
}
// 把每一个 <li> 条目,输出成navbar需要的 nav-item nav-link
if (!empty($catUlHtml)) {
// 拆分出每一个li
preg_match_all('/<li>\s*<a\s+href="([^"]+)">([^<]+)<\/a>/',$catUlHtml,$liMatches,PREG_SET_ORDER);
foreach ($liMatches as $item) {
$catHref = $item[1];
$catRawTitle = $item[2];
// 去掉插件自带的计数后缀,例如 "(3)"
$catTitle = preg_replace('/\s*\(\d+\)$/','',$catRawTitle);
$activeClass = '';
if ($WHERE_AM_I === 'category' && $url->slug() === basename($catHref)) {
$activeClass = ' active';
}
echo '<li class="nav-item">';
echo '<a class="nav-link'.$activeClass.'" href="'.$catHref.'">'.blowfish_text($catTitle).'</a>';
echo '</li>';
}
}
?>
demo2
<?php
// 从已启用的Categories插件提取分类链接,复用插件本身输出,避免类调用报错
$catUlHtml = '';
$plugins = $GLOBALS['plugins']; // 直接从全局符号表读取插件对象
if (isset($plugins['siteSidebar'])) {
foreach ($plugins['siteSidebar'] as $plugin) {
$pluginOut = $plugin->siteSidebar();
// 匹配categories插件输出
if (strpos($pluginOut,'plugin-categories') !== false) {
// 只提取 <ul>...</ul> 部分
if(preg_match('/<ul>(.*?)<\/ul>/s',$pluginOut,$matches)){
$catUlHtml = $matches[1];
}
break;
}
}
}
// 把每一个 <li> 条目,输出成navbar需要的 nav-item nav-link
if (!empty($catUlHtml)) {
// 拆分出每一个li
preg_match_all('/<li>\s*<a\s+href="([^"]+)">([^<]+)<\/a>/',$catUlHtml,$liMatches,PREG_SET_ORDER);
if (!empty($liMatches)) {
foreach ($liMatches as $item) {
$catHref = $item[1];
$catRawTitle = $item[2];
// 去掉插件自带的计数后缀,例如 "(3)"
$catTitle = preg_replace('/\s*\(\d+\)$/','',$catRawTitle);
$activeClass = '';
if (isset($WHERE_AM_I, $url) && $WHERE_AM_I === 'category') {
$slugCheck = explode('/', rtrim($catHref,'/'));
$slugCheck = end($slugCheck);
if ($url->slug() === $slugCheck) {
$activeClass = ' active';
}
}
echo '<li class="nav-item">';
echo '<a class="nav-link'.$activeClass.'" href="'.htmlspecialchars($catHref,ENT_QUOTES).'">'.blowfish_text($catTitle).'</a>';
echo '</li>';
}
}
}
?>
4.6 增加公式前台解析
KaTeX 是目前最快的 LaTeX 渲染库,体积小、渲染速度快,完全满足博客常规公式需求。
只需要修改主题的 php/footer.php(或 index.php 底部 </body> 之前),插入以下代码:
<!-- KaTeX 样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css">
<!-- KaTeX 核心 JS -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js"></script>
<!-- 自动扫描渲染插件 -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js"
onload="renderMathInElement(document.body, {
delimiters: [
{left: '$$', right: '$$', display: true}, // 块级公式
{left: '$', right: '$', display: false}, // 行内公式
{left: '\\(', right: '\\)', display: false},
{left: '\\[', right: '\\]', display: true}
],
throwOnError: false
});">
</script>
五、关键踩坑总结(避坑核心)
- Bludit子模板严禁直接调用插件方法:会直接白屏,必须通过全局
GLOBALS读取。 - 栅格空DOM不删除,样式修改无效:去侧边栏必须删栅格容器,仅注释无用。
- 不要滥用主题原生API:子模板作用域有限,优先复用插件输出,规避类加载报错。
- Bootstrap下拉必须补全交互JS:仅靠CSS无法点击,主题默认缺失Popper。
- 默认下拉样式不兼容深色主题,必须手动重写配色。
六、改造最终闭环总结
本次改造实现了 Blowfish主题从“博客静态展示”到“完整CMS栏目站点” 的蜕变:
冗余侧边栏去除 → 内容视野最大化 → 缺失的分类导航补齐 → 栏目下拉收纳防溢出 → 交互样式适配修复 → 全站逻辑闭环、无BUG、可长期复用。
所有修改均为轻量化改造,不破坏主题原生功能、不新增插件、不产生冗余代码,适配主题更新,后续重装主题可直接复用全套方案。
以上为本人对问题的解决路径与总结,结果为AI总结 请谨慎判断!