Box-Shadow Generator — TypeScript source
Design layered CSS box-shadows with offset, blur, spread, color, and inset. Live preview and copy-ready CSS.
This is the TypeScript implementation — the same logic the interactive tool runs, in a shareable, citable form.
// Pure CSS box-shadow builder - no React, no DOM, deterministic.
// Formats one or more shadow layers and joins them. Never throws.
export interface ShadowLayer {
inset: boolean;
offsetX: number;
offsetY: number;
blur: number;
spread: number;
color: string;
}
const NAMED_COLORS = new Set([
'transparent', 'black', 'white', 'red', 'green', 'blue', 'yellow',
'orange', 'purple', 'pink', 'gray', 'grey', 'brown', 'cyan', 'magenta',
]);
export function parseColor(color: string): { ok: boolean; error: string | null } {
const c = (color || '').trim().toLowerCase();
if (!c) return { ok: false, error: 'empty color' };
if (NAMED_COLORS.has(c)) return { ok: true, error: null };
if (/^#[0-9a-f]{3}([0-9a-f]{3})?$/.test(c)) return { ok: true, error: null };
if (/^#[0-9a-f]{8}$/.test(c)) return { ok: true, error: null };
if (/^rgba?\([^)]+\)$/.test(c)) return { ok: true, error: null };
if (/^hsla?\([^)]+\)$/.test(c)) return { ok: true, error: null };
return { ok: false, error: `invalid color: ${color}` };
}
function normalizeColor(color: string): string {
return parseColor(color).ok ? color.trim() : 'rgba(0,0,0,0.5)';
}
export function formatLayer(layer: ShadowLayer): string {
const { inset, offsetX, offsetY, blur, spread, color } = layer;
return `${inset ? 'inset ' : ''}${offsetX}px ${offsetY}px ${blur}px ${spread}px ${normalizeColor(color)}`;
}
export function buildBoxShadow(layers: ShadowLayer[]): string {
if (!layers.length) return 'none';
return layers.map(formatLayer).join(', ');
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →