963 markdown files reformatted with the repository's pinned prettier so pnpm format:check covers the folded tree like every other repo file. The formatter's embedded-language pass also normalized code fences (TS semicolons, closed HTML tags in examples, lowercased CSS hex colors, one renumbered list that skipped an index). Alphanumeric token deltas vs the fold commit were audited file-by-file; all are formatter-equivalent markup normalizations plus the four sanitized skills.
3.8 KiB
3.8 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | ||||
|---|---|---|---|---|---|---|---|---|
| Scoped Styles May Not Apply to Teleported Content | MEDIUM | Scoped styles can fail to apply to teleported elements due to data attribute limitations | gotcha |
|
Scoped Styles May Not Apply to Teleported Content
Impact: MEDIUM - When using scoped styles with Teleport, the styles may not apply correctly to teleported elements. This is a known limitation related to how Vue's scoped style attributes work with elements rendered outside the component's DOM tree.
Task Checklist
- Test scoped styles on teleported content
- Use
:deep()selector or non-scoped styles for teleported content - Consider CSS modules as an alternative
- Keep teleported content styles in a separate non-scoped style block
Problem - Scoped Styles Not Applied:
<template>
<Teleport to="body">
<div class="modal">
<p class="modal-text">This text may not be styled!</p>
</div>
</Teleport>
</template>
<style scoped>
/* These styles may NOT apply to teleported content */
.modal {
background: white;
padding: 20px;
}
.modal-text {
color: blue; /* May not work */
}
</style>
Solution 1 - Use Non-Scoped Styles for Teleported Content:
<template>
<Teleport to="body">
<div class="my-modal">
<p class="my-modal-text">This text will be styled</p>
</div>
</Teleport>
</template>
<style scoped>
/* Component-specific styles */
.button {
color: blue;
}
</style>
<style>
/* Non-scoped styles for teleported content */
/* Use specific class names to avoid conflicts */
.my-modal {
background: white;
padding: 20px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.my-modal-text {
color: blue;
}
</style>
Solution 2 - Use :deep() Selector:
<template>
<Teleport to="body">
<div class="modal">
<p class="modal-text">Styled with :deep()</p>
</div>
</Teleport>
</template>
<style scoped>
:deep(.modal) {
background: white;
padding: 20px;
}
:deep(.modal-text) {
color: blue;
}
</style>
Solution 3 - CSS Modules:
<template>
<Teleport to="body">
<div :class="$style.modal">
<p :class="$style.modalText">Styled with CSS modules</p>
</div>
</Teleport>
</template>
<style module>
.modal {
background: white;
padding: 20px;
}
.modalText {
color: blue;
}
</style>
Multi-Root Components with Teleport
Using Teleport as one of multiple root nodes causes additional issues:
<template>
<!-- Multi-root component -->
<button @click="open = true">Open</button>
<Teleport to="body">
<div class="modal">Content</div>
</Teleport>
</template>
<!-- Warning: class/style attributes may not be inherited -->
Pass classes explicitly to avoid inheritance issues:
<template>
<button @click="open = true">Open</button>
<Teleport to="body">
<div :class="['modal', $attrs.class]" :style="$attrs.style">Content</div>
</Teleport>
</template>
Best Practice: Dedicated Modal Styles
Create a dedicated stylesheet for modal/overlay components:
/* modal-styles.css */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
}
.modal-content {
background: white;
border-radius: 8px;
padding: 24px;
max-width: 500px;
width: 90%;
}
<script setup>
import './modal-styles.css';
</script>
<template>
<Teleport to="body">
<div v-if="open" class="modal-overlay">
<div class="modal-content">
<slot />
</div>
</div>
</Teleport>
</template>