Skip to content
Design
Skill

/omd-cjk-type-shader

One effect, done well: 먹 번짐 — a large Korean, Japanese or Chinese display headline that reads as sumi ink printed on hanji. The heading stays real, selectable DOM text in ink color from the first frame; a WebGL2 layer over it adds what real ink does: a wet, glossy stroke with a

BOOST
From plugin
oh-my-design
53641 skills21 agents1 MCP
Install
$ npx -y skills add kwakseongjae/oh-my-design --skill omd-cjk-type-shader --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/omd-cjk-type-shader

Context preview

The summary Claude sees to decide when to auto-load this skill.

One effect, done well: 먹 번짐 — a large Korean, Japanese or Chinese display headline that reads as sumi ink printed on hanji. The heading stays real, selectable DOM text in ink color from the first frame; a WebGL2 layer over it adds what real ink does: a wet, glossy stroke with a

SKILL.md

omd-cjk-type-shader.SKILL.md
name: omd-cjk-type-shader
description: "One effect, done well: 먹 번짐 — a large Korean, Japanese or Chinese display headline that reads as sumi ink printed on hanji. The heading stays real, selectable DOM text in ink color from the first frame; a WebGL2 layer over it adds what real ink does: a wet, glossy stroke with a soft bloom that shrinks as it dries, ink pooling darker at stroke rims, ends and corners, paper fibers showing through thick strokes, and capillary feathering along fibers at a few edges only. Two parameters (bleed, duration), ~5 KiB gzip of library JS, procedural paper texture, static fallback, prefers-reduced-motion, real-GPU verification script. Use for a CJK hero/launch headline, brand title, campaign line or section opener that should feel like a printed calligraphy poster. Triggers: '먹 번짐', '잉크 번짐', '한지 느낌 제목', '한글 타이포 셰이더', '제목에 셰이더', '墨のにじみ', '和紙', '筆文字っぽく', '墨跡暈開', '宣紙', 'CJK headline shader', 'sumi ink text effect', 'ink bleed text', 'Hangul shader'. Not for body text, buttons, or Latin-only headlines. Full-page shader backgrounds → omd-shader-hero. Korean typesetting rules → hangul. Brand tokens → omd-apply."
argument-hint: "<selector or file of the CJK headline> [bleed 0..1] [duration seconds]"
user-invocable: true

omd-cjk-type-shader — 먹 번짐: CJK display type as sumi ink on hanji

Ink soaking into paper is the one image Korean, Japanese and Chinese writing share. This skill makes a big CJK headline read like it was printed or brushed in sumi on hanji. On a fast skim it should look like a calligraphy poster, not a filter.

How it works. The heading is ordinary DOM text in the ink color, readable and selectable from the first frame. The skill traces every grapheme where the browser laid it out and builds three fields from that mask: distance outside the strokes, distance inside them, and local ink coverage. A WebGL2 layer drawn **over** the text then adds only what real ink does:

  • **wet → dry:** the stroke starts glossy-dark with a soft bloom around it, and the bloom shrinks back as the ink dries;
  • **pooling:** ink collects darker along the stroke rim and at stroke ends and convex corners (low local coverage);
  • **kasure:** paper fibers show through the middle of thick strokes once dry;
  • **nijimi:** capillary feathering runs along a few paper fibers at some edges, chosen by low-frequency noise, never as an even ring around every glyph;
  • **paper:** a procedural hanji texture (SVG turbulence, no image) on the page.

It plays once when the heading enters the viewport, then the render loop stops. Line wrapping, `keep-all`, font swaps and resizes are re-traced.

Working example: [`examples/demo.html`](./examples/demo.html) (single file, Korean + Japanese + Traditional Chinese). Proof: [`scripts/verify.mjs`](./scripts/verify.mjs).

1. When to use / when not

Use when:

  • a Korean, Japanese or Chinese **display** headline (≥ 40px; hero, launch title, campaign line, section opener) should feel inked, calligraphic, "printed on hanji / washi / 宣紙";
  • the brand's ink and paper colors are known (DESIGN.md foreground/canvas, or the heading's computed `color` and the page background).

Don't use for:

  • body text, labels, buttons, nav, anything below ~32px (pooling and feathering need stroke width to read);
  • Latin-only headlines (it works, but the cultural point is gone);
  • more than one or two headings per page. Boldness in one place (tf-shaders rule);
  • light text on dark paper. The effect darkens ink, so it needs a paper that ink reads on.

2. The effect and its two parameters

| Param | Range | Default | What it does | |---|---|---|---| | `bleed` | 0–1 | 0.7 | How far the capillary feathering travels along fibers (up to `0.12em × bleed`, at the edges noise picks) and how big the wet bloom gets. 0.4 = barely there, 0.8 = a wet brush. | | `duration` | s | 2.6 | Time from wet to dry. The bloom peaks early and shrinks; pooling and fiber show-through come in as it dries. Under 1.5s it reads as a flash, over 4s as a loading state. |

Everything else is fixed on purpose. Ink = the heading's computed `color`, darkened to 25% for pools; paper = the page background color. Text ink should be a sumi grey-black, not pure black (the demo uses `#3a3530` on `#f3eee4`, about 10:1), so the darker pools have room to show. One signature, not a control panel.

3. The contract that keeps text text

  • The heading is a normal `<h1>`/`<h2>` with its real text. `inkBleed()` wraps the text in `.ink-text` and inserts an `aria-hidden="true"`, `pointer-events: none` layer over it (z-index 2). The layer only darkens, lightens or extends what is already there. It never replaces or re-draws the glyphs, and with the layer removed the heading is still complete.
  • **The headline paints on the first frame.** No `opacity: 0`, no clip, no wait for the shader. tf-shaders measured LCP going to 7.8s when hero copy waited for a shader.
  • Selection, copy, find-in-page, translation, screen readers and SEO see plain text. `verify.mjs` checks that selecting the heading returns its full text in every pass.
  • Leave ~0.4em of clear space around the heading (the demo uses `margin-bottom: 0.4em`). Feathering and bloom extend up to ~0.3em past the glyphs.
  • Never draw CJK headlines with a canvas/`Text` shader component. Canvas text loses selection, accessibility, indexing and correct CJK shaping (tf-shaders "Don't" list).

4. CJK typesetting (applies before the shader)

From `/hangul` (HG rules) for Korean; ja/zh scoped separately so Korean rules don't leak:

.ink:lang(ko) { word-break: keep-all; overflow-wrap: anywhere;  /* HG-10, scoped to :lang(ko) */
                letter-spacing: -0.02em;                          /* HG-7: display never below -0.03em */
                line-height: 1.3; }                               /* HG-5: wrapping display >= 1.3 */
.ink:lang(ja), .ink:lang(zh-Hant) {
  line-break: strict;                                 /* kinsoku: no small kana / closing marks at lin
Read more
Ships withoh-my-design

Give your AI coding agent a design system. One command installs 500+ quality-graded company DESIGN.md references + skills into Claude Code, Codex, Cursor, and OpenCode. Free, MIT, zero AI calls.

Get the whole plugin

Other skills on oh-my-design.