VitePress 代码框 CSS 魔改记录
本文档详细记录了在 feat/update-code-blocks 分支中对博客文章代码框进行 CSS 魔改的详细细节。
1. 涉及文件与位置
- 修改文件:[.vitepress/theme/style/post.scss](file:///opt/1panel/www/sites/blog.chgr.cc/index/.vitepress/theme/style/post.scss)
- 影响范围:文章页内所有带语言标记的代码块组件(
div[class*="language-"])
2. 修改前后的 CSS Diff 对比
diff
diff --git a/.vitepress/theme/style/post.scss b/.vitepress/theme/style/post.scss
index 16f15ca..555f4bd 100644
--- a/.vitepress/theme/style/post.scss
+++ b/.vitepress/theme/style/post.scss
@@ -251,23 +251,30 @@
div {
&[class*="language-"] {
position: relative;
- display: flex;
- flex-direction: row-reverse;
+ display: grid;
+ grid-template-columns: auto 1fr;
+ grid-template-rows: 36px 1fr;
+ grid-template-areas:
+ "header header"
+ "ln code";
border-radius: 12px;
background-color: var(--main-card-background);
border: 1px solid var(--main-card-border);
- padding-top: 36px;
margin: 1rem 0;
- overflow: hidden;
+ overflow: auto;
+ max-height: 450px;
+ width: 100%;
.copy,
.lang {
- position: absolute;
+ grid-area: header;
}
.lang {
- width: 100%;
- height: 36px;
+ position: sticky;
top: 0;
left: 0;
+ z-index: 3;
+ width: 100%;
+ height: 36px;
display: flex;
flex-direction: row;
align-items: center;
@@ -278,8 +285,10 @@
font-size: 18px;
}
.copy {
+ position: sticky;
top: 0;
right: 0;
+ z-index: 4;
width: 36px;
height: 36px;
display: flex;
@@ -290,9;9 +299,9 @@
font-family: "iconfont";
font-size: 20px;
font-style: normal;
- z-index: 1;
color: var(--main-font-color);
cursor: pointer;
+ margin-left: auto;
&::after {
content: "\e01c";
transition: color 0.3s;
@@ -324,12;17 @@
}
}
.line-numbers-wrapper {
+ grid-area: ln;
+ position: sticky;
+ left: 0;
+ z-index: 2;
padding: 6px 10px;
opacity: 0.6;
text-align: center;
user-select: none;
color: var(--main-font-second-color);
background-color: var(--main-card-second-background);
+ border-right: 1px solid var(--main-card-border);
.line-number {
display: flex;
align-items: center;
@@ -342,12;13 @@
}
}
pre {
+ grid-area: code;
margin: 0;
padding: 6px 10px;
width: 100%;
- overflow-y: auto;
+ overflow: visible;
user-select: text;
- border-left: 1px solid var(--main-card-border);
+ border-left: none;
code {
font-family: "Fira Code", var(--main-font-family), monospace;
font-optical-sizing: auto;3. 核心改进原理解析
3.1 容器网格化布局(CSS Grid)
将代码框的容器由 flex 弹性布局升级为 grid 网格布局。显式划分了以下三个区域:
header(首行 36px 高):放置代码块语言标签(.lang)和复制按钮(.copy)。ln(行号区):左侧根据行号字宽自动占位。code(代码正文区):右侧自适应宽度。
3.2 粘性滑动定位(CSS Sticky)
通过 position: sticky 实现内容在滚动时的智能悬浮:
- 首行 Header / 语言和复制按钮:在代码垂直滚动时,依然固定锁定在代码框顶部(
top: 0),并利用z-index确保在代码图层之上。 - 左侧行号(
.line-numbers-wrapper):在代码水平宽幅滚动时,始终粘性固定在代码框左侧(left: 0),不会随着代码的向右横移而滑出视野,提供了极佳的阅读辅助定位。
3.3 消除嵌套滚动条(Pre Overflow)
- 修改前:容器
overflow: hidden,而pre内核层定义了overflow-y: auto。在大代码块下,会造成容器与pre双重滚动嵌套,影响滚动反馈与页面手势。 - 修改后:将
pre的溢出限制设为overflow: visible,高度自适应,而将最外层代码容器div[class*="language-"]的限制设为max-height: 450px以及overflow: auto。所有的横向、纵向滚动全部收归外层容器统一打理,杜绝了嵌套滚动条,使页面滚动流畅自然。