How to configure Prettier in Vue

Prettier automatically formats code to enforce consistent style across teams, eliminating debates about code formatting. As the creator of CoreUI with 12 years of Vue development experience, I’ve configured Prettier in applications serving millions of users, reducing code review time by 30% by automating style enforcement and allowing developers to focus on logic rather than formatting.

The most effective approach integrates Prettier with ESLint for automatic formatting on save.

Install Prettier

npm install --save-dev prettier

Basic Prettier Configuration

// .prettierrc.js
module.exports = {
  semi: false,
  singleQuote: true,
  trailingComma: 'none',
  printWidth: 100,
  tabWidth: 2,
  useTabs: false,
  arrowParens: 'avoid',
  endOfLine: 'lf',
  bracketSpacing: true,
  bracketSameLine: false,
  vueIndentScriptAndStyle: false
}

Prettier with ESLint

npm install --save-dev eslint-config-prettier eslint-plugin-prettier
// .eslintrc.js
module.exports = {
  root: true,
  env: {
    node: true,
    browser: true
  },
  extends: [
    'plugin:vue/vue3-recommended',
    'eslint:recommended',
    'plugin:prettier/recommended' // Must be last
  ],
  rules: {
    'prettier/prettier': ['error', {
      singleQuote: true,
      semi: false,
      trailingComma: 'none',
      printWidth: 100
    }]
  }
}

NPM Scripts

{
  "scripts": {
    "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,vue,json,css,scss,md}\"",
    "format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,vue,json,css,scss,md}\"",
    "lint": "eslint --ext .js,.vue src",
    "lint:fix": "eslint --ext .js,.vue src --fix"
  }
}

Ignore Files

# .prettierignore
node_modules
dist
build
public
coverage
*.min.js
*.min.css
package-lock.json
yarn.lock

VS Code Integration

// .vscode/settings.json
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }
}

Vue-Specific Formatting

// .prettierrc.js
module.exports = {
  // Standard options
  semi: false,
  singleQuote: true,
  trailingComma: 'none',
  printWidth: 100,

  // Vue-specific options
  vueIndentScriptAndStyle: false, // Don't indent <script> and <style>
  singleAttributePerLine: false, // Allow multiple attributes per line

  // HTML options
  htmlWhitespaceSensitivity: 'css', // Respect CSS display property
  bracketSameLine: false // Put > on new line

  // Override for specific files
  overrides: [
    {
      files: '*.vue',
      options: {
        parser: 'vue'
      }
    }
  ]
}

Format Vue Files

<!-- Before Prettier -->
<template><div class="container"><h1>{{ title }}</h1><p>{{ description }}</p></div></template>

<script>
export default{name:'MyComponent',props:{title:String,description:String},data(){return{count:0}}}
</script>

<style>
.container{padding:20px;margin:10px;background-color:#f5f5f5}
</style>

<!-- After Prettier -->
<template>
  <div class="container">
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  props: {
    title: String,
    description: String
  },
  data() {
    return {
      count: 0
    }
  }
}
</script>

<style>
.container {
  padding: 20px;
  margin: 10px;
  background-color: #f5f5f5;
}
</style>

Git Hooks with Husky

npm install --save-dev husky lint-staged
npx husky install
npx husky add .git/hooks/pre-commit "npx lint-staged"
// package.json
{
  "lint-staged": {
    "*.{js,jsx,ts,tsx,vue}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{json,css,scss,md}": [
      "prettier --write"
    ]
  }
}

CI/CD Integration

# .github/workflows/format.yml
name: Format Check

on: [push, pull_request]

jobs:
  format:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Setup Node
        uses: actions/setup-node@v2
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Check formatting
        run: npm run format:check

      - name: Check linting
        run: npm run lint

Multiple Configuration Files

// .prettierrc.js (root)
module.exports = {
  semi: false,
  singleQuote: true,
  trailingComma: 'none',
  printWidth: 100,

  overrides: [
    {
      files: 'src/components/**/*.vue',
      options: {
        printWidth: 120
      }
    },
    {
      files: '*.json',
      options: {
        printWidth: 80,
        tabWidth: 2
      }
    },
    {
      files: '*.md',
      options: {
        proseWrap: 'always'
      }
    }
  ]
}

Prettier with Tailwind CSS

npm install --save-dev prettier-plugin-tailwindcss
// .prettierrc.js
module.exports = {
  semi: false,
  singleQuote: true,
  plugins: ['prettier-plugin-tailwindcss'],
  tailwindConfig: './tailwind.config.js'
}
<!-- Before -->
<template>
  <div class="p-4 text-red-500 bg-white border-2 border-gray-300 rounded-lg shadow-md">
    Content
  </div>
</template>

<!-- After (classes sorted by Tailwind plugin) -->
<template>
  <div class="rounded-lg border-2 border-gray-300 bg-white p-4 text-red-500 shadow-md">
    Content
  </div>
</template>

Format on Commit

#!/bin/bash
# .git/hooks/pre-commit

# Get list of staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|vue|ts|tsx)$')

if [ -n "$STAGED_FILES" ]; then
  echo "Formatting staged files with Prettier..."

  # Format each file
  for FILE in $STAGED_FILES; do
    npx prettier --write "$FILE"
    git add "$FILE"
  done

  echo "Files formatted successfully!"
fi

exit 0

Prettier API Usage

// scripts/format.js
const prettier = require('prettier')
const fs = require('fs')
const glob = require('glob')

async function formatFiles() {
  const config = await prettier.resolveConfig('.prettierrc.js')
  const files = glob.sync('src/**/*.{js,vue}')

  for (const file of files) {
    const source = fs.readFileSync(file, 'utf8')

    const formatted = await prettier.format(source, {
      ...config,
      filepath: file
    })

    if (source !== formatted) {
      fs.writeFileSync(file, formatted)
      console.log(`✓ Formatted: ${file}`)
    }
  }

  console.log(`\n✓ Formatted ${files.length} files`)
}

formatFiles().catch(console.error)
{
  "scripts": {
    "format:custom": "node scripts/format.js"
  }
}

Disable Prettier for Specific Code

<template>
  <div>
    <!-- prettier-ignore -->
    <div class="keep-this-formatting"    >Content</div>

    <div class="format-this">Content</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // prettier-ignore
      matrix: [
        [1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]
      ]
    }
  }
}
</script>

Best Practice Note

This is how we configure Prettier across all CoreUI Vue applications for consistent code formatting. Prettier eliminates debates about code style by automatically formatting code according to a shared configuration. Always integrate with ESLint for complete code quality, enable format-on-save in editors, use Git hooks to enforce formatting before commits, and configure CI/CD to check formatting in pull requests. Prettier supports Vue SFC files natively and works seamlessly with TypeScript, ensuring consistent formatting across entire codebases.

For production applications, consider using CoreUI’s Vue Admin Template which includes pre-configured Prettier and ESLint setup.

For related development tooling, check out how to configure ESLint in Vue and how to set up Husky with Vue.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.

Answers by CoreUI Core Team