Vize

Vue Rules: Template Formatting

Every rule on this page includes its purpose, prerequisites, configuration, and complete Bad/Good examples. Highlighted lines show what changes; copying an example gives you the complete source. Each rule also states its current support limits.

Rule Examples Purpose
vue/attribute-hyphenation Bad · Good Enforce attribute naming style on custom components
vue/attribute-order Bad · Good Enforce a consistent order of attributes
vue/html-quotes Bad · Good Enforce quotes style of HTML attributes
vue/html-self-closing Bad · Good Enforce self-closing style
vue/mustache-interpolation-spacing Bad · Good Enforce consistent spacing inside mustache interpolations
vue/no-boolean-attr-value Bad · Good Disallow explicit values for boolean HTML attributes
vue/no-inline-style Bad · Good Discourage use of inline style attributes
vue/no-multi-spaces Bad · Good Disallow multiple consecutive spaces
vue/prefer-props-shorthand Bad · Good Recommend shorthand syntax for props (Vue 3.4+)
vue/prop-name-casing Bad · Good Enforce a casing for declared prop names
vue/valid-attribute-name Bad · Good Require valid attribute names

All rules · Rule Options · ESLint migration map · Project checks · Attributes across components

vue/attribute-hyphenation

Enforce attribute naming style on custom components

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/attribute-hyphenation": "warn"
      }
    },
  },
});
vp run lint

Bad

The component attribute uses the camelCase spelling firstName.

<template>
<UserCard firstName="Ada" />
</template>

Good

The first-name spelling follows the configured hyphenated component-attribute convention.

<template>
<UserCard first-name="Ada" />
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/attribute-order

Enforce a consistent order of attributes

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/attribute-order": "warn"
      }
    },
  },
});
vp run lint

Bad

The event handler appears before the structural v-if directive and ordinary id attribute.

<template>
  <div @click="onClick" v-if="show" id="main"></div>
</template>

Good

v-if comes first, followed by id and then the event handler, following the rule ordering.

<template>
  <div v-if="show" id="main" @click="onClick"></div>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/html-quotes

Enforce quotes style of HTML attributes

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/html-quotes": "warn"
      }
    },
  },
});
vp run lint

Bad

The attributes use single quotes or no quotes instead of the double-quote convention.

<template>
  <div class='foo'></div>
  <div class=foo></div>
  <div v-if='ready'></div>
</template>

Good

Both ordinary attributes and directive expressions use double quotes.

<template>
  <div class="foo"></div>
  <div v-if="ready"></div>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/html-self-closing

Enforce self-closing style

Bad · Good

Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: See typed options and defaults.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/html-self-closing": "warn"
      }
    },
  },
});
vp run lint

Bad

The empty component uses a closing pair, while void img and br elements omit the configured self-closing spelling.

<template>
  <MyComponent></MyComponent>
  <img>
  <br>
</template>

Good

The component and void elements use self-closing syntax; a div with content retains its closing tag.

<template>
  <MyComponent />
  <div></div>
  <div />
  <img />
  <br />
  <div>content</div>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/mustache-interpolation-spacing

Enforce consistent spacing inside mustache interpolations

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/mustache-interpolation-spacing": "warn"
      }
    },
  },
});
vp run lint

Bad

The text interpolation is missing a space at one or both delimiter boundaries.

<template>
  <div>{{text}}</div>
  <div>{{ text}}</div>
  <div>{{text }}</div>
</template>

Good

Spaces separate the expression from both opening and closing mustache delimiters.

<template>
  <div>{{ text }}</div>
  <div>{{ foo.bar }}</div>
  <div>{{ foo + bar }}</div>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/no-boolean-attr-value

Disallow explicit values for boolean HTML attributes

Bad · Good

Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/no-boolean-attr-value": "warn"
      }
    },
  },
});
vp run lint

Bad

The boolean disabled and checked attributes redundantly contain string values.

<template>
  <input disabled="disabled" />
  <input checked="checked" />
  <button disabled="true">Save</button>
</template>

Good

The presence of each boolean attribute expresses the same enabled state without a value.

<template>
  <input disabled />
  <input checked />
  <button disabled>Save</button>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/no-inline-style

Discourage use of inline style attributes

Bad · Good

Default severity: warning
Presets: nuxt, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/no-inline-style": "warn"
      }
    },
  },
});
vp run lint

Bad

The static style attribute embeds the color declaration in the element.

<template>
  <div style="color: red">Text</div>
</template>

Good

Classes express the fixed color; the ratio-dependent width remains a dynamic style binding, outside the static-attribute check.

<template>
  <div class="text-red">Text</div>
  <span :class="{ 'text-red': isRed }">Text</span>
  <div :style="{ width: `${ratio}%` }">Text</div>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/no-multi-spaces

Disallow multiple consecutive spaces

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/no-multi-spaces": "warn"
      }
    },
  },
});
vp run lint

Bad

Two spaces separate attributes or the element name and the first attribute.

<template>
  <div  class="panel"></div>
  <div class="panel"  id="main"></div>
</template>

Good

Single spaces separate the same attributes.

<template>
  <div class="panel"></div>
  <div class="panel" id="main"></div>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/prefer-props-shorthand

Recommend shorthand syntax for props (Vue 3.4+)

Bad · Good

Default severity: warning
Presets: nuxt, opinionated
Automatic fix: Available for supported findings
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/prefer-props-shorthand": "warn"
      }
    },
  },
});
vp run lint

Bad

Each binding repeats the corresponding variable name, including the camelCase equivalent of a hyphenated argument.

<template>
  <MyComponent :foo="foo" />
  <MyComponent :user-name="userName" />
  <span :style="style" />
  <div :aria-label="ariaLabel" />
</template>

Good

Vue 3.4+ same-name binding shorthand removes the repeated expressions; a different source variable such as bar remains explicit.

<template>
  <MyComponent :foo />
  <MyComponent :user-name />
  <span :style />
  <div :aria-label />
  <MyComponent :foo="bar" />
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/prop-name-casing

Enforce a casing for declared prop names

Bad · Good

Default severity: warning
Presets: happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Checks declared prop names, not the casing of attributes passed to a child.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/prop-name-casing": "warn"
      }
    },
  },
});
vp run lint

Bad

The declared prop name user_name uses underscore-separated spelling.

<script setup lang="ts">
defineProps<{ user_name: string }>();
</script>
<template><p>{{ user_name }}</p></template>

Good

The declaration and its template reference use the camelCase name userName.

<script setup lang="ts">
defineProps<{ userName: string }>();
</script>
<template><p>{{ userName }}</p></template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules

vue/valid-attribute-name

Require valid attribute names

Bad · Good

Default severity: error
Presets: essential, happy-path, nuxt, ecosystem, opinionated
Automatic fix: None; review the suggested change
Applies to: Vue SFC templates and blocks, with script context where the rule requires it
Options: No rule-specific options. Severity and preset selection are configurable.

Bad diagnostic: parser/template

Malformed attribute spelling is diagnosed by parser/template before this defensive rule sees an attribute. Bad therefore reports parser/template; it does not promise a separate vue/valid-attribute-name finding.

Configuration (Vite+)

import { defineConfig } from "@vizejs/vite-plugin/vite-plus";

export default defineConfig({
  lint: {
    vize: {
      "preset": "incremental",
      "rules": {
        "vue/valid-attribute-name": "error"
      }
    },
  },
});
vp run lint

Bad

The quote inside my"attr makes the attribute name malformed. This example produces the parser's parser/template diagnostic rather than promising a separate rule diagnostic.

<template>
<div my"attr="value"></div>
</template>

Good

my-attr is a well-formed attribute name, so the template parser can read the attribute and its value.

<template>
<div my-attr="value"></div>
</template>

Good avoids this rule's finding under the configuration above; other rules may still report diagnostics.

Implementation · All rules