Communitygithub.com

sridhar-raj/blur-craft

UI에서 블러와 유리 효과를 프리미엄급으로 만들고, 가독성을 입증합니다: Apple 수준의 젖빛 유리(두께 레벨, 테두리 조명, 색조 레벨로 측정된 소재), 바로 사용 가능한 유리 표면(스티키 내비, 사이드바/패널, 독, 메뉴, 흐릿하게 처리된 페이지 위의 다이얼로그, 토스트, 시트), 액체 유리 굴절, 프로그레시브 블러, 블러 리빌, 글로우와 깊이 효과를 React, Vue, Svelte, Tailwind 및 네이티브(SwiftUI, Flutter, React Native, Compose) 가이드와 함께 제공합니다. 또한 대비 및 서리 확인 도구를 포함합니다.

blur-craft란 무엇인가요?

Blur Craft는 웹 UI에서 Apple 수준의 고급스러운 유리 효과를 구현하기 위한 종합적인 기술 스킬입니다. 이 스킬은 단순한 CSS 블러 필터를 넘어, 유리를 하나의 '소재'로 다루며 세 가지 핵심 원칙을 따릅니다: 유리 뒤에 조명 배치하기, 채도와 그라데이션, 테두리 조명, 깊이감을 갖춘 소재 사용하기, 그리고 최악의 배경에서도 텍스트 대비를 측정하여 검증하기입니다. React, Vue, Svelte, Tailwind CSS, SwiftUI, Flutter, React Native, Compose 등 주요 프레임워크와 플랫폼을 지원하며, 다양한 UI 패턴(스티키 내비, 사이드바, 독, 메뉴, 다이얼로그, 토스트, 시트)에 맞춰 미리 만들어진 CSS 클래스를 제공합니다. 또한 Liquid Glass 굴절 효과, 프로그레시브 블러, 블러 리빌, 글래스 모프 등 고급 효과를 위한 레시피와 성능 최적화 가이드(블러 영역 예산, 기기별 성능 계층화)를 포함합니다. 대비 확인 스크립트와 서리 확인 스크립트를 통해 실제 환경에서의 가독성을 자동으로 검증하도록 설계되어, 개발자가 디자인 퀄리티를 유지하면서도 성능과 접근성을 보장할 수 있도록 돕습니다.

지원 대상~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/sridhar-raj/blur-craft/tree/HEAD

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Blur craft

웹상의 대부분 유리 효과는 세 가지 이유로 싸구려로 보입니다. 유리 뒤에 흥미로운 것이 없거나, 소재가 단순한 색조에 하나의 블러만 적용되어 있거나, 그 위의 텍스트가 아무도 측정하지 않은 탁한 회색이기 때문입니다. 고급스러워 보이는 유리(Apple의 소재, visionOS, 최고의 제품 사이트)는 다음 세 가지를 올바르게 처리합니다. 순서대로 적용하세요:

  1. 유리 뒤의 빛이 설계되어 있습니다. 유리는 뒤에 있는 것을 드러내므로, 그곳에 빛을 배치하세요.
  2. 유리는 색조가 아닌 소재입니다. 채도가 높은 블러, 그라데이션 채우기, 테두리 조명, 반짝임, 깊이감, 질감. assets/glass.css를 참조하세요.
  3. 텍스트가 측정되었습니다. 반투명 유리는 뒤의 모든 픽셀에 따라 대비가 변하므로, 스크립트를 통해 최악의 지점에서 대비를 확인합니다. 세 가지 상태로 확인합니다(scripts/glass-contrast.mjs).

빠른 경로

만들고 있는 대상…사용참고
스티키 내비게이션 바.gs-bar (surfaces.css)확장 배경; gs-bar--on-scroll을 추가하면 스크롤 후에만 유리 효과 적용
아트 위의 플레이어, 독 또는 필.gs-dock.glass.glass--clear + liquid-glass.js투명 액체 유리, 화면당 하나; 아트가 많이 변하면 적응형 톤
텍스트가 있는 플로팅 카드 또는 패널.glass.glass--regular디테일한 사진 위에서는 thick
메뉴, 팝오버 또는 명령어 바.gs-menu.glass32px, 약 86% 불투명도, 0.5px 상단 하이라이트
다이얼로그.gs-veil + .gs-dialog.glass.glass--thick결제, 삭제, 서명 시 glass--solid; 유리 크롬이 아래에 있을 때는 gs-veil--flat + .gs-modal-open
토스트 또는 바텀 시트.gs-toast.glass.glass--regular / .gs-sheet.glass.glass--thickgs- 클래스는 레이아웃 전용; 소재는 .glass에서 옴
바 아래로 사라지는 콘텐츠프로그레시브 블러 (레시피 2)뷰당 하나의 스크롤-가장자리 효과
나타나는 헤드라인 또는 변경되는 값블러 리빌 (4) / 2px 크로스페이드 (4b)화면당 한 번
아트의 색상으로 채워진 페이지아트 배경, 베이크드 (레시피 8)고정 유리 아래에서는 절대 라이브 블러 사용 금지
Tailwind v4 프로젝트glass.css + glass.tailwind.css (glass-blur-24, …)Tailwind의 자체 backdrop-blur-*는 Sonoma Safari에서 깨짐
네이티브 앱 (SwiftUI, Flutter, React Native, Compose)references/native.md동일한 방법, 각 툴킷의 소재
사진, 비디오 또는 디자인 편집기의 크롬.glass.glass--thick.glass--neutral중립: 채도 증가 없음, 유리가 작업물을 변색시켜선 안 됨

그런 다음: 빛을 구성하고(§1), 소재를 설정하고(§2), 확인하세요(§5). assets/demo.html은 모든 표면을 컨트롤과 함께 라이브로 보여줍니다; 선택하기 전에 각 클래스가 무엇을 하는지 확인하려면 열어보세요.

1. 먼저 빛을 구성하세요

각 유리 표면 바로 뒤에 무엇이 올지 결정하고, 그곳을 가장 빛나는 영역으로 만드세요.

  • 유리 아래에 빛을 배치하세요: 글로우, 아트 속의 태양, 제품의 색상, 라이브 WebGL 컴포넌트. 블러 처리된 단색은 여전히 단색일 뿐입니다; 빈 공간 위의 유리는 회색 상자에 불과합니다.

  • 빛이 가장자리를 가로지르게 하세요. 최고의 유리는 절반은 빛 위에, 절반은 어둠 위에 놓여 색상이 폭에 따라 변합니다.

  • 테두리 조명을 빛 방향으로 맞추세요. --glass-light를 빛의 색상(일몰의 경우 255 200 160)으로, --glass-rim-angle을 방향으로 설정하세요. 테두리의 밝은 쪽이 빛을 향합니다:

    빛 방향좌측 상단상단우측 상단우측우측 하단하단좌측 하단좌측
    각도135deg180deg225deg270deg315deg0deg45deg90deg

    유리 아래의 빛은 가장 가까운 가장자리의 각도 + 센터 방향으로 약 15deg를 취합니다. 각도는 등록된 @property이므로, 포인터나 스크롤을 따라 부드럽게 이동할 수 있습니다(Apple의 하이라이트는 빛이 이동함에 따라 소재 주변을 여행합니다).

  • 유리를 주인공처럼 크게 잡으세요. 유리 아래의 장면 변화를 보여줄 만큼 충분히 클 때 소재로 읽힙니다. Apple은 더 큰 유리를 더 두꺼운 유리처럼 동작하게 만듭니다: 더 깊은 그림자, 더 부드러운 산란.

2. 소재 설정

assets/glass.css(복사 시 glass 접두사 이름 변경)와 assets/surfaces.css를 미리 만들어진 표면용으로 사용하거나, 컴포넌트(Glass.tsx (React), Glass.vue (Vue 3), Glass.svelte (Svelte 5))를 사용하세요. 한 줄짜리 backdrop-filter 카드를 직접 작성하지 마세요.

backdrop-filter를 리터럴 값으로 작성하고, var()를 절대 사용하지 마세요. 접두사 없는 것을 먼저, -webkit-을 마지막에 두세요. macOS Sonoma의 Safari 18 및 26은 필터가 사용자 정의 속성으로 빌드될 때 블러를 렌더링하지 않습니다(WebKit 297620, 열림). Tailwind v4의 backdrop-blur-*는 정확히 그 방식으로 빌드됩니다. 동일한 버그 보고서는 접두사 없는 속성이 리터럴 값에서도 실패함을 보여주므로, 접두사가 있는 선언이 마지막에 와야 Safari가 적용합니다(Chrome과 Firefox는 무시합니다). glass.css는 두께 × 톤당 리터럴 필터를 가지며 클래스로 전환합니다; 변수는 채우기, 차광 및 색상에 괜찮습니다.

두께. 유리가 담는 텍스트 양에 따라 선택하세요. 값은 demo.html에서 밝은 빛 위에서 대비 체커로 보정되었습니다:

클래스블러, 차광밝은 빛 위에서 4.5:1 통과?사용 대상
glass--clear16px, 22%아니요: 굵거나 큰 텍스트 및 아이콘만 가능독, 재생 버튼, 미디어 위의 필 (Apple: 클리어는 굵고 밝은 콘텐츠와 차광 레이어 필요)
glass--thin24px, 30%가장 밝은 빛 위에서는 불가중간 정도 배경의 컨트롤, 칩, 작은 카드
glass--regular32px, 48%캘리브레이션 페이지에서는 예; 플레이어 뒤의 밝은 일몰은 0.62에서 thick 필요플레이어, 패널, 토스트: 기본값. 블러-오프(틴트 전용) 상태가 일반적으로 먼저 실패
glass--thick44px, 56%예메뉴, 시트, 다이얼로그, 텍스트가 많은 모든 것
glass--solid4px, 92%예결제, 삭제, 서명 (약 85% 이상 채우면 큰 블러가 보이지 않으므로 4px)

밝은 유리와 잉크 텍스트를 위해 glass--light를 추가하고, 색상이 중요한 앱(사진, 비디오 및 디자인 편집기)에서는 glass--neutral을 추가하세요: 채도 증가나 톤 변화가 없어야 유리가 작업물 모양을 변경하지 않습니다. 디테일한 사진 위에서는 --glass-dim: rgb(10 10 18 / 0.65–0.75)로 thick부터 시작하세요(숫자가 아닌 색상임): 생생한 유리와 읽기 쉬운 텍스트는 서로 상충되므로, 생생함은 테두리, 광택 및 유리 주변에 번지는 빛에 사용하세요.

iOS 26.1과 같은 두 가지 레벨: prefers-contrast: more(Safari 사용자가 접근할 수 있는 설정; Safari에는 prefers-reduced-transparency 없음)에 대해 틴트 레벨(더 많은 불투명도, 절대 적지 않음)이 켜집니다. glass--tinted를 사용하거나, 사이트 전체에 <html data-glass="tinted">를 사용하세요. glass.css는 Windows High Contrast(단색 Canvas 표면), 인쇄(테두리 있는 일반 상자), 스크린샷 도구용 캡처 모드 및 RTL도 처리합니다.

유리는 제어 레이어에 속합니다 (내비게이션, 툴바, 독, 메뉴, 시트, 다이얼로그). 콘텐츠 자체 위에 떠 있어야 하며, 절대 유리 위에 유리를 두지 마세요(Apple, WWDC25). 기본 작업에만 색조를 입히세요. 브리프의 레지스터에 맞추세요: 몰입형 브리프는 강한 빛과 히어로 컨트롤의 투명 유리를 사용하고; 신뢰 기반(금융, 건강)은 두껍거나 단색 유리와 거의 빛을 사용하지 않습니다.

references/material.md에는 나머지가 있습니다: 각 레이어가 하는 일과 이유, Apple.com, Linear, Raycast, Radix, Material 및 Fluent에서 읽어온 프리셋, Apple의 전체 WWDC25 규칙 목록 및 레지스터 테이블.

3. 시그니처 효과

references/recipes.md의 코드:

  • 액체 유리 굴절: 테두리가 뒤의 것을 렌즈처럼 구부리며, 선택적 색수차(0.6–1) 포함. 두 가지 버전: liquid-glass.ts/.js는 모든 페이지 콘텐츠를 굴절시키지만 Chromium에서만 작동합니다(Safari는 SVG 배경 필터에 대해 아무것도 그리지 않음, WebKit 245510); liquid-glass-webgl.js는 페이지 자체가 그리는 배경(<canvas>, <img> 또는 <video>, 예: 히어로 배경화면)을 모든 브라우저에서 굴절시키며, Chromium 및 WebKit에서 렌더링이 확인되었습니다. 다른 곳에서는 젖빛 소재가 자체적으로 완성된 모습을 보여야 합니다. 굴절과 젖빛은 트레이드오프가 있습니다: 굽힘은 투명 유리(blur 0–6)를 통해 보이고; 젖빛 처리(12–20)는 가장자리에서 가장자리로 서리가 내리며 굽힘은 부드러운 색상 변화가 됩니다. 단어나 아이콘에는 투명, 문장에는 젖빛, 텍스트는 가장자리에서 베젤 너비만큼 안쪽으로 배치합니다. 베일 위의 다이얼로그에서는 절대 사용하지 마세요: 구부릴 날카로운 것이 남아 있지 않습니다.
  • 스티키 바용 확장 배경: 콘텐츠가 아래로 스크롤되기 전에 유리 안에 색상이 도착합니다. gs-bar--on-scroll은 순수 CSS(스크롤 기반 애니메이션)를 사용하여 스크롤 후에만 바를 유리처럼 만듭니다.
  • 프로그레시브 블러: 콘텐츠가 잘리는 대신 바 아래에서 용해됩니다. CSS가 linear-blur()를 얻을 때까지 스택 마스크 레이어가 유일한 방법입니다(제안됨, csswg #13285).
  • 블러-브리지 크로스페이드: 상태 전환 중 2px 블러(Emil Kowalski).
  • 블러 리빌: blur(8px)에서 시작하여, 한 번, 도착 순간으로 사용.
  • 포커스 베일: 다이얼로그 뒤의 페이지가 4–8px 뒤로 물러납니다.
  • 글래스 모프 및 프레스: 근처 유리 모양 사이의 layoutId 모프(Cursor: 0.34초, [0.32, 0.72, 0, 1]) 및 프레스 시 내부 글로우 펄스(스케일 아님).
  • 유리 모양 병합: 구이 필터링된 SVG 마스크로 잘린 하나의 유리 레이어. 근처 모양이 Apple의 유리 컨테이너처럼 액체 목으로 연결됩니다(레시피 11, Chromium에서 테스트됨).
  • 비디오의 앰비언트 글로우: 재생 중인 비디오의 10×6 캔버스 샘플을 확대하여 사용(레시피 8b).
  • 틴팅: 구조용 유리는 크로마 ~0.03–0.05, 틴트는 상대 색상 알파 사용(레시피 12).
  • 피사계 심도, 속도 모션 블러, 아트 배경(베이크드), 잠긴 콘텐츠, 그레인.

4. 속도 유지하기

먼저 디자인을 완성한 다음, 다음 사항을 준수하세요:

  • 길거나 반복되는 애니메이션은 블러 반경이 아닌 불투명도와 변형(transform)에 적용하세요. 짧은 일회성 애니메이션은 괜찮습니다: Apple.com은 메뉴 커튼의 블러를 0 → 20px로 320ms 동안 애니메이션합니다.
  • 두 개의 겹친 표면을 동시에 블러 처리하지 마세요(Apple의 내비게이션은 플라이아웃이 열려 있는 동안 자체 블러를 해제합니다). 다이얼로그가 유리 크롬 위에 열리면 <html>에 .gs-modal-open을 추가하고(크롬이 블러를 중단하고 거의 불투명해짐) gs-veil--flat을 사용하거나 이미지 또는 캔버스 배경에서 베일을 구우세요. 사진 편집기 테스트에서 측정: 다섯 개의 유리 패널 위의 라이브 전체 화면 베일 블러는 31fps로 실행되었고, 없으면 60fps였습니다.
  • 고정 또는 스티키 블러는 모든 스크롤 프레임에서 다시 실행됩니다. 화면당 하나의 큰 블러만 사용하고, 그 아래에 큰 블러 이미지를 구우세요(측정: 라이브 블러 60 → 22fps, 구운 블러 60fps).
  • 휴대폰: 일곱 개의 18px 패널은 Mali-G57에서 프레임당 약 3.5ms를 소비합니다(제시간에 도착한 프레임 75–80% vs 없을 때 99%). 패널이 몇 개 이상이면 레이아웃의 휴대폰 중단점에서 backdrop-filter를 제거하고 반투명 채우기를 유지하거나(또는 glass-tier.js가 기기별로 결정하도록 함).
  • 블러 영역을 예산으로 잡고, 반경이나 개수가 아닙니다. 이 스킬에 대해 측정됨(Chromium, 소프트웨어 렌더링 2배, 움직이는 배경, vsync 켜짐): 반경 4 → 64px 및 동일한 총 면적에서 1 → 9개 표면은 차이가 없었습니다; 화면의 90%를 블러 처리하면 51fps로 떨어졌습니다(p95 33ms). 이는 Skia의 대형 블러 다운샘플링과 일치합니다. 숫자는 상대적(소프트웨어 렌더링하는 빠른 Mac)이며, 순위는 이식 가능합니다.
  • html에 불투명한 배경색을 지정하세요: 그러면 Safari가 유리가 있는 페이지에 대해 추가 전체 화면 합성 레이어를 건너뜁니다(WebKit 271340: 수정 사항은 불투명 문서에 대해서만 레이어를 건너뜁니다).
  • 불투명 채우기 아래에서는 블러를 적용하지 마세요. Framer와 Dia는 단색 배경에 backdrop-filter를 제공하여 아무도 볼 수 없는 블러에 비용을 지불합니다. 약 85% 이상 채우면 ≤ 4px를 사용하거나 사용하지 마세요(Arc의 토스트: 85% 및 3px).
  • 기기별로 유리 계층화: assets/glass-tier.js는 data-glass-tier를 full, lite(하나의 8px 블러) 또는 flat(블러 없음, 더 많은 색조)으로 설정합니다. 기기 메모리, Save-Data, 프레임 속도 프로브(iOS 저전력 모드는 의도적으로 애니메이션을 30fps로 제한함) 및 Compute Pressure를 기반으로 합니다. Android, Fluent 및 Apple이 약하거나 전력 절약 장치에서 블러를 제거하는 방식과 동일합니다.
  • 비디오 위에서는 재생 중인 비디오를 블러 처리하지 마세요: 작은 캔버스에 샘플링하고(레시피 8b), 전체 화면에서는 유리를 제거하세요. Safari는 비디오 픽셀을 SVG 필터에 전달하지 않습니다.
  • 배경 루트: opacity < 1, filter, 마스크, clip-path, mix-blend-mode, backdrop-filter 또는 이들 중 하나에 대한 will-change가 있는 부모는 내부의 유리를 평평하게 만듭니다. 여기에는 Framer Motion 부모 페이드 아웃 및 유리 블롭의 부모에 대한 구이 filter가 포함됩니다. 유리 자체를 페이드하고 완료되면 리빌 필터(filter: none)를 지우세요.
  • backdrop-filter는 엘리먼트를 position: fixed 자식의 포함 블록으로 만듭니다: 포털 메뉴, 토스트 및 다이얼로그는 유리 컨테이너 밖에 있어야 합니다.
  • 조상에 상시 view-transition-name이 있으면 Chromium에서 유리가 평평해집니다; 전환 중에만 이름을 설정하세요. 래퍼의 프레임워크 페이드 전환도 동일한 작업을 수행합니다: 유리 자체를 페이드하세요.
  • 유리의 스크린샷, OG 이미지 또는 PDF를 찍을 때: html2canvas, Satori 및 인쇄는 블러를 제거하거나 깨뜨립니다. 캡처하는 동안 <html>에 data-glass-capture를 설정하고(glass.css는 유리를 불투명하게 만듦) quirks.md를 참조하세요.

5. 확인 (필수)

유리를 완료했다고 판단하기 전에 다음을 모두 실행하세요:

  1. 서리 확인: node <skill>/scripts/frost-check.mjs <url 또는 file.html>는 각 유리 표면에 대해 블러가 제거하는 디테일의 양(블러 켜짐 vs 꺼짐)을 측정합니다. NO BLUR는 배경 루트, 깨진 접두사 또는 var(), 또는 오래된 Liquid Glass 맵을 의미합니다; FLAT는 뒤에 측정할 것이 없음을 의미합니다. 눈으로 확인하려면 유리 뒤에 굵은 빨간색 텍스트를 놓고, deviceScaleFactor: 1에서 캡처하여 확대하세요.
  2. 측정된 대비, 최악의 배경에서: node <skill>/scripts/glass-contrast.mjs <url 또는 file.html>. 가장 밝은 실제 상태를 가리키세요. 예쁜 기본값이 아닙니다: 가장 밝은 사진, 일광 프레임, +2 EV로 밀어낸 이미지, 바 아래로 스크롤되는 흰색 페이지 섹션(스크립트가 로드할 수 있도록 URL 매개변수나 테스트 상태를 추가하세요). 한 편집기에서 기본 사진은 8.7:1로 통과했고 밝은 프레임은 4.4:1로 실패했습니다. 휴대폰 너비도 확인하세요(--width 390 --height 844). 텍스트를 숨기고, 각 줄 아래에서 가장 밝은 픽셀과 가장 어두운 픽셀을 찾아 세 가지 상태에서 4.5:1(큰 텍스트는 3:1)을 확인합니다: 일반, 틴트 전용(iOS 저전력 모드처럼 블러 꺼짐) 및 prefers-contrast: more. 실패를 수정하려면 두께를 한 단계 올리거나, --glass-dim의 알파를 높이거나(예: 0.48 → 0.55), 더 큰 글꼴 크기를 사용하거나, 고정된 디자인에서는 백플레이트 뒤에 불투명 패치를 넣으세요. --glass-text-color를 조정하지 마세요: 가독성 있는 텍스트는 배경과 독립적이어야 하며, 배경과 일치시키려는 것은 잘못된 방향입니다.

assets 구조

assets/
  glass.css          # 핵심 유리 소재: 두께, 톤, 테두리 조명, 성능 계층, 접근성
  surfaces.css       # 미리 만들어진 표면: .gs-bar, .gs-dock, .gs-menu, .gs-veil, .gs-dialog, .gs-toast, .gs-sheet
  glass.tailwind.css # Tailwind v4 유틸리티: .glass-blur-24, .glass-bg-48 등
  glass-tier.js      # 기기 감지: full / lite / flat 설정, 데이터 속성 설정, Compute Pressure 사용
  demo.html          # 모든 표면과 컨트롤을 보여주는 라이브 데모 페이지
scripts/
  glass-contrast.mjs # 각 유리 표면 아래의 최악의 텍스트 대비를 측정합니다.
  frost-check.mjs    # 각 유리 표면이 실제로 블러를 적용하는지 확인합니다.
references/
  material.md        # 소재 심층 분석: Apple, Linear, Raycast, Radix, Material, Fluent 프리셋; WWDC25 규칙; 레지스터
  native.md          # SwiftUI, Flutter, React Native, Compose 가이드
  recipes.md         # 시그니처 효과 코드: Liquid Glass, 프로그레시브 블러, 블러 리빌 등
  quirks.md          # 브라우저별 문제 및 해결 방법

관련 스킬