1. Install
Copy the files you need into your project:
sketchy.css ← development (readable)
sketchy.min.css ← production (43 KB, minified)
sketchy.js ← development (readable)
sketchy.min.js ← production (14 KB, minified)
Then in your HTML:
<link href="https://fonts.googleapis.com/css2?family=Caveat:wght@400;600&family=Patrick+Hand&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<!-- development -->
<link rel="stylesheet" href="sketchy.css">
<!-- or production -->
<link rel="stylesheet" href="sketchy.min.css">
<!-- add class="s-kit" to your wrapper (body or any div) -->
<body class="s-kit">
<!-- your markup -->
</body>
<!-- development -->
<script src="sketchy.js"></script>
<!-- or production -->
<script src="sketchy.min.js"></script>
The s-kit class is the scope boundary — all styles are contained inside it, so the kit won't conflict with existing CSS in your project. You can put it on <body> to style the whole page, or on any inner wrapper to style just a section.
2. The SVG filter
The wobble effect comes from an inline SVG filter. Paste this once at the top of <body>:
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
<defs>
<filter id="hand-drawn" x="-4%" y="-4%" width="108%" height="108%">
<feTurbulence type="fractalNoise" baseFrequency="0.025" numOctaves="3" seed="3" result="noise"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="3.5" xChannelSelector="R" yChannelSelector="G"/>
</filter>
<filter id="hand-drawn-tight" x="-15%" y="-15%" width="130%" height="130%">
<feTurbulence type="fractalNoise" baseFrequency="0.08" numOctaves="2" seed="5" result="noise"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="1.6" xChannelSelector="R" yChannelSelector="G"/>
</filter>
</defs>
</svg>
Then apply it to anything: filter: url(#hand-drawn). Tweak scale for more/less wobble; change seed to get a different random pattern.
3. Fonts
Three Google fonts:
- Patrick Hand — body text, form controls.
- Caveat — headings, labels, buttons.
- JetBrains Mono — code, technical captions.
Swap them in sketchy.css if you want a different feel — the kit only references them in a handful of places.
4. Dark mode
Set data-theme="dark" on the <html> element, or use the helper:
// programmatically
Sketchy.setTheme('dark'); // or 'light'
Sketchy.toggleTheme(); // flip
// or as a button
<button data-toggle-theme>☾</button>
Persists in localStorage. The kit defines all colors as CSS custom properties, so dark mode is one variable swap.
5. Form controls
All form controls are real native elements (<input>, <select>, <textarea>). The kit just skins them.
.ip — text input / select / textarea
<input class="ip" type="email" placeholder="..." />
<select class="ip select">...</select>
<textarea class="ip"></textarea>
.check / .radio
<label class="check">
<input type="checkbox" />
<span class="box"></span>
Label text
</label>
.toggle
<label class="toggle">
<input type="checkbox" />
<span class="switch"></span>
Label text
</label>
6. Interactive bits
Components are activated by data-* attributes. sketchy.js auto-wires them.
Modal — data-modal-open / data-modal-close
<button data-modal-open="#my-modal">Open</button>
<div class="modal-backdrop" id="my-modal">
<div class="modal">
<h3>Title</h3>
<p>Body</p>
<div class="modal-actions">
<button class="btn" data-modal-close>Cancel</button>
<button class="btn primary" data-modal-close>OK</button>
</div>
</div>
</div>
Esc and backdrop-click also close. Programmatic: Sketchy.openModal('#id'), Sketchy.closeModal().
Toast — Sketchy.toast()
Sketchy.toast('Saved successfully', { type: 'success', duration: 4000 });
// types: info (default), success, error
Tabs — data-tabs / data-tab / data-panel
<div data-tabs>
<div class="tabs">
<div class="tab" data-tab="a">One</div>
<div class="tab" data-tab="b">Two</div>
</div>
<div class="tab-panel" data-panel="a">...</div>
<div class="tab-panel" data-panel="b">...</div>
</div>
Dropdown — data-dropdown-trigger
<div class="dropdown">
<button class="btn" data-dropdown-trigger>Menu</button>
<div class="dropdown-menu">
<a class="dd-item" href="#">Edit</a>
<a class="dd-item" href="#">Delete</a>
</div>
</div>
Combobox — data-combo + data-options
<div class="combo" data-combo data-options='["A","B","C"]'>
<input class="ip" />
<div class="combo-list"></div>
</div>
Keyboard: ↑/↓ to highlight, Enter to pick, Esc to close.
Gallery — data-gallery
<div class="gallery" data-gallery>
<div class="thumb" data-label="Sketch 01">
<img src="01.jpg" />
</div>
...
</div>
Lightbox opens on click — ←/→ navigate, Esc closes.
Star rating — data-rating
<div class="rating" data-rating data-value="3" data-max="5"></div>
el.addEventListener('change', e => console.log(e.detail.value));
File drop — data-file-drop
<div class="file" data-file-drop>
<span class="file-icon">✎</span>
<input type="file" />
</div>
7. Images & borders
Use .frame to wrap any image. The content clips to clean sharp corners via overflow:hidden — only the ::after border gets the wobble filter, so the image stays pixel-perfect.
<div class="frame">
<img src="photo.jpg" alt="..." />
</div>
Add a slight rotation for a more natural, tossed-on-a-desk look:
<div class="frame" style="transform: rotate(-2deg);">
<img src="photo.jpg" alt="..." />
</div>
See the live demo on the Components page.
8. Customize
All theme values are CSS custom properties on :root (and [data-theme="dark"]):
:root {
--ink: #1a1a1a; /* main lines */
--paper: #fdfcf8; /* background */
--accent: #2b5fff; /* highlights */
--danger: #d83a3a;
--warn: #b8860b;
--success: #2e8b57;
--muted: #6b6b6b;
}
Override any of them in your own stylesheet to rebrand the kit. To increase the wobble globally, edit the scale attribute on <feDisplacementMap> in the SVG defs.
9. Accessibility
- Form controls are real native
<input>s — screen readers, autofill, validation all work. - Focus rings on every interactive element via
:focus-visible. - Modals trap focus; Esc closes; backdrop click closes.
- Combobox supports ↑/↓/Enter/Esc keyboard nav.
- Lightbox supports ←/→/Esc.
prefers-reduced-motiondisables animations.- Hit targets ≥ 44px for buttons and inputs.
10. Tips
- Don't filter the whole page. The wobble filter is GPU-cheap but not free — apply it to specific cards/elements, not
body. - Use
filter: url(#hand-drawn-tight)for small things (icons, checkboxes) so the wobble doesn't dominate. - For pixel-sharp interior content with a sketchy outline, use the
.frameclass — the image stays sharp, only the border wobbles. - Performance: avoid stacking many filtered elements; the kit applies the filter sparingly by default.
- Print: SVG filters print fine in modern browsers, but you can disable with
@media print { * { filter: none !important; } }.
11. Icons
Sketchy Kit doesn't bundle an icon set — keeping the two-file install clean is a deliberate choice. Two libraries pair well with the aesthetic:
Lucide — recommended
Consistent 2 px stroked lines with rounded caps — the stroke weight sits right next to the kit's 2.5px solid var(--ink) borders and reads as the same hand. ~1 500 icons, MIT licensed.
<!-- one script tag -->
<script src="https://unpkg.com/lucide@latest"></script>
<!-- use icons by name -->
<i data-lucide="pencil"></i>
<i data-lucide="trash-2"></i>
<!-- initialise (call once after the DOM is ready) -->
<script>lucide.createIcons();</script>
Docs & icon search: lucide.dev
Phosphor — more personality
Six weights (Thin → Bold). The Light or Regular weight has a slightly more hand-crafted, uneven feel that complements the wobble mode well. ~9 000 icons, MIT licensed.
<script src="https://unpkg.com/@phosphor-icons/web"></script>
<!-- weight via class prefix: ph-light, ph-regular, ph-bold … -->
<i class="ph-light ph-pencil"></i>
<i class="ph-light ph-trash"></i>
Docs & icon search: phosphoricons.com
Font Awesome Pro — whiteboard style
Font Awesome Pro includes a Whiteboard icon family — hand-drawn, marker-on-paper strokes that are a near-perfect visual match for Sketchy Kit. Requires a paid FA Pro subscription.
Load via your FA Pro kit script tag, then use the whiteboard style prefix for your icons. Search fontawesome.com for "whiteboard" to preview the family and find the exact class names for your FA Pro version. If you're already on FA Pro this is the closest aesthetic match to the kit.
Sizing tip
Both libraries default to 1em — they scale with your font size automatically. Icons placed inside a filtered element (a wobbled card, button, or frame) will wobble with it naturally.