博客 / 技术笔记

Astro 博客集成 Mac 风格代码块

前言

使用 Astro 搭建博客时,代码高亮是核心功能之一。astro-expressive-code 是一个优秀的代码块插件,但默认样式比较朴素。

本文记录如何为博客添加 Mac 风格的红黄绿三色窗口效果。

问题分析

astro-expressive-code 的终端代码块(bash/shell)默认会显示窗口样式,但存在以下问题:

  1. 三个点的透明度太低(默认 15%),几乎看不见
  2. 无法单独设置三个点的颜色(红/黄/绿)
  3. 复制按钮位置不理想

官方提供的 styleOverrides 配置有限,无法满足 Mac 风格需求。

解决方案

采用 JavaScript 动态注入 + CSS 样式覆盖 的方案:

  1. 页面加载后,用 JS 动态创建三个 <span> 元素
  2. 用 CSS 控制颜色、大小和位置
  3. 隐藏 Expressive Code 原有的元素

实现步骤

1. 动态注入 HTML 元素

src/layouts/BlogPost.astro<head> 中添加脚本:

<script is:inline>
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
document.querySelectorAll('.expressive-code .frame.is-terminal figcaption.header').forEach(function(header) {
// 避免重复添加
if (!header.querySelector('.mac-dots')) {
var dots = document.createElement('div');
dots.className = 'mac-dots';
dots.innerHTML = '<span class="dot-red"></span><span class="dot-yellow"></span><span class="dot-green"></span>';
header.insertBefore(dots, header.firstChild);
}
});
}, 100);
});
</script>

注意:必须使用 is:inline,否则 Astro 会将脚本打包,导致运行时找不到元素。

2. 添加 CSS 样式

src/styles/global.css 中添加:

/* 隐藏原有的三个点 */
.expressive-code .frame.is-terminal .dots,
.expressive-code .frame.is-terminal figcaption .dots {
display: none !important;
}
/* Mac 风格三个点容器 */
.mac-dots {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
display: flex;
gap: 8px;
}
/* 三个圆点 */
.mac-dots span {
width: 14px;
height: 14px;
border-radius: 50%;
}
/* 红黄绿颜色 */
.dot-red { background-color: #ff5f56; }
.dot-yellow { background-color: #ffbd2e; }
.dot-green { background-color: #27c93f; }
/* 复制按钮靠右 */
.expressive-code .copy {
margin-left: auto;
}

3. 配置 Expressive Code

astro.config.mjs 中可以微调一些基础配置:

expressiveCode({
themes: ['github-dark', 'github-light'],
frames: {
editorSwitcherTabs: false,
shadow: 'md',
frameBoxShadowCssValue: '0 8px 32px rgba(0,0,0,0.12)',
},
styleOverrides: {
borderRadius: '12px',
terminalTitlebarBackground: '#24292e',
terminalTitlebarForeground: '#ffffff',
},
})

效果预览

最终效果:

  • 🔴 红色关闭按钮
  • 🟡 黄色最小化按钮
  • 🟢 绿色最大化按钮
  • 复制按钮在标题栏右侧

技术要点总结

要点说明
is:inline脚本内联到 HTML,避免打包问题
!important强制覆盖第三方库样式
position: absolute精确定位元素
setTimeout等待 Expressive Code 渲染完成

相关资源


有问题或建议?欢迎留言讨论!