diff --git a/docs/rules/single-attribute-single-line.md b/docs/rules/single-attribute-single-line.md
new file mode 100644
index 000000000..eec091980
--- /dev/null
+++ b/docs/rules/single-attribute-single-line.md
@@ -0,0 +1,67 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/single-attribute-single-line
+description: enforce component opening tags with a single attribute to be on a single line
+since: v7.5.0
+---
+# vue/single-attribute-single-line
+
+> enforce component opening tags with a single attribute to be on a single line
+
+- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
+
+Ensures that component opening tags that only have one attribute are inline to improve readability.
+
+## :book: Rule Details
+
+This rule aims to enforce component opening tags with a single attribute to be place on a single line.
+It checks all the elements in a template and verifies that when the number of attributes for a component is 1, that it is inlined on the opening tag.
+
+
+
+```vue
+
+
+
+
+
+
+ content
+
+
+
+
+
+
+ content
+
+
+```
+
+
+
+## :wrench: Options
+
+```json
+{
+ "vue/single-attribute-single-line": ["error"]
+}
+```
+
+
+
+## :rocket: Version
+
+This rule was introduced in eslint-plugin-vue v7.5.0
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/single-attribute-single-line.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/single-attribute-single-line.js)
diff --git a/lib/rules/single-attribute-single-line.js b/lib/rules/single-attribute-single-line.js
new file mode 100644
index 000000000..dcffe006d
--- /dev/null
+++ b/lib/rules/single-attribute-single-line.js
@@ -0,0 +1,78 @@
+/**
+ * @fileoverview Enforce component opening tags with a single attribute to be on a single line
+ * @author Jackson Gross
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+const utils = require('../utils')
+
+module.exports = {
+ meta: {
+ type: 'layout',
+ docs: {
+ description:
+ 'enforce component opening tags with a single attribute to be on a single line',
+ categories: undefined,
+ url: 'https://eslint.vuejs.org/rules/single-attribute-single-line.html'
+ },
+ fixable: 'whitespace', // or "code" or "whitespace"
+ schema: []
+ },
+ /** @param {RuleContext} context */
+ create(context) {
+ const sourceCode = context.getSourceCode()
+ const template =
+ context.parserServices.getTemplateBodyTokenStore &&
+ context.parserServices.getTemplateBodyTokenStore()
+
+ return utils.defineTemplateBodyVisitor(context, {
+ VStartTag(node) {
+ const closingTag = node.range[1] - 1
+ const numberOfAttributes = node.attributes.length
+
+ if (numberOfAttributes !== 1) return
+
+ if (!utils.isSingleLine(node)) {
+ // Find the closest token before the current prop
+ // that is not a white space
+ const prevToken = /** @type {Token} */ (template.getTokenBefore(
+ node.attributes[0],
+ {
+ filter: (token) => token.type !== 'HTMLWhitespace'
+ }
+ ))
+
+ const startOfAttribute = node.attributes[0].range[0]
+ const endOfAttribute = node.attributes[0].range[1]
+
+ /** @type {Range} */
+ const rangeBetweenAttributeAndStartTag = [
+ prevToken.range[1],
+ startOfAttribute
+ ]
+
+ /** @type {Range} */
+ const rangeBetweenAttributeAndClosingTag = [
+ endOfAttribute,
+ closingTag
+ ]
+
+ context.report({
+ node,
+ message: "'{{name}}' should be on a single line.",
+ data: { name: sourceCode.getText(node.attributes[0].key) },
+ fix(fixer) {
+ return [
+ fixer.replaceTextRange(rangeBetweenAttributeAndClosingTag, ''),
+ fixer.replaceTextRange(rangeBetweenAttributeAndStartTag, ' ')
+ ]
+ }
+ })
+ }
+ }
+ })
+ }
+}
diff --git a/tests/lib/rules/single-attribute-single-line.js b/tests/lib/rules/single-attribute-single-line.js
new file mode 100644
index 000000000..f9bb56d8c
--- /dev/null
+++ b/tests/lib/rules/single-attribute-single-line.js
@@ -0,0 +1,155 @@
+/**
+ * @fileoverview Enforce component opening tags with a single attribute to be on a single line
+ * @author Jackson Gross
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const RuleTester = require('eslint').RuleTester
+const rule = require('../../../lib/rules/single-attribute-single-line')
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester({
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: { ecmaVersion: 2015 }
+})
+
+ruleTester.run('single-attribute-single-line', rule, {
+ valid: [
+ {
+ code: ``
+ },
+ {
+ code: ``
+ },
+ {
+ code: `
+
+ `
+ },
+ {
+ code: `
+
+ `
+ },
+ {
+ code: ``
+ },
+ {
+ code: ``
+ },
+ {
+ code: `
+
+ `
+ },
+ {
+ code: `
+
+ `
+ },
+ {
+ code: `
+
+ Some content
+
+ `
+ },
+ {
+ code: `
+
+ Some content
+
+ `
+ }
+ ],
+
+ invalid: [
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: ["'name' should be on a single line."]
+ },
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: ["':name' should be on a single line."]
+ },
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: ["'v-bind' should be on a single line."]
+ },
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: ["'@buy' should be on a single line."]
+ },
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: ["'@click.stop' should be on a single line."]
+ },
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: ["'v-if' should be on a single line."]
+ },
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: ["'v-bind:name' should be on a single line."]
+ }
+ ]
+})