diff --git a/changelog_unreleased/vue/12895.md b/changelog_unreleased/vue/12895.md
new file mode 100644
index 000000000000..8a4eeaff3d43
--- /dev/null
+++ b/changelog_unreleased/vue/12895.md
@@ -0,0 +1,19 @@
+#### Avoid printing attribute per line in Vue SFC blocks (#12895 by @sosukesuzuki)
+
+
+```vue
+
+
+
+
+
+
+
+
+```
diff --git a/src/language-html/print/tag.js b/src/language-html/print/tag.js
index 7d97ec0fd924..000688983309 100644
--- a/src/language-html/print/tag.js
+++ b/src/language-html/print/tag.js
@@ -17,6 +17,7 @@ const {
isPreLikeNode,
hasPrettierIgnore,
shouldPreserveContent,
+ isVueSfcBlock,
} = require("../utils/index.js");
function printClosingTag(node, options) {
@@ -251,8 +252,11 @@ function printAttributes(path, options, print) {
node.attrs[0].fullName === "src" &&
node.children.length === 0;
- const attributeLine =
- options.singleAttributePerLine && node.attrs.length > 1 ? hardline : line;
+ const shouldPrintAttributePerLine =
+ options.singleAttributePerLine &&
+ node.attrs.length > 1 &&
+ !isVueSfcBlock(node, options);
+ const attributeLine = shouldPrintAttributePerLine ? hardline : line;
/** @type {Doc[]} */
const parts = [
diff --git a/src/language-html/utils/index.js b/src/language-html/utils/index.js
index 00b1e24121e6..4164edc4e4f2 100644
--- a/src/language-html/utils/index.js
+++ b/src/language-html/utils/index.js
@@ -674,6 +674,7 @@ module.exports = {
isVueScriptTag,
isVueSlotAttribute,
isVueSfcBindingsAttribute,
+ isVueSfcBlock,
isDanglingSpaceSensitiveNode,
isIndentationSensitiveNode,
isLeadingSpaceSensitiveNode,
diff --git a/tests/format/vue/single-attribute-per-line/__snapshots__/jsfmt.spec.js.snap b/tests/format/vue/single-attribute-per-line/__snapshots__/jsfmt.spec.js.snap
index 0a2ce5116370..7da8e503a5cf 100644
--- a/tests/format/vue/single-attribute-per-line/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/vue/single-attribute-per-line/__snapshots__/jsfmt.spec.js.snap
@@ -1,5 +1,152 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`sfc-blocks.vue - {"singleAttributePerLine":true} format 1`] = `
+====================================options=====================================
+parsers: ["vue"]
+printWidth: 80
+singleAttributePerLine: true
+ | printWidth
+=====================================input======================================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+=====================================output=====================================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+================================================================================
+`;
+
+exports[`sfc-blocks.vue format 1`] = `
+====================================options=====================================
+parsers: ["vue"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+=====================================output=====================================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+================================================================================
+`;
+
exports[`single-attribute-per-line.vue - {"singleAttributePerLine":true} format 1`] = `
====================================options=====================================
parsers: ["vue"]
diff --git a/tests/format/vue/single-attribute-per-line/sfc-blocks.vue b/tests/format/vue/single-attribute-per-line/sfc-blocks.vue
new file mode 100644
index 000000000000..9118346d54e3
--- /dev/null
+++ b/tests/format/vue/single-attribute-per-line/sfc-blocks.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+