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.
4.4 KiB
4.4 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| Use Class Selectors in Scoped CSS for Performance | MEDIUM | Element selectors in scoped CSS are slower because browsers must check both the element type and data attribute | efficiency |
|
Use Class Selectors in Scoped CSS for Performance
Impact: MEDIUM - When Vue compiles scoped CSS, it adds attribute selectors to every rule. Element selectors combined with attribute selectors (e.g., p[data-v-xxx]) are significantly slower for browsers to match than class selectors with attributes (e.g., .text[data-v-xxx]).
Task Checklist
- Prefer class selectors over element selectors in scoped styles
- Avoid deeply nested element selectors in scoped CSS
- Use BEM or similar naming conventions to ensure unique class names
- For heavy styling, consider CSS modules or utility-first approaches
Problematic Code:
<template>
<article>
<header>
<h1>{{ title }}</h1>
<p>{{ subtitle }}</p>
</header>
<section>
<p>{{ content }}</p>
<ul>
<li v-for="item in items" :key="item">{{ item }}</li>
</ul>
</section>
</article>
</template>
<style scoped>
/* BAD: Element selectors are slower when scoped */
article {
max-width: 800px;
}
header {
margin-bottom: 2rem;
}
h1 {
font-size: 2rem;
}
p {
line-height: 1.6;
}
ul {
padding-left: 1.5rem;
}
li {
margin-bottom: 0.5rem;
}
</style>
Correct Code:
<template>
<article class="article">
<header class="article-header">
<h1 class="article-title">{{ title }}</h1>
<p class="article-subtitle">{{ subtitle }}</p>
</header>
<section class="article-content">
<p class="article-text">{{ content }}</p>
<ul class="article-list">
<li v-for="item in items" :key="item" class="article-list-item">
{{ item }}
</li>
</ul>
</section>
</article>
</template>
<style scoped>
/* GOOD: Class selectors are faster */
.article {
max-width: 800px;
}
.article-header {
margin-bottom: 2rem;
}
.article-title {
font-size: 2rem;
}
.article-subtitle,
.article-text {
line-height: 1.6;
}
.article-list {
padding-left: 1.5rem;
}
.article-list-item {
margin-bottom: 0.5rem;
}
</style>
How Scoped CSS Compiles
Vue transforms scoped CSS by adding data attributes:
/* What you write */
p {
color: red;
}
.text {
color: blue;
}
/* What Vue generates */
p[data-v-7ba5bd90] {
color: red;
}
.text[data-v-7ba5bd90] {
color: blue;
}
Browser CSS matching for p[data-v-xxx]:
- Find all
<p>elements (element lookup) - Check each for the
data-v-xxxattribute (attribute check)
Browser CSS matching for .text[data-v-xxx]:
- Find all elements with class
text(class lookup - optimized) - Check each for the
data-v-xxxattribute
Class lookups are highly optimized in modern browsers, making option 2 faster.
When Performance Matters
This optimization matters most when:
- Rendering large lists (100+ items)
- Complex component trees
- Animation-heavy interfaces
- Mobile devices with limited CPU
<template>
<!-- 1000 items - performance difference is noticeable -->
<ul class="list">
<li v-for="item in items" :key="item.id" class="list-item">
<span class="item-name">{{ item.name }}</span>
<span class="item-price">{{ item.price }}</span>
</li>
</ul>
</template>
<style scoped>
/* Fast selectors for large lists */
.list { ... }
.list-item { ... }
.item-name { ... }
.item-price { ... }
</style>
Acceptable Element Selectors
For small components with few elements, element selectors are fine:
<template>
<button class="btn">
<span>{{ label }}</span>
</button>
</template>
<style scoped>
/* OK for small, simple components */
.btn {
padding: 0.5rem 1rem;
}
span {
font-weight: bold;
}
</style>
CSS Modules Alternative
For performance-critical components, CSS modules avoid the attribute selector entirely:
<template>
<p :class="$style.text">Content</p>
</template>
<style module>
/* Generates unique class names without attribute selectors */
.text {
color: red;
}
/* Compiles to something like: .text_abc123 { color: red; } */
</style>