\n\n\n\n\n```\n\n## Способ 2: CSS Modules\n\n```javascript\n// Component.vue\n\n\n\n\n\n```\n\n## Способ 3: BEM (Block Element Modifier)\n\n```javascript\n// UserCard.vue\n\n\n\n\n\n```\n\n## Способ 4: CSS-in-JS с Tailwind CSS\n\n```javascript\n// UserCard.vue\n\n```\n\n## Способ 5: Комбинированный подход\n\n```javascript\n// Используем scoped для простых стилей\n// Используем CSS Modules для сложных стилей\n\n\n\n\n```\n\n## Сравнение методов\n\n- Scoped CSS: Просто, встроено в Vue\n- CSS Modules: Явная изоляция, уникальные имена\n- BEM: Читаемо, масштабируемо\n- Tailwind: Быстро, много утилит\n- Комбинированный: Гибкость и лучшее из всех","dateCreated":"2026-04-03T17:56:12.325843","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как реализовать изоляцию CSS в компонентах Vue?

2.0 Middle🔥 111 комментариев
#HTML и CSS

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое CSS изоляция?

CSS изоляция — это концепция ограничения области действия CSS стилей только компонентом, в котором они определены. Без изоляции стили компонента могут случайно затронуть другие компоненты. Vue предоставляет несколько способов достичь CSS изоляции.

Способ 1: Scoped CSS (встроенный в Vue)

// Component.vue
<template>
  <div class="container">
    <h1>{{ title }}</h1>
    <p class="description">{{ description }}</p>
    <button class="btn">Click me</button>
  </div>
</template>

<script setup>
defineProps({
  title: String,
  description: String
});
</script>

<style scoped>
.container {
  padding: 20px;
  background-color: #f5f5f5;
  border-radius: 8px;
}

h1 {
  color: #333;
  font-size: 24px;
}

.description {
  color: #666;
  margin: 10px 0;
}

.btn {
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.btn:hover {
  background-color: #0056b3;
}
</style>

<!-- Vue добавляет data-атрибут каждому элементу:
<div class="container" data-v-f3f3eg9c>

И модифицирует CSS селекторы:
.container[data-v-f3f3eg9c] { ... }
-->

Способ 2: CSS Modules

// Component.vue
<template>
  <div :class="styles.container">
    <h1 :class="styles.title">{{ title }}</h1>
    <p :class="styles.description">{{ description }}</p>
    <button :class="[styles.btn, isActive && styles.btnActive]">
      Click me
    </button>
  </div>
</template>

<script setup>
import { ref } from "vue";
import styles from "./Component.module.css";

defineProps({
  title: String,
  description: String
});

const isActive = ref(false);
</script>

<style module="styles">
.container {
  padding: 20px;
  background-color: #f5f5f5;
  border-radius: 8px;
}

.title {
  color: #333;
  font-size: 24px;
}

.description {
  color: #666;
  margin: 10px 0;
}

.btn {
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.btnActive {
  background-color: #0056b3;
}
</style>

Способ 3: BEM (Block Element Modifier)

// UserCard.vue
<template>
  <div class="user-card">
    <div class="user-card__header">
      <img :src="avatar" :alt="name" class="user-card__avatar" />
      <h2 class="user-card__name">{{ name }}</h2>
    </div>
    <div class="user-card__body">
      <p class="user-card__bio">{{ bio }}</p>
      <div class="user-card__tags">
        <span
          v-for="tag in tags"
          :key="tag"
          class="user-card__tag"
        >
          {{ tag }}
        </span>
      </div>
    </div>
    <div class="user-card__footer">
      <button
        class="user-card__btn user-card__btn--primary"
        @click="handleFollow"
      >
        Follow
      </button>
      <button
        class="user-card__btn user-card__btn--secondary"
        @click="handleMessage"
      >
        Message
      </button>
    </div>
  </div>
</template>

<script setup>
defineProps({
  name: String,
  avatar: String,
  bio: String,
  tags: Array
});

const emit = defineEmits(["follow", "message"]);

const handleFollow = () => emit("follow");
const handleMessage = () => emit("message");
</script>

<style scoped>
.user-card {
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.user-card__header {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
}

.user-card__avatar {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  object-fit: cover;
}

.user-card__name {
  font-size: 18px;
  font-weight: bold;
}

.user-card__body {
  margin-bottom: 16px;
}

.user-card__bio {
  color: #666;
  font-size: 14px;
}

.user-card__tag {
  display: inline-block;
  padding: 4px 12px;
  background-color: #e0e0e0;
  border-radius: 20px;
  font-size: 12px;
}

.user-card__btn {
  padding: 8px 12px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.user-card__btn--primary {
  background-color: #007bff;
  color: white;
}

.user-card__btn--primary:hover {
  background-color: #0056b3;
}

.user-card__btn--secondary {
  background-color: #f0f0f0;
  color: #333;
}
</style>

Способ 4: CSS-in-JS с Tailwind CSS

// UserCard.vue
<template>
  <div class="p-5 border border-gray-300 rounded-lg max-w-sm">
    <div class="flex gap-3 mb-4">
      <img
        :src="avatar"
        :alt="name"
        class="w-15 h-15 rounded-full object-cover"
      />
      <h2 class="text-lg font-bold text-gray-900 self-center">{{ name }}</h2>
    </div>
    <div class="mb-4">
      <p class="text-sm text-gray-600 mb-3">{{ bio }}</p>
      <div class="flex flex-wrap gap-2">
        <span
          v-for="tag in tags"
          :key="tag"
          class="px-3 py-1 bg-gray-200 rounded-full text-xs"
        >
          {{ tag }}
        </span>
      </div>
    </div>
    <div class="flex gap-2">
      <button
        class="flex-1 px-3 py-2 bg-blue-500 text-white rounded hover:bg-blue-700"
        @click="handleFollow"
      >
        Follow
      </button>
      <button
        class="flex-1 px-3 py-2 bg-gray-200 rounded hover:bg-gray-300"
        @click="handleMessage"
      >
        Message
      </button>
    </div>
  </div>
</template>

Способ 5: Комбинированный подход

// Используем scoped для простых стилей
// Используем CSS Modules для сложных стилей

<style scoped>
.wrapper {
  padding: 20px;
  background-color: #f9f9f9;
}

.header {
  border-bottom: 2px solid #007bff;
  padding-bottom: 10px;
  margin-bottom: 20px;
}
</style>

<style module="styles">
.content {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

.cardWrapper {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
</style>

Сравнение методов

  • Scoped CSS: Просто, встроено в Vue
  • CSS Modules: Явная изоляция, уникальные имена
  • BEM: Читаемо, масштабируемо
  • Tailwind: Быстро, много утилит
  • Комбинированный: Гибкость и лучшее из всех
Как реализовать изоляцию CSS в компонентах Vue? | PrepBro