prettier icon indicating copy to clipboard operation
prettier copied to clipboard

HTML: Avoid linebreaks inside end tags

Open lydell opened this issue 5 years ago • 11 comments

Due to the unfortunate whitespace rules of HTML, Prettier has to do some clever tricks to be able to safely format HTML as good as it can while not introducing unwanted spacing in the rendered output of the HTML.

Here’s a tweak we can do: Many times we don’t gain anything by putting a line break inside an end tag. For example:

<div id="update-available">
  Myapp has a new version.
  <a href="#" onClick="window.location.reload(true);return false;"
    >Click to reload</a
  >
</div>

That would be much nicer formatted as:

<div id="update-available">
  Myapp has a new version.
  <a href="#" onClick="window.location.reload(true);return false;"
    >Click to reload</a>
</div>

But it is unfortunately not as easy as just never putting a linebreak inside end tags, because sometimes that’s the only way to be able to break long lines:

<div id="update-available">
  Myapp has a new version.
  <a href="#" onClick="reload()"
    ><strong
      >Click to reload and get the latest and greatest version!</strong
    ></a
  ><span data-icon="star"></span>
</div>

If we were to never break inside end tags, it would look like this:

<div id="update-available">
  Myapp has a new version.
  <a href="#" onClick="reload()"
    ><strong
      >Click to reload and get the latest and greatest version!</strong></a><span data-icon="star"></span>
</div>

That line is getting very long.

So my proposal is:

If an end tag is followed by whitespace, don’t break inside the end tag.


An alternative rule would be:

Only break inside end tags if immediately followed by another tag or a comment.

For example, this:

<p id="v1">
  That was done using
  <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"
    >MutationObserver</a
  >s and other cool DOM APIs such as
  <a href="TODO-link">IntersectionObserver</a>s. Cool, huh?
</p>

<p id="v2">
  That was done using
  <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"
    >MutationObserver</a
  >s and other cool DOM APIs such as
  <a
    href="https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver"
    >IntersectionObserver</a
  >s. Cool, huh?
</p>

…could be formatted as:

<p id="v1">
  That was done using
  <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"
    >MutationObserver</a>s and other cool DOM APIs such as
  <a href="TODO-link">IntersectionObserver</a>s. Cool, huh?
</p>

<p id="v2">
  That was done using
  <a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver"
    >MutationObserver</a>s and other cool DOM APIs such as
  <a
    href="https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver"
    >IntersectionObserver</a>s. Cool, huh?
</p>

lydell avatar May 13 '20 19:05 lydell

I noticed some surprising formatting today:

<pre>
a
b</pre>

Becomes:

<pre>
a
b</pre
>

Playground


I can't tell if that's within the scope of this issue. The outcome is a linebreak inside of an end tag, but the surprising part isn't where the linebreak is, it's that Prettier is trying to break up that line at all (since it's way under the print width). 

Let me know if I should file a separate issue.

mkantor avatar Sep 05 '20 20:09 mkantor

Just jump into this issue.

@thorn0 Can we just put the leading > to the line above? It looks much better.

From:

<span class="word"
  ><span class="syllable"
    ><span class="letter vowel">i</span
    ><span class="letter consonant">p</span></span
  ><span class="syllable"
    ><span class="letter consonant onset">s</span
    ><span class="letter vowel">u</span
    ><span class="letter consonant">m</span></span
  ></span
>

To:

<span class="word">
  <span class="syllable">
    <span class="letter vowel">i</span>
    <span class="letter consonant">p</span>
  </span>
  <span class="syllable">
    <span class="letter consonant onset">s</span>
    <span class="letter vowel">u</span>
    <span class="letter consonant">m</span>
  </span>
</span>

max-hk avatar Aug 12 '21 14:08 max-hk

@maxloh It sounds like you’re looking for the HTML Whitespace Sensitivity option. That’s not what this issue is about.

lydell avatar Aug 12 '21 16:08 lydell

This fixed it for me (in .prettierrc or wherever you manage your prettier settings):

  "htmlWhitespaceSensitivity": "ignore"

Docs: https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting

davidbielik avatar Dec 23 '21 19:12 davidbielik

I think the following is related to this bug. Would someone kindly confirm?

Before Prettier:

    <form action="" method="post"><label for="">First Name</label><input type="text" name="firstName" id="" value=""><button type="submit">Submit</button></form>

After Prettier:

    <form action="" method="post">
      <label for="">First Name</label
      ><input type="text" name="firstName" id="" value="" /><button
        type="submit"
      >
        Submit
      </button>
    </form>

Ideal formatting (or, at the very least, not inserting new lines in the middle of tags):

    <form action="" method="post">
      <label for="">First Name</label>
      <input type="text" name="firstName" id="" value="" />
      <button type="submit">Submit</button>
    </form>

superclarkk avatar Nov 07 '22 12:11 superclarkk

100% agree on the author above. This looks so much better (non-prettier):

    <form action="" method="post">
      <label for="">First Name</label>
      <input type="text" name="firstName" id="" value="" />
      <button type="submit">Submit</button>
    </form>

Rather than this («prettier»):

    <form action="" method="post">
      <label for="">First Name</label
      ><input type="text" name="firstName" id="" value="" /><button
        type="submit"
      >
        Submit
      </button>
    </form>

I'm having exact same problem.

UPD. "htmlWhitespaceSensitivity": "ignore" seems to be enough in my case

jerrygreen avatar Dec 28 '22 01:12 jerrygreen

I dont get it .. so many people find this ugly and there is no solution for 3 years?

i suggest there will be configuration parameter allowLineBreaksAtEndTags: true|false and if it is set to true, it will not allow end tag to have new space, but instead it place the end tag as whole on new line

scholtz avatar Dec 25 '23 19:12 scholtz