文章内嵌代码块-macOS Style
Table of Contents
如果我要持续技术学习类的文章写作,将在文章中放置大量代码。
但是 Astro 默认的代码块样式(Shiki)不够美观,且缺少功能性。
在此尝试实现了类 macOS 的视觉效果,并添加多种功能。
就以此作为个人博客的第一篇学习文章吧!
功能实现
-
模拟 macOS 窗口栏
-
语言类型提示
-
复制按钮(手动去除 div 块带来的回车,实现紧密复制)
-
下拉 / 收起代码块(已调整至合适视图)
-
一定程度的抽象封装
需要注意的是,Astro v5 之后代码块行号记录不再能通过 config 显式开启。
原来只需要在 shikiConfig 中添加 lineNumbers: true 。
现在需要通过 CSS 来实现行号显示。
代码实现
-
容器与装饰
/* 基础容器 */ pre.astro-code { position: relative; overflow: hidden; margin-top: 1.5em; margin-bottom: 1.5em; padding: 0; max-width: 100%; box-sizing: border-box; border-radius: 8px; box-shadow: var(--box-shadow); font-size: 1rem; transition: max-height 0.3s ease-out; } /* 模拟 macOS 窗口栏 */ pre.astro-code::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2.5rem; background-color: #1e293b; background-image: radial-gradient(circle at 1.5rem 1.25rem, #ff5f56 0.375rem, transparent 0.375rem), radial-gradient(circle at 2.75rem 1.25rem, #ffbd2e 0.375rem, transparent 0.375rem), radial-gradient(circle at 4rem 1.25rem, #27c93f 0.375rem, transparent 0.375rem); background-repeat: no-repeat; z-index: 1; } /* 语言提示 */ pre.astro-code::after { content: attr(data-language); position: absolute; top: 0.375rem; right: 5.5rem; padding: 0.125rem 0.5rem; border-radius: 0.25rem; font-size: 1.25rem; font-weight: 600; text-transform: uppercase; z-index: 1; display: inline-block; } -
图标与按钮系统
/* [抽象基类] 布局核心:负责定位、尺寸与对齐 */ pre.astro-code .astro-code-icon-base { position: absolute; top: 0.25rem; width: 2rem; height: 2rem; padding: 0.125rem; border-radius: 0.25rem; display: flex; align-items: center; justify-content: center; } /* [交互组件] 按钮外观:负责点击反馈、背景与层级 */ pre.astro-code .astro-code-icon-btn { border: none; background-color: transparent; cursor: pointer; z-index: 3; transition: background-color 0.2s; outline: none; } pre.astro-code .astro-code-icon-btn:hover { background-color: rgba(0, 0, 0, 0.5); } /* [实例] 下拉/收回按钮 */ pre.astro-code .toggle-btn { right: 3.25rem; } /* [实例] 复制功能组 */ pre.astro-code .copy-btn, pre.astro-code .copy-success { right: 1rem; } /* 复制成功状态特有样式 */ pre.astro-code .copy-success { z-index: 4; opacity: 0; transition: opacity 0.2s; pointer-events: none; } pre.astro-code .copy-success.show { opacity: 1; } -
代码内容与行号
pre.astro-code > code { display: block; width: 100%; padding: 3.5rem 1.5rem 1.5rem 3rem; counter-reset: line; box-sizing: border-box; overflow: auto; max-height: 49rem; line-height: 0.75rem; } /* 折叠状态逻辑 */ pre.astro-code.collapsed > code { max-height: 22rem; } /* Shiki 行容器 */ .astro-code .line { display: block; position: relative; max-width: 100%; box-sizing: border-box; min-height: 0.75rem; } /* 自动行号生成 */ .astro-code .line::before { content: counter(line); counter-increment: line; position: absolute; top: 0; left: -3.3rem; width: 2.5rem; text-align: right; color: inherit; opacity: 0.7; user-select: none; pointer-events: none; }