Vue.js: Bind de Class & Style

Última atualização: 2026-08-26

:class e :style são os dois bindings mais comumente usados no Vue — eles permitem alternar dinamicamente nomes de classes CSS e estilos inline com base nos dados. Essencialmente, são duas formas sintáticas especiais de v-bind; por serem usados com tanta frequência, foram implementados como “açúcar sintático”.

Dominar esses 5 estilos de escrita é suficiente para cobrir 95% dos cenários: sintaxe de objetos, sintaxe de matrizes, operadores ternários, propriedades calculadas e concatenação de strings.

1. O que você vai aprender


2. Um desafio de estilo com uma etiqueta de status do pedido

(1) Problema: 5 estados, 5 instruções “if”

Alice precisava exibir 5 status de ordem no painel de administração com cores diferentes:

HTML
<!-- ❌ The "Broken" Version: 5 v-if with class -->
<span v-if="status === 'pending'" class="badge yellow">Pending</span>
<span v-else-if="status === 'paid'" class="badge green">Paid</span>
<span v-else-if="status === 'shipped'" class="badge blue">Shipped</span>
<span v-else-if="status === 'delivered'" class="badge gray">Delivered</span>
<span v-else class="badge red">Cancelled</span>

O gerente de produto Charlie:

“Alice, isso ficou feio. E se a gente adicionar mais três status no mês que vem? Não dá pra simplesmente copiar e colar. Precisamos de uma abordagem dinâmica e organizada.”

(2) Vue :class Solução: Lidar com 5 estados em apenas 1 linha

VUE
<template>
  <span :class="['badge', statusClass]">{{ statusText }}</span>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({ status: String })

const statusClass = computed(() => ({
  pending: 'yellow',
  paid: 'green',
  shipped: 'blue',
  delivered: 'gray',
  cancelled: 'red'
}[props.status]))

const statusText = computed(() => ({
  pending: 'Pending',
  paid: 'Paid',
  shipped: 'Shipped',
  delivered: 'Delivered',
  cancelled: 'Cancelled'
}[props.status]))
</script>

(3) Receita


3. 5 maneiras de escrever :class

(1) Sintaxe de strings

VUE
<template>
  <!-- Static -->
  <div class="active">Static</div>
  
  <!-- Dynamic Strings -->
  <div :class="className">Dynamic</div>
</template>

<script setup>
import { ref } from 'vue'
const className = ref('active text-bold')
</script>

(2) Sintaxe de objetos (a mais comum)

VUE
<template>
  <!-- Basics: isActive is true, Add active class -->
  <div :class="{ active: isActive }">Single</div>
  
  <!-- Multiple conditions -->
  <div :class="{
    active: isActive,
    'text-danger': hasError,
    disabled: !canEdit
  }">
    Multiple
  </div>
  
  <!-- Computed properties return objects -->
  <div :class="classObject">Computed</div>
</template>

<script setup>
import { ref, computed } from 'vue'

const isActive = ref(true)
const hasError = ref(false)
const canEdit = ref(true)

// Computed Properties:Dynamic Return class Object
const classObject = computed(() => ({
  active: isActive.value && !hasError.value,
  'text-danger': hasError.value,
  'bg-success': isActive.value
}))
</script>

(3) Sintaxe de matrizes

VUE
<template>
  <!-- Array: Several class concatenation -->
  <div :class="[activeClass, errorClass]">Array</div>
  
  <!-- Trinomial Expression -->
  <div :class="[isActive ? 'active' : '', errorClass]">Ternary</div>
  
  <!-- Array + Object Mixing -->
  <div :class="[activeClass, { 'text-danger': hasError }]">Mixed</div>
  
  <!-- Nested Objects in an Array -->
  <div :class="[{ active: isActive }, errorClass]">Nested</div>
</template>

<script setup>
import { ref } from 'vue'
const activeClass = ref('active')
const errorClass = ref('text-danger')
const isActive = ref(true)
const hasError = ref(false)
</script>

(4) Coexistência com classes estáticas

VUE
<template>
  <!-- Static + Dynamic Merging(Vue Automatic Merge) -->
  <div class="static-class" :class="{ active: isActive }">
    Both
  </div>
  
  <!-- In the end class: "static-class active" or "static-class" -->
</template>

(5) Aulas sobre componentes

VUE
<!-- Parent Component -->
<UserCard class="shadow-lg" :class="{ active: isActive }" />

<!-- Child component UserCard.vue -->
<template>
  <!-- Receive -->
  <div :class="$attrs.class">
    <!-- Rendering "shadow-lg active" -->
  </div>
</template>

4. 5 maneiras de escrever :style

(1) Sintaxe de objetos

VUE
<template>
  <!-- Basic Objects -->
  <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">
    Object
  </div>
</template>

<script setup>
import { ref } from 'vue'
const activeColor = ref('red')
const fontSize = ref(16)
</script>

(2) Conversão de nomes de propriedades CSS

O Vue converte automaticamente as convenções de nomenclatura do JavaScript para as convenções de nomenclatura do CSS:

VUE
<template>
  <div :style="{
    backgroundColor: 'red',        // → background-color
    fontSize: '16px',              // → font-size
    marginTop: '10px',             // → margin-top
    WebkitTransform: 'scale(2)'     // → -webkit-transform
  }">
    CSS naming
  </div>
</template>

(3) Sintaxe de matrizes (combinação de vários objetos)

VUE
<template>
  <!-- Array:Merge style objects in order(The later one overrides the earlier one)-->
  <div :style="[baseStyles, overrideStyles]">Array</div>
</template>

<script setup>
import { ref } from 'vue'

const baseStyles = ref({
  color: 'blue',
  fontSize: '14px'
})

const overrideStyles = ref({
  color: 'red',  // Coverage baseStyles.color
  fontWeight: 'bold'
})
</script>

(4) Aplicação automática de prefixos

O Vue 3 adiciona automaticamente prefixos de navegador às propriedades CSS (com base no mecanismo do navegador):

JS
// Write:
{ transform: 'rotate(45deg)' }

// Vue Auto-add:
{
  -webkit-transform: 'rotate(45deg)',
  transform: 'rotate(45deg)'
}

(5) Variáveis CSS (recomendado para o Vue 3)

VUE
<template>
  <div :style="{
    '--main-color': mainColor,
    '--spacing': spacing + 'px'
  }">
    CSS Variables
  </div>
</template>

<script setup>
import { ref } from 'vue'
const mainColor = ref('#42b883')
const spacing = ref(20)
</script>

<style>
.dynamic {
  color: var(--main-color);
  padding: var(--spacing);
}
</style>

5. Exemplo completo: Status dinâmico do pedido

▶ Exemplo: 1. 5 maneiras de escrever :class

VUE
<template>
  <!-- 1. String -->
  <div :class="className">String</div>
  
  <!-- 2. Object -->
  <div :class="{ active: isActive, error: hasError }">Object</div>
  
  <!-- 3. Array -->
  <div :class="[activeClass, errorClass]">Array</div>
  
  <!-- 4. Array + Object -->
  <div :class="[activeClass, { disabled: !canEdit }]">Mixed</div>
  
  <!-- 5. Computed Properties -->
  <div :class="dynamicClass">Computed</div>
</template>

<script setup>
import { ref, computed } from 'vue'
const isActive = ref(true)
const hasError = ref(false)
const canEdit = ref(true)
const className = ref('badge')
const activeClass = ref('active')
const errorClass = ref('error')

const dynamicClass = computed(() => ({
  active: isActive.value,
  error: hasError.value,
  'cursor-not-allowed': !canEdit.value
}))
</script>
▶ Experimente

▶ Exemplo: 2. 5 maneiras de escrever :style

VUE
<template>
  <!-- 1. Basic Objects -->
  <div :style="{ color: 'red', fontSize: '16px' }">Object</div>
  
  <!-- 2. Multiple properties -->
  <div :style="{ backgroundColor: bg, padding: p + 'px' }">Multi</div>
  
  <!-- 3. Merging Sets -->
  <div :style="[baseStyles, themeStyles]">Array</div>
  
  <!-- 4. CSS Variable -->
  <div :style="{ '--theme-color': theme }">CSS Var</div>
  
  <!-- 5. Computed Properties -->
  <div :style="computedStyle">Computed</div>
</template>

<script setup>
import { ref, computed } from 'vue'
const bg = ref('#42b883')
const p = ref(20)
const theme = ref('#35495e')
const baseStyles = ref({ color: 'white' })
const themeStyles = ref({ backgroundColor: '#42b883' })

const computedStyle = computed(() => ({
  color: 'white',
  backgroundColor: theme.value,
  padding: `${p.value}px`
}))
</script>
▶ Experimente

▶ Exemplo: 3. Emblema de status do pedido

VUE 📖 Somente leitura
<template>
  <span :class="['order-badge', statusClass]">
    {{ statusText }}
  </span>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  status: { type: String, required: true }
})

// 5 Status → 5 class
const statusClass = computed(() => {
  const map = {
    pending: 'bg-yellow',
    paid: 'bg-green',
    shipped: 'bg-blue',
    delivered: 'bg-gray',
    cancelled: 'bg-red'
  }
  return map[props.status] || 'bg-default'
})

const statusText = computed(() => {
  const map = {
    pending: 'Pending',
    paid: 'Paid',
    shipped: 'Shipped',
    delivered: 'Delivered',
    cancelled: 'Cancelled'
  }
  return map[props.status] || 'Unknown'
})
</script>

<style scoped>
.order-badge {
  padding: 4px 12px;
  border-radius: 12px;
  color: white;
  font-size: 12px;
}
.bg-yellow { background: #f59e0b; }
.bg-green { background: #10b981; }
.bg-blue { background: #3b82f6; }
.bg-gray { background: #6b7280; }
.bg-red { background: #ef4444; }
</style>
44 linhas de lógica (limite de 40, somente leitura)

▶ Exemplo: 4. 5 erros comuns

Erro Sintoma Solução
A classe String não está respondendo A classe está codificada de forma rígida e não muda Vinculada usando :class
Nome incorreto da classe de array Várias classes com o mesmo nome se sobrescrevendo mutuamente Uso da sintaxe de objeto
Unidade de estilo ausente O número 16 é interpretado como 16px e é ignorado A sequência de caracteres '16px' é exibida
Nome incorreto da propriedade CSS font-size deveria ser fontSize Use camelCase ou aspas
:conflito de classe Colisão de nomes estáticos e dinâmicos O Vue os mescla automaticamente, tudo bem

▶ Exemplo: 5. 5 Comparações de desempenho

Implementação Resultado da compilação Desempenho Aplicabilidade
String Concatenação direta de strings ⭐⭐⭐⭐⭐ Simples
Objeto Análise estática ⭐⭐⭐⭐ Moderado
Matrizes Concatenação de strings ⭐⭐⭐⭐ Várias classes
Matrizes + Objetos Tratamento misto ⭐⭐⭐ Complexo
Propriedade calculada Valor armazenado em cache ⭐⭐⭐⭐⭐ Lógica complexa

▶ Exemplo: 6. As 5 principais diferenças entre classe e estilo

Aspecto classe estilo
Avaliação ⭐⭐⭐⭐⭐ ⭐⭐⭐
Reutilização de CSS Fácil (reutilização de nomes de classes) Difícil (estilos dispersos)
Desempenho Superior (otimização do navegador) Ligeiramente inferior
Prioridade Depende do seletor Em linha (mais alta)
Troca de tema Fácil (alterar classe) Fácil (alterar variável CSS)

❓ Perguntas Frequentes

P: As ligações de classe e de estilo podem coexistir? R: Sim. As ligações estáticas class="x" e dinâmicas :class="{active: y}" são automaticamente combinadas (resultando em class="x active" ou "x").

P: Por que o atributo style precisa ser escrito como um objeto? Não posso simplesmente usar uma string de CSS? R: Sim, você pode. <div style="color: red"> é a sintaxe nativa do HTML, e <div :style="'color: red'"> também é uma abordagem baseada em string. No entanto, usar um objeto :style="{ color: 'red' }" permite que você vincule variáveis dinamicamente. Recomendamos o uso de um objeto.

P: Como se usa variáveis CSS? R: Use {'--my-var': value} em :style e var(--my-var) no CSS. O Vue 3 recomenda o uso de variáveis CSS para a troca de temas, pois é mais eficiente do que vincular estilos diretamente (basta atualizar uma única variável, e o DOM não será reajustado).

P: Como os componentes recebem classes externas? R: Os componentes de raiz única herdam automaticamente o atributo class (comportamento padrão do Vue 3). Os componentes de raízes múltiplas usam $attrs.class para se vincular explicitamente a um elemento específico.

P: Qual é a ordem das classes na sintaxe de array? R: Elas são concatenadas na ordem em que aparecem no array, mas a ordem não afeta a especificidade do CSS (que é determinada pela especificidade dos seletores CSS).

P: É possível usar :class com v-if? R: Sim. <div v-if="show" :class="{ active: isActive }"> Quando show=false, o elemento inteiro não é renderizado, e isActive não tem efeito.

P: Como faço para alternar temas dinamicamente? R: Recomendamos o uso de variáveis CSS. :style="{ '--primary': theme.primary }" se aplica a todos os elementos color: var(--primary). Para alternar temas, basta alterar apenas uma variável, o que é mais eficiente do que alterar 100 classes.


📖 Resumo


📝 Exercícios

  1. Questões básicas (Dificuldade: ⭐)

    Use o seletor :class para implementar três estados do botão:

    • principal: texto branco sobre fundo azul
    • sucesso: texto branco sobre fundo verde
    • perigo: texto branco sobre fundo vermelho

    Dados: const variant = ref('primary')

  2. Problemas avançados (Dificuldade: ⭐⭐)

    Implemente uma lista de pedidos em que cada linha exiba um ícone em uma cor diferente, de acordo com o status do pedido:

    • 5 status (em espera/pago/enviado/entregue/cancelado)
    • Retornar um objeto class usando uma propriedade calculada
    • :style Adicione a cor do ícone correspondente ao status
  3. Problema desafiador (Dificuldade: ⭐⭐⭐)

    Implementar um sistema completo de troca de temas:

    1. 3 temas (claro/escuro/alto contraste)
    2. Use variáveis CSS para definir as cores do tema (primária/secundária/fundo/texto)
    3. :class — Alterar o nome da classe do tema
    4. Use o localStorage para lembrar a seleção do usuário
    5. A troca de temas não atualiza a página (o design responsivo é atualizado automaticamente)
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%