Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.6 KiB
4.6 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| Scoped CSS Cannot Style Slot Content Directly | HIGH | Slot content receives the parent component's scope, not the child's, causing styles to fail unexpectedly | gotcha |
|
Scoped CSS Cannot Style Slot Content Directly
Impact: HIGH - When a parent passes content through a slot, that content receives the parent component's scoped style attributes, not the child component's. This means the child component cannot style slot content with regular scoped CSS.
Task Checklist
- Use
:deep()selector in the wrapper component to style slot content - Alternatively, use
:slotted()pseudo-selector to target slotted elements - For complex slot styling, consider using CSS modules or unscoped styles
- Document expected slot content structure when styling assumptions exist
Problematic Code:
<!-- Card.vue (child component) -->
<template>
<div class="card">
<div class="card-body">
<slot />
</div>
</div>
</template>
<style scoped>
.card-body {
padding: 1rem;
}
/* BAD: Won't apply to slot content! */
.card-body h2 {
color: #333;
margin-bottom: 0.5rem;
}
.card-body p {
color: #666;
}
</style>
<!-- Parent.vue -->
<template>
<Card>
<!-- This h2 and p won't be styled by Card's scoped CSS -->
<h2>Card Title</h2>
<p>Card description text.</p>
</Card>
</template>
Correct Code:
<!-- Card.vue - Using :slotted() -->
<template>
<div class="card">
<div class="card-body">
<slot />
</div>
</div>
</template>
<style scoped>
.card-body {
padding: 1rem;
}
/* GOOD: :slotted() targets slot content */
:slotted(h2) {
color: #333;
margin-bottom: 0.5rem;
}
:slotted(p) {
color: #666;
}
</style>
Using :deep() Alternative
<!-- Card.vue - Using :deep() -->
<style scoped>
.card-body {
padding: 1rem;
}
/* :deep() also works for slot content */
.card-body :deep(h2) {
color: #333;
}
.card-body :deep(p) {
color: #666;
}
</style>
Why This Happens
Slot content is compiled in the parent component's scope:
<!-- Parent template compiles to: -->
<Card>
<h2 data-v-parent123>Card Title</h2>
<p data-v-parent123>Card description</p>
</Card>
<!-- Card template compiles to: -->
<div class="card" data-v-card456>
<div class="card-body" data-v-card456>
<slot /> <!-- Content inserted WITHOUT data-v-card456 -->
</div>
</div>
The <h2> has data-v-parent123, but Card's scoped CSS expects data-v-card456.
:slotted() vs :deep() for Slots
Both work, but have subtle differences:
<style scoped>
/* :slotted() - Specifically for slot content */
/* Only targets direct slotted elements */
:slotted(h2) {
color: blue;
}
/* :deep() - More general deep selector */
/* Can target nested elements within slot content */
.card-body :deep(h2) {
color: blue;
}
/* For nested elements in slot content, must use :deep() */
:slotted(.wrapper h2) { } /* Won't work for nested h2 */
.card-body :deep(.wrapper h2) { } /* Works for nested */
</style>
Combining with Named Slots
<template>
<div class="card">
<header class="card-header">
<slot name="header" />
</header>
<div class="card-body">
<slot />
</div>
<footer class="card-footer">
<slot name="footer" />
</footer>
</div>
</template>
<style scoped>
/* Style specific slot content */
.card-header :slotted(h1),
.card-header :slotted(h2) {
margin: 0;
font-size: 1.25rem;
}
.card-body :slotted(p) {
margin-bottom: 1rem;
}
.card-footer :slotted(button) {
margin-right: 0.5rem;
}
</style>
Performance Tip: Use Classes
Element selectors with :slotted() can be slower:
<style scoped>
/* SLOWER: Element selector */
:slotted(p) {
color: gray;
}
/* FASTER: Class selector */
:slotted(.card-text) {
color: gray;
}
</style>
When to Use Unscoped Styles
For complex slot styling, unscoped styles may be cleaner:
<template>
<article class="article-card">
<slot />
</article>
</template>
<style>
/* Unscoped with unique prefix for complex content styling */
.article-card h1,
.article-card h2,
.article-card h3 {
font-family: Georgia, serif;
line-height: 1.2;
}
.article-card p {
line-height: 1.6;
}
.article-card img {
max-width: 100%;
}
.article-card blockquote {
border-left: 3px solid #ccc;
padding-left: 1rem;
}
</style>