picasso-skill 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +299 -76
- package/agents/picasso.md +400 -3
- package/package.json +1 -1
- package/skills/picasso/SKILL.md +22 -1
- package/skills/picasso/references/accessibility-wcag.md +245 -0
- package/skills/picasso/references/anti-patterns.md +138 -49
- package/skills/picasso/references/color-and-contrast.md +251 -2
- package/skills/picasso/references/conversion-design.md +193 -0
- package/skills/picasso/references/data-visualization.md +226 -0
- package/skills/picasso/references/modern-css-performance.md +361 -0
- package/skills/picasso/references/performance-optimization.md +746 -0
- package/skills/picasso/references/style-presets.md +502 -0
- package/skills/picasso/references/typography.md +206 -2
- package/skills/picasso/references/ux-psychology.md +235 -0
- package/skills/picasso/references/ux-writing.md +513 -0
- package/skills/picasso/references/accessibility.md +0 -172
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# Modern CSS & Web Performance Reference
|
|
2
|
+
|
|
3
|
+
## 1. Modern CSS Features (2024-2025)
|
|
4
|
+
|
|
5
|
+
### CSS Nesting (Baseline 2024)
|
|
6
|
+
Native nesting eliminates preprocessor dependency.
|
|
7
|
+
|
|
8
|
+
```css
|
|
9
|
+
.card {
|
|
10
|
+
padding: 1rem;
|
|
11
|
+
> h2:first-child { margin-block-start: 0; }
|
|
12
|
+
&:hover { box-shadow: 0 4px 12px rgb(0 0 0 / 0.1); }
|
|
13
|
+
@media (width >= 768px) { padding: 2rem; }
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Cascade Layers (@layer)
|
|
18
|
+
Control specificity ordering without selector wars.
|
|
19
|
+
|
|
20
|
+
```css
|
|
21
|
+
@layer reset, base, components, utilities;
|
|
22
|
+
@layer reset { *, *::before, *::after { box-sizing: border-box; margin: 0; } }
|
|
23
|
+
@layer base { body { font-family: system-ui; line-height: 1.6; } }
|
|
24
|
+
@layer components { .btn { padding: 0.5rem 1rem; border-radius: 0.375rem; } }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### :has() Selector
|
|
28
|
+
Style parents based on children.
|
|
29
|
+
|
|
30
|
+
```css
|
|
31
|
+
form:has(:invalid) { border-color: red; }
|
|
32
|
+
.card:has(img) { grid-template-rows: auto 1fr; }
|
|
33
|
+
body:has(dialog[open]) { overflow: hidden; }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### CSS Anchor Positioning
|
|
37
|
+
Position elements relative to other elements without JS.
|
|
38
|
+
|
|
39
|
+
```css
|
|
40
|
+
.trigger { anchor-name: --tooltip-anchor; }
|
|
41
|
+
.tooltip {
|
|
42
|
+
position: absolute;
|
|
43
|
+
position-anchor: --tooltip-anchor;
|
|
44
|
+
top: anchor(bottom);
|
|
45
|
+
left: anchor(center);
|
|
46
|
+
translate: -50% 0.5rem;
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### @scope
|
|
51
|
+
Restrict styles to a DOM subtree with optional lower boundary.
|
|
52
|
+
|
|
53
|
+
```css
|
|
54
|
+
@scope (.card) to (.card-content) {
|
|
55
|
+
h2 { font-size: 1.25rem; font-weight: 600; }
|
|
56
|
+
p { color: var(--muted); }
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### @property (Typed Custom Properties)
|
|
61
|
+
Register custom properties with type, initial value, and inheritance. Enables animating custom properties.
|
|
62
|
+
|
|
63
|
+
```css
|
|
64
|
+
@property --gradient-angle {
|
|
65
|
+
syntax: "<angle>";
|
|
66
|
+
initial-value: 0deg;
|
|
67
|
+
inherits: false;
|
|
68
|
+
}
|
|
69
|
+
.gradient-border {
|
|
70
|
+
--gradient-angle: 0deg;
|
|
71
|
+
border-image: conic-gradient(from var(--gradient-angle), #f06, #9f6, #06f) 1;
|
|
72
|
+
animation: spin 3s linear infinite;
|
|
73
|
+
}
|
|
74
|
+
@keyframes spin { to { --gradient-angle: 360deg; } }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### color-mix()
|
|
78
|
+
Blend colors in any color space at runtime.
|
|
79
|
+
|
|
80
|
+
```css
|
|
81
|
+
.button {
|
|
82
|
+
--brand: oklch(0.65 0.25 260);
|
|
83
|
+
background: var(--brand);
|
|
84
|
+
&:hover { background: color-mix(in oklch, var(--brand) 85%, white); }
|
|
85
|
+
&:active { background: color-mix(in oklch, var(--brand) 80%, black); }
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Logical Properties
|
|
90
|
+
Write direction-agnostic layouts (LTR/RTL safe).
|
|
91
|
+
|
|
92
|
+
Key mappings: `margin-left` -> `margin-inline-start`, `padding-top` -> `padding-block-start`, `width` -> `inline-size`, `height` -> `block-size`.
|
|
93
|
+
|
|
94
|
+
```css
|
|
95
|
+
.sidebar { margin-inline-end: 2rem; padding-block: 1rem; border-inline-start: 3px solid var(--accent); }
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Subgrid
|
|
99
|
+
Child grids align to parent grid tracks.
|
|
100
|
+
|
|
101
|
+
```css
|
|
102
|
+
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
|
|
103
|
+
.grid > .card {
|
|
104
|
+
display: grid;
|
|
105
|
+
grid-row: span 3;
|
|
106
|
+
grid-template-rows: subgrid;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Popover API
|
|
111
|
+
Native popovers with light-dismiss, no JS required.
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<button popovertarget="info">Info</button>
|
|
115
|
+
<div popover id="info">Content here. Click outside to dismiss.</div>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```css
|
|
119
|
+
[popover] {
|
|
120
|
+
&::backdrop { background: rgb(0 0 0 / 0.25); }
|
|
121
|
+
opacity: 0; transition: opacity 0.2s, display 0.2s allow-discrete;
|
|
122
|
+
&:popover-open { opacity: 1; }
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 2. Core Web Vitals Optimization
|
|
129
|
+
|
|
130
|
+
**Thresholds:** LCP < 2.5s | CLS < 0.1 | INP < 200ms
|
|
131
|
+
|
|
132
|
+
### LCP (Largest Contentful Paint)
|
|
133
|
+
- Preload hero images: `<link rel="preload" as="image" href="hero.webp" fetchpriority="high">`
|
|
134
|
+
- Use `fetchpriority="high"` on the LCP `<img>` element.
|
|
135
|
+
- Eliminate render-blocking CSS/JS; inline critical CSS.
|
|
136
|
+
- Use CDN, compress with Brotli.
|
|
137
|
+
|
|
138
|
+
### CLS (Cumulative Layout Shift)
|
|
139
|
+
- Always set `width`/`height` or `aspect-ratio` on images and video.
|
|
140
|
+
- Reserve space for ads/embeds with `min-height`.
|
|
141
|
+
- Use `font-display: optional` (best CLS) or `swap` (best UX).
|
|
142
|
+
- Avoid inserting content above the fold after load.
|
|
143
|
+
|
|
144
|
+
### INP (Interaction to Next Paint)
|
|
145
|
+
Replaced FID in March 2024. Measures all interactions across the page lifecycle.
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
button.addEventListener('click', () => {
|
|
149
|
+
button.classList.add('pressed'); // instant visual feedback
|
|
150
|
+
requestAnimationFrame(() => {
|
|
151
|
+
setTimeout(() => doHeavyWork(), 0); // yield to browser
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- Break long tasks with `scheduler.yield()` (or `setTimeout(0)` fallback).
|
|
157
|
+
- Use `content-visibility: auto` for off-screen DOM.
|
|
158
|
+
- Avoid layout thrashing: batch reads, then batch writes.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 3. Image Optimization
|
|
163
|
+
|
|
164
|
+
| Format | Best For | vs JPEG |
|
|
165
|
+
|--------|----------|---------|
|
|
166
|
+
| **AVIF** | Photos, complex images | ~50% smaller |
|
|
167
|
+
| **WebP** | Photos, transparency | ~30% smaller |
|
|
168
|
+
| **SVG** | Icons, logos, illustrations | Infinitely scalable |
|
|
169
|
+
| **PNG** | Screenshots, pixel-precise | Lossless only |
|
|
170
|
+
|
|
171
|
+
### Responsive Images Pattern
|
|
172
|
+
|
|
173
|
+
```html
|
|
174
|
+
<picture>
|
|
175
|
+
<source srcset="hero.avif" type="image/avif">
|
|
176
|
+
<source srcset="hero.webp" type="image/webp">
|
|
177
|
+
<img src="hero.jpg"
|
|
178
|
+
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
|
|
179
|
+
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
180
|
+
alt="Hero" width="1200" height="675"
|
|
181
|
+
loading="lazy" decoding="async">
|
|
182
|
+
</picture>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Rules:** Never lazy-load above-the-fold images (hurts LCP). Use `fetchpriority="high"` on LCP image. Always include `width`/`height` for CLS prevention.
|
|
186
|
+
|
|
187
|
+
### Blur-Up Placeholder
|
|
188
|
+
|
|
189
|
+
```css
|
|
190
|
+
.img-placeholder {
|
|
191
|
+
background: url('data:image/webp;base64,...') center/cover;
|
|
192
|
+
aspect-ratio: 16/9;
|
|
193
|
+
}
|
|
194
|
+
.img-placeholder img {
|
|
195
|
+
opacity: 0; transition: opacity 0.3s;
|
|
196
|
+
&.loaded { opacity: 1; }
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 4. Font Performance
|
|
203
|
+
|
|
204
|
+
### Optimal Loading Strategy
|
|
205
|
+
|
|
206
|
+
```html
|
|
207
|
+
<link rel="preload" href="/fonts/display.woff2" as="font" type="font/woff2" crossorigin>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```css
|
|
211
|
+
@font-face {
|
|
212
|
+
font-family: 'Display';
|
|
213
|
+
src: url('/fonts/display.woff2') format('woff2');
|
|
214
|
+
font-weight: 100 900;
|
|
215
|
+
font-display: swap;
|
|
216
|
+
unicode-range: U+0000-00FF;
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### font-display Decision Guide
|
|
221
|
+
- **`swap`**: shows fallback immediately, swaps when loaded. Best for body text. Causes FOUT.
|
|
222
|
+
- **`optional`**: uses web font only if cached/instant. Best CLS score.
|
|
223
|
+
- **`fallback`**: 100ms blank, then fallback, short swap window. Good compromise.
|
|
224
|
+
- **`block`**: up to 3s invisible text (FOIT). Avoid for body text.
|
|
225
|
+
|
|
226
|
+
### Variable Fonts
|
|
227
|
+
One file replaces multiple weight/style files. Use when you need 3+ weights. A single variable font (~90KB) replaces 6 static files (360KB+).
|
|
228
|
+
|
|
229
|
+
### Subsetting
|
|
230
|
+
Strip unused glyphs with `pyftsubset` or `glyphhanger`. Can reduce 200KB+ files to 15-30KB.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 5. Critical CSS & Resource Hints
|
|
235
|
+
|
|
236
|
+
### Critical CSS Pattern
|
|
237
|
+
|
|
238
|
+
```html
|
|
239
|
+
<head>
|
|
240
|
+
<style>/* inlined above-the-fold styles, ~14KB max */</style>
|
|
241
|
+
<link rel="preload" href="/styles.css" as="style" onload="this.rel='stylesheet'">
|
|
242
|
+
<noscript><link rel="stylesheet" href="/styles.css"></noscript>
|
|
243
|
+
</head>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Resource Hints
|
|
247
|
+
|
|
248
|
+
```html
|
|
249
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
250
|
+
<link rel="dns-prefetch" href="https://analytics.example.com">
|
|
251
|
+
<link rel="preload" href="/critical.woff2" as="font" crossorigin>
|
|
252
|
+
<link rel="prefetch" href="/next-page.js">
|
|
253
|
+
<link rel="modulepreload" href="/app.js">
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Build tools:** Use `critical` (npm) or `critters` (webpack/vite plugin) to auto-extract above-fold CSS at build time.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## 6. Tailwind CSS v4
|
|
261
|
+
|
|
262
|
+
Released January 2025. Core rewritten in Rust (Oxide engine). Full builds 3.8x faster, incremental rebuilds up to 182x faster.
|
|
263
|
+
|
|
264
|
+
### CSS-First Configuration
|
|
265
|
+
|
|
266
|
+
```css
|
|
267
|
+
@import "tailwindcss";
|
|
268
|
+
|
|
269
|
+
@theme {
|
|
270
|
+
--color-brand: oklch(0.65 0.25 260);
|
|
271
|
+
--font-display: "Satoshi", sans-serif;
|
|
272
|
+
--breakpoint-3xl: 1920px;
|
|
273
|
+
--ease-fluid: cubic-bezier(0.3, 0, 0, 1);
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
No `tailwind.config.js` needed. All customization lives in CSS via `@theme`.
|
|
278
|
+
|
|
279
|
+
### Key Changes
|
|
280
|
+
- **Automatic content detection** -- scans files, respects `.gitignore`.
|
|
281
|
+
- **Built on `@layer`, `@property`, `color-mix()`**.
|
|
282
|
+
- **Container queries** built in: `@sm:`, `@md:` variants.
|
|
283
|
+
- **3D transforms**: `rotate-x-45 transform-3d perspective-distant`.
|
|
284
|
+
- **`@starting-style`** support for enter/exit transitions with `transition-discrete`.
|
|
285
|
+
- **`not-*` variant**: `not-hover:opacity-75`, `not-last:border-b`.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 7. Advanced Animation APIs
|
|
290
|
+
|
|
291
|
+
### View Transitions API
|
|
292
|
+
|
|
293
|
+
```css
|
|
294
|
+
@view-transition { navigation: auto; }
|
|
295
|
+
.hero-image { view-transition-name: hero; }
|
|
296
|
+
::view-transition-old(hero) { animation: fade-out 0.3s ease-out; }
|
|
297
|
+
::view-transition-new(hero) { animation: fade-in 0.3s ease-in; }
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
```js
|
|
301
|
+
document.startViewTransition(() => updateDOM());
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Scroll-Driven Animations (No JS, Off Main Thread)
|
|
305
|
+
|
|
306
|
+
```css
|
|
307
|
+
.progress-bar {
|
|
308
|
+
animation: grow-width linear;
|
|
309
|
+
animation-timeline: scroll();
|
|
310
|
+
}
|
|
311
|
+
@keyframes grow-width { from { width: 0; } to { width: 100%; } }
|
|
312
|
+
|
|
313
|
+
.reveal {
|
|
314
|
+
animation: fade-slide-up linear both;
|
|
315
|
+
animation-timeline: view();
|
|
316
|
+
animation-range: entry 0% entry 100%;
|
|
317
|
+
}
|
|
318
|
+
@keyframes fade-slide-up {
|
|
319
|
+
from { opacity: 0; translate: 0 2rem; }
|
|
320
|
+
to { opacity: 1; translate: 0; }
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Web Animations API (WAAPI)
|
|
325
|
+
|
|
326
|
+
```js
|
|
327
|
+
element.animate(
|
|
328
|
+
[{ transform: 'translateY(0)', opacity: 1 },
|
|
329
|
+
{ transform: 'translateY(-20px)', opacity: 0 }],
|
|
330
|
+
{ duration: 300, easing: 'ease-out', fill: 'forwards' }
|
|
331
|
+
);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### GSAP ScrollTrigger
|
|
335
|
+
|
|
336
|
+
```js
|
|
337
|
+
gsap.to('.hero-title', {
|
|
338
|
+
scrollTrigger: {
|
|
339
|
+
trigger: '.hero', start: 'top top', end: 'bottom top',
|
|
340
|
+
scrub: true, pin: true
|
|
341
|
+
},
|
|
342
|
+
y: -100, opacity: 0, scale: 0.9
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Browser Support (Baseline 2025)
|
|
349
|
+
|
|
350
|
+
| Feature | Chrome | Firefox | Safari |
|
|
351
|
+
|---------|--------|---------|--------|
|
|
352
|
+
| CSS Nesting | 120+ | 117+ | 17.2+ |
|
|
353
|
+
| :has() | 105+ | 121+ | 15.4+ |
|
|
354
|
+
| @layer | 99+ | 97+ | 15.4+ |
|
|
355
|
+
| Subgrid | 117+ | 71+ | 16+ |
|
|
356
|
+
| Anchor Positioning | 125+ | Nightly | No |
|
|
357
|
+
| View Transitions (SPA) | 111+ | 144+ | 18+ |
|
|
358
|
+
| Scroll-driven Animations | 115+ | Nightly | No |
|
|
359
|
+
| Popover API | 114+ | 125+ | 17+ |
|
|
360
|
+
| @property | 85+ | 128+ | 15.4+ |
|
|
361
|
+
| color-mix() | 111+ | 113+ | 16.2+ |
|