因为喜欢写一些技术文章,因此代码在文章中的比例还是比较大的。给高亮代码弄个良好的外观很有必要。
一、哪些外观
1.顶部 banner 修饰
给多行代码顶部弄个 banner,是很多高亮代码都提供了的美学体现
2.代码语言
能让人一眼就了解代码所使用的语言也是一个不错的选择
3.代码折叠
很早之前就因为看到 csdn 上面的优雅的代码折叠功能而心动,于是实现了一下。但那时因为没有良师或者说是 AI 的帮助,思路不够开阔,只做了个默认全部展开,然后再通过按钮实现折叠。但初始那长长的代码总是影响了我的心情。
前段时间看到 小十 的博客及那个不错的代码折叠效果,又勾起了我优化的欲望,加上是因为现在 AI 解惑的能力确实很强,而且能够提供良好的思路,于是,我再次进行了修改,终于实现了良好的代码折叠功能。
- 默认对超过 5 行的代码折叠
- 默认可展开的代码添上遮罩层
二、代码实现
依托 highlight.js 实现。
- 在 pre 之前添加一个 banner,左侧添加伪元素(:before)显示 3 个不同颜色的圆点,右侧显示代码语言
- 在 code 下方,添加 1 个遮罩 div 及一个折叠按钮,按钮在折叠时不占空间(absolute),展开时则位于 code 下面
需要用到的 css 代码示例
/* 头部 banner */
.code-header {
position: relative;
background-color: rgba(200, 200, 200, 0.5);
height: 2rem;
padding-left: 10rem;
padding-right: 1rem;
margin-top: 0.75rem;
margin-bottom: 0px;
border-top-left-radius: 0.35rem;
border-top-right-radius: 0.35rem;
display: flex;
justify-content: end;
align-items: center;
}
.code-header:before {
content: "";
position: absolute;
border-radius: 50%;
background: #fc625d;
width: 0.8rem;
height: 0.8rem;
left: 0.7rem;
top: 0.7rem;
box-shadow: 1.4rem 0 #fdbc40, 2.8rem 0 #35cd4b;
}
/* pre标签 */
pre {
margin: 0;
margin-bottom: 0.75rem;
position: relative;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
letter-spacing: 0;
overflow: hidden;
}
/* 折叠高度 */
pre.collapsed {
max-height: 10rem;
}
/* pre code */
code.hljs {
position: static;
width: auto;
background-color: transparent;
font-size: 0.9em;
overflow-x: auto;
}
/* 遮罩层 */
.fade-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2rem;
background: -webkit-linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.5));
background: -moz-linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.5));
background: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.5));
}
/* 折叠按钮 */
.troggle-btn {
width: 100%;
display: flex;
align-items: end;
justify-content: center;
cursor: pointer;
}
.troggle-absolute {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}javascript 实现代码
// pre 操作
$(".post-content pre").each(function () {
const $pre = $(this);
const language = getLanguageFromPre(this); //代码语言获取方法
// 代码头部
const $header = $("<div>", {
class: "code-header",
html: `<span class="language">${language || "Code"}</span>`,
});
// 遮罩层
const $overlay = $("<div>", {
class: "fade-overlay",
});
// 折叠按钮
const $trogglebtn = $("<button>", {
class: "troggle-btn troggle-absolute",
html: `<i class="ri-arrow-down-double-line"></i>展开<i class="ri-arrow-down-double-line"></i>`,
});
// 添加头部
$pre.before($header);
//添加遮罩层及折叠按钮
$pre.append([$overlay, $trogglebtn]);
// 检查代码行数并添加折叠功能
const lineCount = $pre.text().split("\n").length;
if (lineCount > 5) {
$pre.addClass("collapsed");
$overlay.show();
$trogglebtn.show();
} else {
$overlay.hide();
$trogglebtn.hide();
}
// 绑定折叠/展开事件
$trogglebtn.on("click", function () {
const $btn = $(this);
const $codeContainer = $btn.closest("pre"); //查最近的祖先元素 pre
const $overlay = $codeContainer.find(".fade-overlay"); //查找 pre 下面的遮罩层
const $code = $codeContainer.find("code.hljs"); //查找代码体
if ($codeContainer.hasClass("collapsed")) {
// 展开
$codeContainer.removeClass("collapsed");
$overlay.hide();
$btn.html('<i class="ri-arrow-up-double-line"></i>折叠<i class="ri-arrow-up-double-line"></i>'); //用到了图标库样式
$btn.removeClass("troggle-absolute");
} else {
// 折叠
$codeContainer.addClass("collapsed");
$overlay.show();
$btn.html('<i class="ri-arrow-down-double-line"></i>展开<i class="ri-arrow-down-double-line"></i>');
$btn.addClass("troggle-absolute");
}
});
});
// 从pre标签下的code标签类名中提取语言代码
function getLanguageFromPre(preElement) {
const $pre = $(preElement);
const $code = $pre.find("code");
if ($code.length === 0) {
return null;
}
const classNames = $code.attr("class") || "";
// 查找 lang-xxx
const langMatch = classNames.match(/\blang-(\w+)\b/);
if (langMatch) return langMatch[1];
// 查找 language-xxx
const languageMatch = classNames.match(/\blanguage-(\w+)\b/);
if (languageMatch) return languageMatch[1];
return null;
}
By:ymz316
In:

以前记得你是折叠全部面板,我就模仿了下。现在改成局部折叠了,更棒了 哈哈
以前我也是想实现留几行的,但没头绪。
代码这东西我已经忘光了。
不过想说一下,感觉注释色彩和背景有点太接近,导致色彩偏淡,不是很清晰。可否加一点对比度。
下次看看能不能稍微亮一点点 😀