Progressive Enhancement guide with CSS-first approach and outcome-first development philosophy. Use when working with layout (レイアウト), styling (スタイル), positioning (位置), animations (アニメーション), show/hide functionality (表示/非表示), toggles (トグル), responsive design (レスポンシブ), CSS Grid, Flexbox, transforms, transitions, or when seeking CSS-only solutions (CSSのみ/JavaScript不要). Suggests CSS solutions before JavaScript, promoting simple (シンプル), maintainable, and performant implementations based on "The best code is no code" and YAGNI philosophy.
Limited to specific tools
Additional assets for this skill
This skill is limited to using the following tools:
"The best code is no code" - If CSS can solve it, JavaScript is unnecessary
/* ✅ CSS Grid overlay */
.container {
display: grid;
}
.background, .foreground {
grid-column: 1 / -1;
grid-row: 1 / -1;
}
/* ❌ No JavaScript needed: avoid position: absolute */
Use cases:
/* ✅ Center alignment */
.center {
display: flex;
justify-content: center;
align-items: center;
}
/* ❌ No JavaScript needed: manual calculation and position setting */
/* ✅ Transform - no reflow */
.move-up {
transform: translateY(-10px);
transition: transform 0.3s;
}
/* ❌ Avoid top/left (causes reflow) */
.move-up-bad {
position: relative;
top: -10px; /* Triggers reflow */
}
Performance:
transform: GPU accelerated, no reflowtop/left/margin: CPU rendering, causes reflow/* ✅ visibility/opacity for animations */
.hidden {
visibility: hidden;
opacity: 0;
transition: opacity 0.3s, visibility 0s 0.3s;
}
.visible {
visibility: visible;
opacity: 1;
transition: opacity 0.3s;
}
/* ❌ display: none disappears instantly, no animation */
/* ✅ Mobile-first */
.component {
/* Mobile default styles */
flex-direction: column;
}
@media (min-width: 768px) {
.component {
flex-direction: row;
}
}
/* ❌ No JavaScript needed: window.innerWidth detection */
/* ✅ Based on component's own size */
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
grid-template-columns: 1fr 1fr;
}
}
/* ❌ ResizeObserver not needed */
/* ✅ URL hash-based state management */
.modal {
display: none;
}
.modal:target {
display: flex;
}
/* HTML: <a href="#modal">Open</a> */
/* ❌ No JavaScript needed: showModal(), hideModal() */
/* ✅ Checkbox state management */
.toggle:checked ~ .content {
max-height: 500px;
opacity: 1;
}
.toggle:not(:checked) ~ .content {
max-height: 0;
opacity: 0;
overflow: hidden;
}
/* ❌ No JavaScript needed: toggleClass() */
/* ✅ Parent element styling */
.form:has(input:invalid) .submit-button {
opacity: 0.5;
cursor: not-allowed;
}
/* ❌ No JavaScript needed: input.addEventListener('invalid') */
<details>
<summary>Click to expand</summary>
<p>Expanded content</p>
</details>
details {
border: 1px solid #ddd;
}
summary {
cursor: pointer;
padding: 1rem;
}
summary::marker {
content: '▶ ';
}
details[open] summary::marker {
content: '▼ ';
}
/* ❌ No JavaScript needed: onClick, setState, CSS class toggle */
Benefits:
.tooltip {
position: relative;
}
.tooltip::after {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
/* Hidden by default */
opacity: 0;
visibility: hidden;
transition: opacity 0.3s, visibility 0s 0.3s;
}
.tooltip:hover::after,
.tooltip:focus::after {
opacity: 1;
visibility: visible;
transition: opacity 0.3s;
}
/* HTML: <button class="tooltip" data-tooltip="Hint">Button</button> */
/* ❌ No JavaScript needed: position calculation, show/hide control */
.modal {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: none;
place-items: center;
}
.modal:target {
display: grid;
}
/* HTML: <a href="#myModal">Open</a> */
/* HTML: <div id="myModal" class="modal">...</div> */
/* ❌ No JavaScript needed: openModal(), closeModal() */
Before implementation, ask yourself:
Layout → Grid/Flexbox
Position → Transform
Display control → visibility/opacity
State management → :target, :checked, :has()
Animation → transition/animation
❓ Is there an actual problem occurring?
❓ Have users requested this?
❓ Is there measurable evidence?
All No → Don't implement yet
Option A: 3 lines of CSS
Option B: 50 lines of JavaScript + 10 lines of CSS
→ Choose Option A
User: "I want cards to scale up on hover"
Skill auto-triggers →
"From a Progressive Enhancement perspective, this can be achieved with CSS transform:
```css
.card {
transition: transform 0.3s;
}
.card:hover {
transform: scale(1.05);
}
```
No JavaScript needed."
Layout questions
Animation questions
State management questions
Responsive questions
<details>, :has(), etc.)Remember: "The best code is code that doesn't need to exist"