前言
使用 Astro 搭建博客时,代码高亮是核心功能之一。astro-expressive-code 是一个优秀的代码块插件,但默认样式比较朴素。
本文记录如何为博客添加 Mac 风格的红黄绿三色窗口效果。
问题分析
astro-expressive-code 的终端代码块(bash/shell)默认会显示窗口样式,但存在以下问题:
- 三个点的透明度太低(默认 15%),几乎看不见
- 无法单独设置三个点的颜色(红/黄/绿)
- 复制按钮位置不理想
官方提供的 styleOverrides 配置有限,无法满足 Mac 风格需求。
解决方案
采用 JavaScript 动态注入 + CSS 样式覆盖 的方案:
- 页面加载后,用 JS 动态创建三个
<span>元素 - 用 CSS 控制颜色、大小和位置
- 隐藏 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 渲染完成 |
相关资源
有问题或建议?欢迎留言讨论!