mcpField
T
tui-designer

tui-designer

github.com/ckorhonen设计与 UI2293 次安装5 周前更新
代码仓库

关于 tui-designer

用于设计复古与赛博朋克风格文本界面的技能,覆盖 React、SwiftUI、CSS 和 WebGL。内容包括 CRT 效果、霓虹样式、字体与配色、组件指导及常见实现问题。

主要功能

  1. 01CRT 与扫描线效果
  2. 02霓虹发光样式
  3. 03复古配色与字体
  4. 04React Tuimorphic 组件指导
  5. 05SwiftUI Metal 与 Web 技法
  6. 06跨平台问题与性能建议

适用场景

  1. 01设计终端风格界面
  2. 02为 SwiftUI 视图添加 CRT 效果
  3. 03构建霓虹风格 React 或 Web UI
  4. 04选择配色与等宽字体

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ckorhonen/claude-skills --skill tui-designer

安装后在 Claude Code 中输入/tui-designer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
color-palettes.md
copywriting-guide.md
crt-effects-web.md
design-patterns.md
metal-shaders-ios.md
tuimorphic-reference.md
typography-guide.md
scripts/
generate_palette.py
templates/
crt-shader.metal
neon-glow.css
react-tuimorphic-starter.tsx
swiftui-crt-view.swift

详细介绍

TUI 设计器 - 复古/赛博朋克终端 UI 专家

为设计和实现具有真实复古计算美学的文本界面提供专业指导:CRT 显示器、荧光粉辉光、扫描线和赛博朋克霓虹。

适用场景

适用于以下情况:

  • 创建终端风格或黑客美学的 UI
  • 实现 CRT 显示器效果(扫描线、辉光、桶形畸变)
  • 构建赛博朋克/合成波/复古波界面
  • 在 React 中使用 Tuimorphic 组件
  • 在 SwiftUI 中实现 Metal 着色器以呈现复古效果
  • 设计霓虹辉光文字和 UI 元素
  • 为复古计算美学选择配色方案
  • 使用等宽字体和制表符绘图字符

设计原则

复古/赛博朋克美学

这种美学源自:

  • CRT 显示器:荧光粉辉光、扫描线、屏幕曲率、闪烁
  • 终端界面:等宽字体、制表符绘图字符、绿色/琥珀色文字
  • 赛博朋克小说:霓虹色、深色背景、高对比度
  • 1980 年代计算机:ASCII 艺术、有限的配色方案、块状图形
视觉元素清单
  • 深色背景(近黑色,带微妙的色调)
  • 全程使用等宽字体
  • 使用制表符绘图字符绘制边框和框架
  • 文字和/或边框带有霓虹辉光
  • 扫描线效果(细微的水平线)
  • 有限的配色方案(1-3 种强调色)
  • 文字与背景之间具有高对比度
  • 可选:CRT 曲率、色差、闪烁

快速参考:配色方案

荧光绿(经典终端)
角色Hex用途
明亮#00ff00主要文字、高亮
中等#00cc00次要文字
深色#009900暗化元素
背景#001100主背景
深色背景#000800面板背景
赛博朋克霓虹
角色Hex用途
青色#00ffff主要强调色
洋红色#ff00ff次要强调色
电光蓝#0066ff第三强调色
亮粉色#ff1493警告
背景#0a0a1a主背景
琥珀色 CRT
角色Hex用途
明亮#ffb000主要文字
中等#cc8800次要文字
深色#996600暗化元素
背景#1a1000主背景

完整规范请参见 color-palettes.md。

排版

推荐字体

Web:

font-family: 'GNU Unifont', 'IBM Plex Mono', 'JetBrains Mono',
             'SF Mono', 'Consolas', monospace;

SwiftUI:

.font(.system(size: 14, weight: .regular, design: .monospaced))
制表符绘图字符
Light:   ─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼
Heavy:   ━ ┃ ┏ ┓ ┗ ┛ ┣ ┫ ┳ ┻ ╋
Double:  ═ ║ ╔ ╗ ╚ ╝ ╠ ╣ ╦ ╩ ╬
Rounded: ╭ ╮ ╰ ╯

完整参考请参见 typography-guide.md。

文案撰写

终端界面有独特的语气:简洁、技术化、权威。除非项目另有要求,否则采用以下默认原则。

核心原则
  1. 简洁直接 - 每个词都应发挥作用
  2. 技术权威感 - 系统清楚自己在做什么
  3. 机械般精准 - 不要模棱两可、道歉或使用填充词
文本格式
元素大小写示例
标题/名称全部大写SYSTEM STATUS
标签全部大写CPU USAGE:
状态指示器全部大写ONLINE、OFFLINE
命令/输入小写> run diagnostic
正文句首大写Connection established
消息前缀
[SYS] System message       [ERR] Error
[USR] User action          [WRN] Warning
[INF] Information          [NET] Network
词汇速查
操作终端动词
启动INITIALIZE、BOOT、LAUNCH、ACTIVATE
停止TERMINATE、HALT、ABORT、KILL
保存WRITE、COMMIT、STORE、PERSIST
加载READ、FETCH、RETRIEVE、LOAD
删除PURGE、REMOVE、CLEAR、WIPE
状态终端用语
处理中PROCESSING、EXECUTING、RUNNING
已完成COMPLETE、SUCCESS、FINISHED
失败ERROR、FAULT、ABORTED
就绪ONLINE、AVAILABLE、ARMED
常见模式
> INITIALIZING SYSTEM...
> LOADING MODULES [████████░░] 80%
> AUTHENTICATION COMPLETE
> SYSTEM READY

ERROR: ACCESS DENIED
ERR_CONNECTION_REFUSED: Timeout after 30s
WARNING: Low disk space (< 10%)

CONFIRM DELETE? [Y/N]
SELECT OPTION [1-5]:
避免
  • “Please”“Sorry”“Oops”
  • “Just”“Maybe”“Might”
  • 过多使用感叹号
  • 表情符号(除非特别要求)

完整的语气与风格指南请参阅 copywriting-guide.md。


平台:React 与 Tuimorphic

Tuimorphic 是一个 React 组件库,提供 37 个终端风格且易于访问的 UI 组件。

快速入门
npm install tuimorphic
import { Button, Card, Input } from 'tuimorphic';
import 'tuimorphic/styles.css';

function App() {
  return (
    <div className="theme-dark tint-green">
      <Card>
        <h1>SYSTEM ACCESS</h1>
        <Input placeholder="Enter command..." />
        <Button variant="primary">EXECUTE</Button>
      </Card>
    </div>
  );
}
主题配置

在父元素上通过 CSS 类应用主题:

// Dark mode with green tint
<div className="theme-dark tint-green">

// Light mode with cyan tint
<div className="theme-light tint-blue">

可用色调: tint-green、tint-blue、tint-red、tint-yellow、tint-purple、tint-orange、tint-pink

主要组件
组件用途
Button使用 variant="primary|secondary|ghost" 的操作
Input采用终端样式的文本输入
Card带有框线字符边框的容器
Dialog模态对话框
Menu下拉菜单
CodeBlock带语法高亮的代码
Table数据表格
Tabs标签页导航
TreeView文件树显示

完整 API 请参阅 tuimorphic-reference.md。

添加霓虹光晕

使用 CSS 光晕效果增强 Tuimorphic:

/* Neon text glow */
.neon-text {
  color: #0ff;
  text-shadow:
    0 0 5px #fff,
    0 0 10px #fff,
    0 0 20px #0ff,
    0 0 40px #0ff,
    0 0 80px #0ff;
}

/* Neon border glow */
.neon-border {
  border-color: #0ff;
  box-shadow:
    0 0 5px #0ff,
    0 0 10px #0ff,
    inset 0 0 5px #0ff;
}

/* Flickering animation */
@keyframes flicker {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.95; }
  52% { opacity: 1; }
  54% { opacity: 0.9; }
}

.flicker {
  animation: flicker 3s infinite;
}

平台:使用 Metal 着色器的 SwiftUI

iOS 17+ 支持通过 .colorEffect()、.distortionEffect() 和 .layerEffect() 在 SwiftUI 中直接使用 Metal 着色器。

CRT 效果实现

CRT.metal:

#include <metal_stdlib>
#include <SwiftUI/SwiftUI.h>
using namespace metal;

[[stitchable]] half4 crtEffect(
    float2 position,
    SwiftUI::Layer layer,
    float time,
    float2 size,
    float scanlineIntensity,
    float distortionStrength
) {
    float2 uv = position / size;

    // Barrel distortion
    float2 center = uv - 0.5;
    float dist = length(center);
    float2 distorted = center * (1.0 + distortionStrength * dist * dist);
    float2 samplePos = (distorted + 0.5) * size;

    // Bounds check
    if (samplePos.x < 0 || samplePos.x > size.x ||
        samplePos.y < 0 || samplePos.y > size.y) {
        return half4(0, 0, 0, 1);
    }

    // Sample color
    half4 color = layer.sample(samplePos);

    // Scanlines
    float scanline = sin(position.y * 3.14159 * 2.0) * scanlineIntensity;
    color.rgb *= 1.0 - scanline;

    // Subtle color shift (chromatic aberration)
    color.r *= 1.0 + 0.02 * sin(time * 2.0);
    color.b *= 1.0 - 0.02 * sin(time * 2.0);

    // Slight flicker
    color.rgb *= 1.0 + 0.01 * sin(time * 60.0);

    return color;
}

SwiftUI 视图修饰符:

struct CRTEffectModifier: ViewModifier {
    @State private var startTime = Date()
    var scanlineIntensity: Float = 0.1
    var distortionStrength: Float = 0.1

    func body(content: Content) -> some View {
        TimelineView(.animation) { timeline in
            let time = Float(timeline.date.timeIntervalSince(startTime))
            GeometryReader { geo in
                content
                    .layerEffect(
                        ShaderLibrary.crtEffect(
                            .float(time),
                            .float2(geo.size),
                            .float(scanlineIntensity),
                            .float(distortionStrength)
                        ),
                        maxSampleOffset: .init(width: 10, height: 10)
                    )
            }
        }
    }
}

extension View {
    func crtEffect(
        scanlines: Float = 0.1,
        distortion: Float = 0.1
    ) -> some View {
        modifier(CRTEffectModifier(
            scanlineIntensity: scanlines,
            distortionStrength: distortion
        ))
    }
}

用法:

Text("SYSTEM ONLINE")
    .font(.system(size: 24, weight: .bold, design: .monospaced))
    .foregroundColor(.green)
    .crtEffect(scanlines: 0.15, distortion: 0.08)
SwiftUI 中的霓虹光晕
extension View {
    func neonGlow(color: Color, radius: CGFloat = 10) -> some View {
        self
            .shadow(color: color.opacity(0.8), radius: radius / 4)
            .shadow(color: color.opacity(0.6), radius: radius / 2)
            .shadow(color: color.opacity(0.4), radius: radius)
            .shadow(color: color.opacity(0.2), radius: radius * 2)
    }
}

// Usage
Text("NEON")
    .font(.system(size: 48, design: .monospaced))
    .foregroundColor(.cyan)
    .neonGlow(color: .cyan, radius: 15)

完整着色器代码请参阅 metal-shaders-ios.md。


平台:CSS/原生 Web

扫描线叠加层
.crt-container {
    position: relative;
    background: #000800;
}

.crt-container::after {
    content: '';
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        0deg,
        rgba(0, 0, 0, 0.15),
        rgba(0, 0, 0, 0.15) 1px,
        transparent 1px,
        transparent 2px
    );
    pointer-events: none;
}
霓虹文字效果
.neon-text {
    color: #0ff;
    text-shadow:
        /* White core */
        0 0 5px #fff,
        0 0 10px #fff,
        /* Colored glow layers */
        0 0 20px #0ff,
        0 0 30px #0ff,
        0 0 40px #0ff,
        0 0 55px #0ff,
        0 0 75px #0ff;
}
CRT 曲率(CSS 变换)
.crt-screen {
    border-radius: 20px;
    transform: perspective(1000px) rotateX(2deg);
    box-shadow:
        inset 0 0 50px rgba(0, 255, 0, 0.1),
        0 0 20px rgba(0, 255, 0, 0.2);
}
使用 CRTFilter.js 的 WebGL CRT
<script type="module">
import { CRTFilterWebGL } from 'crtfilter';

const canvas = document.getElementById('crt-canvas');
const crt = new CRTFilterWebGL(canvas, {
    scanlineIntensity: 0.15,
    glowBloom: 0.3,
    chromaticAberration: 0.002,
    barrelDistortion: 0.1,
    staticNoise: 0.03,
    flicker: true,
    retraceLines: true
});

crt.start();
</script>

完整实现技巧请参阅 crt-effects-web.md。


效果模式

扫描线
平台实现方式
CSSrepeating-linear-gradient 伪元素
SwiftUI使用 sin(position.y * frequency) 的 Metal 着色器
WebGL片段着色器亮度调制
泛光/光晕
平台实现方式
CSS使用多个模糊度递增的 text-shadow
SwiftUI使用多个 .shadow() 修饰符
WebGL高斯模糊通道 + 加法混合
Three.js使用 luminanceThreshold 的 UnrealBloomPass
色差
平台实现方式
CSS三个重叠元素,颜色通道各有偏移
SwiftUI对每个 RGB 通道在偏移位置采样纹理
WebGL对每个通道在略微偏移的 UV 位置采样
闪烁
平台实现方式
CSS使用 @keyframes 动画改变不透明度(0.9-1.0)
SwiftUI由计时器驱动的不透明度变化,或基于着色器时间的效果
WebGL基于时间的噪声乘数

性能注意事项

CSS 效果
  • box-shadow 和 text-shadow 由 GPU 加速,但图层过多时开销较大
  • 光晕效果的阴影图层限制在 4-5 层
  • 对动画元素使用 will-change: transform
  • 考虑使用 prefers-reduced-motion 媒体查询
SwiftUI/Metal
  • 支持 iOS 17+ 的所有设备上,Metal 着色器的运行帧率为 60-120fps
  • .layerEffect() 会处理每个像素,因此着色器应保持简单
  • 使用 .compile() 预编译着色器(iOS 18+)
  • 在较旧设备上测试(iOS 17 最低要求为 A12)
WebGL
  • CRTFilter.js 使用硬件加速,对性能影响极小
  • Three.js 中的泛光效果需要渲染到纹理的通道
  • 移动设备可考虑使用较低分辨率的渲染目标
通用建议
  • 降低移动设备上的效果强度
  • 提供关闭效果的选项以满足无障碍需求
  • 使用实际内容进行性能分析,而不只是空白屏幕

模板

可直接使用的入门文件:


常见问题

本节记录了会导致 TUI 实现出错的真实故障模式和边缘情况。这些问题不易察觉,是在跨平台的实际使用中发现的。

终端兼容性问题

问题: 不同终端模拟器对转义序列的支持各异。在 iTerm2 中有效的内容,可能在旧版 xterm、SSH 终端或 Windows Terminal 中失效。

常见故障:

  • 256 色与 ANSI: 各终端支持的色彩深度不同。使用 #rgb 十六进制颜色的代码在现代终端中有效,但在旧系统中会退回到 16 色 ANSI。
  • 重置序列: 忘记重置文本属性(\x1b[0m 或 \x1b[m)可能会污染终端状态,影响后续输出。
  • Windows 上的 Unicode 制表符: Windows PowerShell/Terminal 可能无法正确渲染 ─ │ ┌ ┐。发布前请在 Windows 上测试。
  • VT100 支持不完整: SSH 连接到较旧的 Linux 系统时,通常只能使用 VT100 支持。制表符会显示为乱码。

预防措施:

  • 在目标终端上测试:iTerm2、Terminal.app、Windows Terminal、SSH Linux、Alacritty
  • 制表符无法正常显示时退回到 ASCII:使用 +、-、| 作为替代
  • 设置样式的文本后始终重置属性:\x1b[0m 可以解决问题
  • 检测终端功能:检查 TERM 环境变量(TERM=xterm-256color 与 TERM=xterm)

安全封装示例:

const supportsUnicode = process.env.TERM && process.env.TERM.includes('256');
const border = supportsUnicode ? '─' : '-';
调整大小时布局错乱

问题: 终端调整大小时,固定宽度布局会崩溃。在宽高比意外变化的基于 Web 的 TUI 中尤为常见。

常见故障:

  • 硬编码行宽: 假设宽度为 80 列的居中标题,在 60 列终端中会错乱。
  • 隐藏溢出但未截断: 内容宽度为 100% 再加上内边距,超出容器后会导致文本溢出或意外换行。
  • 宽高比假设: 扫描线叠加效果和 CRT 曲线假设宽高比为 16:9。在超宽屏或移动设备上,瑕疵会很明显。
  • 网格布局使用固定尺寸项: 使用 display: grid 和 grid-template-columns: 100px 200px 100px 无法适应小屏幕。

预防措施:

  • 使用相对于视口的单位:vw、vh 或 calc(100% - Xpx)
  • 使用省略号截断文本:overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  • 在以下宽度下测试:120 列、80 列、40 列(移动设备)、超宽屏
  • 对于扫描线效果,使用随视口缩放的百分比频率
  • 使用 CSS @media 或 JS ResizeObserver 动态调整布局

有问题的扫描线示例:

/* ❌ Breaks on narrow screens */
background: repeating-linear-gradient(0deg, transparent, transparent 20px, black 20px, black 21px);

更好的做法:

/* ✅ Scales with viewport height */
background: repeating-linear-gradient(0deg, transparent, transparent calc(2% of height), black calc(2% of height), black calc(2% of height + 1px));
输入处理边缘情况

问题: 用户输入不只有字母和数字。现实中的输入还包括多字节 UTF-8、特殊按键、粘贴缓冲区和自动补全。

常见故障:

  • UTF-8 字符计数: JavaScript 的 string.length 计算的是 UTF-16 代码单元,而不是字符。一个 4 字节表情符号 🎮 的值为 length: 2,会导致光标定位和验证出错。
  • 粘贴缓冲区处理: 用户会粘贴大段文本。未采用流式处理的输入处理器会导致 UI 卡顿。
  • 方向键与 WASD: 基于终端的游戏通常只支持 WASD,但用户期望能用方向键。缺少支持会导致糟糕的用户体验。
  • 特殊按键无法正常传递: Ctrl+C、Ctrl+Z、Tab 在不同平台上的行为各不相同。SSH 终端会丢失某些组合键。
  • IME 组合输入: 输入法引擎(用于中文、日文和韩文)会在最终组合完成前发送部分字符。每次按键都进行验证会导致 IME 输入出错。

预防措施:

  • 使用能识别字素的库:Intl.Segmenter(现代方案),或 npm 包 graphemesplitter
  • 将粘贴内容作为多字符流处理,而不是单个事件
  • 导航时同时支持方向键和 WASD
  • 处理 IME:仅在最终的 compositionend 时验证,不要在 compositionupdate 时验证
  • 在 macOS(Command 键)、Windows(Alt)和 Linux(各种 WM 行为)上测试

正确的 UTF-8 光标定位方式:

// ❌ Wrong: counts UTF-16 code units
const cursorPos = input.value.length;  // "🎮🎮" = length: 4

// ✅ Correct: counts grapheme clusters
const segmenter = new Intl.Segmenter();
const cursorPos = [...segmenter.segment(input.value)].length;  // "🎮🎮" = 2
性能问题

问题: TUI 效果(扫描线、发光、闪烁)开销很大。简单实现会导致卡顿以及 CPU 和电池耗电。

常见故障:

  • 持续重绘: 每帧都通过 JS 更新 DOM(而不是 GPU),每秒会触发 60 次以上重排,导致动画卡顿,CPU 占用率超过 100%。
  • 文本阴影层过多: 每个 text-shadow: 0 0 5px, 0 0 10px, 0 0 20px, ... 都需要单独的 GPU 渲染通道。10 层以上的阴影会造成明显延迟。
  • 高频闪烁: 用于闪烁效果的 setInterval(..., 16ms) 与动画帧时间绑定,主线程繁忙时会导致卡顿。
  • 扫描线叠层重新计算: 每次调整大小时都重新计算 repeating-linear-gradient(且未进行防抖)会导致卡顿。
  • 未进行限流的 WebGL: 在低端移动设备上以 120fps 运行全屏 CRT 着色器会迅速耗尽电池。

预防措施:

  • 使用 CSS @keyframes 实现持续效果(由 GPU 加速)
  • 将霓虹发光限制在 3-4 层文本阴影;在移动设备上测试
  • 对调整大小的处理器进行防抖:使用带限流的 ResizeObserver,或 window.requestAnimationFrame
  • 对需要动画的元素谨慎使用 will-change: transform, filter
  • 提供减少动态效果选项:prefers-reduced-motion: reduce
  • 在移动设备上检测 CPU 性能:对低功耗设备降低效果更新频率

性能良好的闪烁效果:

/* ✅ GPU-accelerated, smooth */
@keyframes flicker {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.95; }
}
.flicker { animation: flicker 3s infinite; }

会导致卡顿的闪烁效果:

// ❌ Main thread blocked, stutter
setInterval(() => {
  element.style.opacity = Math.random() > 0.5 ? 1 : 0.9;
}, 50);
无障碍支持缺失

问题: 终端 UI 往往忽视无障碍需求。屏幕阅读器、键盘导航和颜色对比度都可能存在问题。

常见问题:

  • 不支持键盘导航: 可点击元素只能通过鼠标操作。屏幕阅读器用户和仅使用键盘的用户都会受阻。
  • 仅用颜色表示状态: 错误显示红色文本,成功显示绿色文本。色盲用户(男性占 8%,女性占 0.5%)无法区分。
  • 缺少 ARIA 标签: 屏幕阅读器只会播报“按钮”,而不是“执行命令”。这会让盲人用户感到困惑。
  • 文本大小固定: 48px 的霓虹光效看起来很酷,但对视力受损的用户而言,缩小到 14px 就会出问题。不支持缩放就意味着无障碍性不足。
  • 没有焦点指示器: 按 Tab 键导航到按钮后,没有可见的焦点环。用户会找不到当前位置。
  • 动画元素无法暂停: 闪烁和扫描线可能引发光敏性癫痫。缺少 prefers-reduced-motion 支持会带来法律和安全风险。

预防措施:

  • 实现完整的键盘导航:Tab/Shift+Tab、按 Enter 激活、使用方向键操作列表
  • 使用屏幕阅读器进行测试:VoiceOver(macOS)、NVDA(Windows)、JAWS
  • 添加 ARIA 标签:aria-label="Start system"、aria-describedby="help-text"
  • 确保文本对比度达到 4.5:1(WCAG AA 标准)
  • 提供 prefers-reduced-motion 替代方案:禁用闪烁、扫描线和动画
  • 焦点指示器::focus { outline: 2px solid #0ff; } 是必需的

无障碍霓虹按钮:

<button
  aria-label="Execute diagnostic"
  className="neon-button"
  onClick={handleClick}
  onKeyDown={(e) => e.key === 'Enter' && handleClick()}
>
  EXECUTE
</button>

<style>
  .neon-button:focus {
    outline: 2px solid #0ff;
    outline-offset: 2px;
  }
  
  @media (prefers-reduced-motion: reduce) {
    .neon-button {
      text-shadow: none; /* Remove glow */
      animation: none;   /* Remove flicker */
    }
  }
</style>
终端模拟器差异

平台特定行为速查:

模拟器显著特性修复方法
iTerm2(macOS)可正确渲染所有 Unicode;支持真彩色无需处理
Terminal.app(macOS)调色板有限;行为类似旧版 xterm使用 256 色模式进行测试
Alacritty速度极快;支持真彩色;可能无法渲染部分 Unicode如果 iTerm2 可正常工作,则运行可靠
Windows Terminal支持真彩色;WSL 集成良好现代代码无需处理
PowerShell旧版本会将框线字符渲染为 ?;请使用备用方案检查 $PSVersionTable
SSH/xterm仅支持 VT100;不支持真彩色和鼠标事件回退到 ASCII 和 ANSI 颜色
Tmux真彩色需要直通模式:set -g default-terminal "tmux-256color"配置 tmux.conf
Screen支持的终端更旧;避免使用复杂效果使用纯 ASCII 模式

平台检测示例:

if [[ "$TERM" == "xterm" ]]; then
  # Old terminal: use ASCII
  BORDER="+"
  COLORS="ANSI"
elif [[ "$TERM" == *"256color"* ]]; then
  # Modern terminal: use box-drawing + 256 colors
  BORDER="─"
  COLORS="256"
else
  # Unknown: default to safe
  BORDER="+"
  COLORS="ANSI"
fi
CRT 效果适得其反的情况

问题: 扫描线、辉光和失真在样图中看起来很酷,但实际使用时会造成问题。

常见问题:

  • 扫描线降低可读性: 覆盖在文本上的细水平线会增加阅读难度,尤其是在移动设备上或远距离观看时。视力较弱的人可能无法阅读。
  • 辉光遮挡文本: 强烈的霓虹辉光(包含 10 层以上的 text-shadow)会模糊文本边缘,降低可读性。
  • 桶形失真破坏对齐: CRT 曲面效果看起来很逼真,但会让内容显得错位。用户会以为 UI 出了问题。
  • 闪烁引发晕动症: 轻微闪烁也会让部分用户感到恶心。光敏性癫痫是真实存在的安全隐患。

预防措施:

  • 使用轻微的扫描线:透明度设为 10-15%,效果清晰可见,但不影响文本
  • 控制辉光强度:如果辉光半径超过 20px,文本就会变得难以辨认
  • 失真仅用于装饰:切勿将其用于关键布局
  • 始终提供 prefers-reduced-motion 退出选项
  • 与实际用户进行测试:“这样读起来舒服吗?”

资源

库
文档
灵感来源

评论

支持 Markdown