An opinionated Prettier plugin for Laravel Blade templates.
Requires Node.js 18 or newer.
Install Prettier and the plugin in your project:
npm i -D prettier prettier-plugin-blade@^3Optional integrations:
npm i -D @prettier/plugin-php prettier-plugin-tailwindcssChisel v3 (prettier-plugin-blade) is a ground-up rewrite. Expect output changes compared to previous versions.
If you rely on previous versions, you should specify the exact version you'd like to use in your package.json.
Create or update your .prettierrc:
{
"plugins": [
"prettier-plugin-blade"
],
"overrides": [
{
"files": ["*.blade.php"],
"options": {
"parser": "blade"
}
}
]
}Format:
npx prettier --write "resources/views/**/*.blade.php"You can pass Blade plugin options directly to the Prettier CLI as kebab-case flags:
npx prettier "resources/views/**/*.blade.php" \
--write \
--plugin prettier-plugin-blade \
--plugin @prettier/plugin-php \
--parser blade \
--blade-php-formatting safe \
--blade-php-formatting-targets echo \
--blade-php-formatting-targets directiveArgs \
--blade-component-prefixes x \
--blade-component-prefixes flux \
--blade-directive-arg-spacing space \
--blade-echo-spacing tightNotes:
- Use kebab-case in CLI flags (for example
bladePhpFormatting->--blade-php-formatting). - Load
@prettier/plugin-phpwhen usingbladePhpFormatting: "safe"from the CLI. - Array options use repeated flags in CLI (for example:
--blade-inline-intent-elements p --blade-inline-intent-elements svg --blade-inline-intent-elements svg:*). bladeDirectiveCaseMaptakes a JSON object string when passed via CLI, but shell quoting is easy to get wrong. Prefer setting it in.prettierrc.
Use bladeSyntaxPlugins to enable framework-specific or package-specific Blade behavior.
Available plugins:
statamiclog1x/sage-directives: for improved compatibility with https://github.com/Log1x/sage-directives
Example:
{
"plugins": [
"prettier-plugin-blade",
"@prettier/plugin-php"
],
"overrides": [
{
"files": ["*.blade.php"],
"options": {
"parser": "blade",
"bladePhpFormatting": "safe",
"bladeSyntaxPlugins": [
"statamic",
"log1x/sage-directives"
]
}
}
]
}To format embedded PHP fragments inside Blade, install @prettier/plugin-php and include it in plugins:
{
"plugins": [
"prettier-plugin-blade",
"@prettier/plugin-php"
],
"overrides": [
{
"files": ["*.blade.php"],
"options": {
"parser": "blade",
"bladePhpFormatting": "safe"
}
}
]
}Notes:
- Without
@prettier/plugin-php, the formatter still works. It falls back gracefully and leaves PHP fragments unchanged. bladePhpFormattingmodes documented here:"off","safe".
Install the Tailwind CSS plugin and include it in plugins:
{
"plugins": [
"prettier-plugin-blade",
"prettier-plugin-tailwindcss"
],
"overrides": [
{
"files": ["*.blade.php"],
"options": {
"parser": "blade"
}
}
]
}- Install the
Prettier - Code formatterextension (esbenp.prettier-vscode). - Ensure your project has local
devDependenciesfor Prettier and this plugin. - Add workspace settings in
.vscode/settings.json:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.requireConfig": true,
"files.associations": {
"*.blade.php": "blade"
},
"[blade]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}| Option | Type | Default | Values |
|---|---|---|---|
bladePhpFormatting |
choice |
"safe" |
"off", "safe", "aggressive" |
bladePhpFormattingTargets |
string[] |
["directiveArgs", "echo", "phpBlock", "phpTag"] |
echo, directiveArgs, phpBlock, phpTag; use [] (or CLI none) to disable all |
bladeSyntaxPlugins |
string[] |
["statamic"] |
plugin names (for example ["statamic"]) |
bladeDirectiveCase |
choice |
"preserve" |
"preserve", "canonical", "lower" |
bladeDirectiveCaseMap |
string |
"" |
JSON object string, e.g. {"disk":"Disk"} |
bladeDirectiveArgSpacing |
choice |
"space" |
"preserve", "none", "space" |
bladeDirectiveBlockStyle |
choice |
"preserve" |
"preserve", "inline-if-short", "multiline" |
bladeBlankLinesAroundDirectives |
choice |
"preserve" |
"preserve", "always" |
bladeEchoSpacing |
choice |
"preserve" |
"preserve", "space", "tight" |
bladeSlotClosingTag |
choice |
"canonical" |
"canonical", "preserve" |
bladeInlineIntentElements |
string[] |
["p", "svg", "svg:*"] |
elements and namespace wildcards |
bladeComponentPrefixes |
string[] |
["x", "s", "statamic", "flux", "livewire", "native"] |
component prefixes |
bladeInsertOptionalClosingTags |
boolean |
false |
true, false |
bladeKeepHeadAndBodyAtRoot |
boolean |
true |
true, false |
bladePhpFormattingTargets aliases supported in each array entry:
echoes->echodirective-args,directive_args->directiveArgsphp-block,php_block->phpBlockphp-tag,php_tag->phpTag
bladeComponentPrefixes behavior:
- Bare prefix tokens expand to both Blade component separator forms:
x->x-,x:widget->widget-,widget:
- Explicit separator tokens are preserved as-is:
x-matches only dash form tagsx:matches only colon form tags
bladeInlineIntentElements SVG behavior:
svgkeeps single-line<svg>...</svg>container intent when the source is inline.svg:*keeps inline attribute and style intent for SVG namespace elements such as<path>and<line>.- Remove one or both entries to opt out of those SVG-specific inline layouts.
This option controls blank lines between directive branches inside a structured directive block.
Examples of branch separators this option affects:
@if ... @else ... @endif@switch ... @case ... @default ... @endswitch@section ... @endsection
Primary scope:
- It decides how much vertical space to print between one branch and the next branch marker.
- In
preservemode it can also keep some existing blank lines between structured siblings inside a directive body when those blank lines were already present in source.
That means it can affect spacing before @else, @elseif, @endif, @case, @default, @endswitch, and similar closers/openers inside the same directive block.
Supported values:
"preserve"- Keeps an existing blank line between directive branches if one existed in the source.
- Otherwise prints a single newline between branches.
"always"- Always inserts a blank line between directive branches.
- In practice this means two line breaks between branches.
Example input:
@if($x)
<p>a</p>
@else
<p>b</p>
@endifWith bladeBlankLinesAroundDirectives: "preserve":
@if ($x)
<p>a</p>
@else
<p>b</p>
@endifWith bladeBlankLinesAroundDirectives: "always":
@if ($x)
<p>a</p>
@else
<p>b</p>
@endifNotes:
- This option is most visible when directive blocks print in multiline form.
- If a block is kept inline, there are no multiline branch separators for this option to manage.
- In
preservemode, some authored blank lines inside a directive body can also survive between structured siblings when the source already had them.
This plugin also respects standard Prettier options, including:
printWidthtabWidthuseTabssingleQuotesingleAttributePerLinebracketSameLineendOfLinehtmlWhitespaceSensitivity
{
"plugins": [
"prettier-plugin-blade",
"@prettier/plugin-php",
"prettier-plugin-tailwindcss"
],
"overrides": [
{
"files": ["*.blade.php"],
"options": {
"parser": "blade",
"htmlWhitespaceSensitivity": "css",
"bladePhpFormatting": "safe",
"bladePhpFormattingTargets": ["directiveArgs", "echo", "phpBlock", "phpTag"],
"bladeSyntaxPlugins": ["statamic"],
"bladeDirectiveCase": "preserve",
"bladeDirectiveArgSpacing": "space",
"bladeDirectiveBlockStyle": "preserve",
"bladeBlankLinesAroundDirectives": "preserve",
"bladeEchoSpacing": "space",
"bladeSlotClosingTag": "canonical",
"bladeInlineIntentElements": ["p", "svg", "svg:*"],
"bladeComponentPrefixes": ["x", "s", "statamic", "flux", "livewire", "native"],
"bladeInsertOptionalClosingTags": false,
"bladeKeepHeadAndBodyAtRoot": true
}
}
]
}- Confirm
prettier-plugin-tailwindcssis installed. - Confirm it is listed in
plugins. - Confirm class values are static strings (not mixed with Blade interpolation).
- Install
@prettier/plugin-php. - Set
bladePhpFormattingto"safe". - Ensure target is enabled in
bladePhpFormattingTargets.
- Use local project dependencies.
- Set
"prettier.requireConfig": true. - Set
"prettier.prettierPath"when needed.