Skip to content

P2.x - Group HTML classes by prefix instead of forcing onto one line #7863

@pburkindine

Description

@pburkindine

Unfortunately we cannot upgrade to 2.x until the change mentioned here: https://prettier.io/blog/2020/03/21/2.0.0.html#format-value-of-html-class-attribute-7555httpsgithubcomprettierprettierpull7555-by-fiskerhttpsgithubcomfisker

... is parameterized and made optional. This would seriously affect the readability and maintainability of our templates.

The reasoning behind the change given here: #5482 is:

An example of such an attribute is class, where class=" a b c " should be semantically equivalent to class="a b c". However, note that if the user is parsing element.className directly, this change is not safe. 

We do not parse className directly; we do, however, make extensive use of long BEM class names and of bootstrap.

Here's a typical example:


<div class="ProviderMeasuresContainer__heading-row
            d-flex
            flex-column flex-lg-row
            justify-content-start justify-content-lg-between
            align-items-start align-items-lg-center"
...

vs.

<div class="ProviderMeasuresContainer__heading-row d-flex flex-column flex-lg-row justify-content-start justify-content-lg-between align-items-start align-items-lg-center"

You can see this greatly reduces the readability of the element. This leads to longer development and debugging cycles as information in some arbitrary position to the right of the viewing screen is the missing piece on why XYZ is styled incorrectly.

Activity

thorn0

thorn0 commented on Mar 24, 2020

@thorn0
Member

I ask you again. Please use the Playground to report issues.

pburkindine

pburkindine commented on Mar 24, 2020

@pburkindine
Author

Sure, I was able to for this one, still trying on the other:

Prettier 2.0.2
Playground link

--parser html

Input:

<div class="ProviderMeasuresContainer__heading-row
  d-flex
  flex-column flex-lg-row
  justify-content-start justify-content-lg-between
  align-items-start align-items-lg-center">Foo</div>

Output:

<div
  class="ProviderMeasuresContainer__heading-row d-flex flex-column flex-lg-row justify-content-start justify-content-lg-between align-items-start align-items-lg-center"
>
  Foo
</div>

I apologize for being too quick; I am trying to get these things on the books as I find them in the midst of other work but I am happy to try to elaborate.

thorn0

thorn0 commented on Mar 24, 2020

@thorn0
Member

Next time to be even quicker, you can use these buttons on the Playground ;)

image

As for the issue at hand, we definitely won't add an option, but we're going to improve how the class attribute is printed.

added
lang:htmlIssues affecting HTML (and SVG but not JSX)
type:bugIssues identifying ugly output, or a defect in the program
on Mar 24, 2020
pburkindine

pburkindine commented on Mar 24, 2020

@pburkindine
Author

I would really like to lobby for an option in this case? I do understand and appreciate the opinionated philosophy of prettier. In this case, you can see in the HTML provided, the whitespace added is very much intentional grouping that adds value. (This is from my perspective at least the "correct, normal" way of using Bootstrap.)

We would be "okay" with one class per line when it goes past the length limit? But would really like to keep the ability to meaningfully group classes as seen here.

added
status:needs discussionIssues needing discussion and a decision to be made before action can be taken
on Mar 24, 2020
thorn0

thorn0 commented on Mar 24, 2020

@thorn0
Member

Options are out of question. A revert is more probable than an option. We might think of something smarter than one class per line though. Like "try keeping classes with the same prefix on one line".

related discussion: #7555 (comment)

pburkindine

pburkindine commented on Mar 25, 2020

@pburkindine
Author

@thorn0 thanks much for your help here and for getting a PR together so quickly

fisker

fisker commented on Mar 25, 2020

@fisker
Member

How about <!-- prettier-ignore-attribute (class) --> https://prettier.io/docs/en/ignore.html#html

Edit: seems this ignore won't work ?

pburkindine

pburkindine commented on Mar 25, 2020

@pburkindine
Author

@fisker
We would have to do this on every element (would be thousands of ignores) as we use bootstrap extensively

zippoxer

zippoxer commented on Apr 28, 2020

@zippoxer

I think a class per-line would be impractical for Tailwind/TACHYONS projects, and that's important since Tailwind is gaining a lot of popularity right now.

Here's an example right of out Tailwind's documentation (here):

<div class="border-r border-b border-l border-gray-400 lg:border-l-0 lg:border-t lg:border-gray-400 bg-white rounded-b lg:rounded-b-none lg:rounded-r p-4 flex flex-col justify-between leading-normal">

With a class per line, it would look like:

<div
    class="
        border-r
        border-b
        border-l
        border-gray-400
        lg:border-l-0
        lg:border-t
        lg:border-gray-400
        bg-white
        rounded-b
        lg:rounded-b-none
        lg:rounded-r
        p-4
        flex
        flex-col
        justify-between
        leading-normal
    "
>

That's half my screen gone right there, kinda killing the purpose of NoCSS frameworks. (Wait, did I just coin a new term?!)

I think the right way to go would be to break lines only when and where needed to keep the Print Width limit, which could look like:

<div class="border-r border-b border-l border-gray-400 lg:border-l-0
            lg:border-t lg:border-gray-400 bg-white rounded-b lg:rounded-b-none
            lg:rounded-r p-4 flex flex-col justify-between leading-normal"
>

(With a limit of 80 characters per line)

I really like this style much better. I do it manually myself (breaking lines when class is too long) when not using prettier, so I'm a bit biased 😋

thorn0

thorn0 commented on Apr 30, 2020

@thorn0
Member

@zippoxer Please have a look at #7865. What are your thoughts on that?

Prettier pr-7865
Playground link

--parser html

Input:

<div
    class="
        border-r
        border-b
        border-l
        border-gray-400
        lg:border-l-0
        lg:border-t
        lg:border-gray-400
        bg-white
        rounded-b
        lg:rounded-b-none
        lg:rounded-r
        p-4
        flex
        flex-col
        justify-between
        leading-normal
    "
>

Output:

<div
  class="
    border-r border-b border-l border-gray-400
    lg:border-l-0 lg:border-t lg:border-gray-400
    bg-white
    rounded-b
    lg:rounded-b-none lg:rounded-r
    p-4
    flex flex-col
    justify-between
    leading-normal
  "
></div>

28 remaining items

locked as resolved and limited conversation to collaborators on Apr 19, 2021
removed
locked-due-to-inactivityPlease open a new issue and fill out the template instead of commenting.
on Nov 30, 2021
unlocked this conversation on Sep 23, 2022
mightymatth

mightymatth commented on May 4, 2023

@mightymatth

Consider reading this again #10918 (comment) where @Scotchester said:

I agree that this would be a really elegant solution that bridges the gap between the two extremes of one giant line and one line per class, neither of which are appealing to me as a Tailwind user.

Both extremes are bad, and while your decision to move to a one-liner approach in v2.5 eased your life, it made our code drastically harder to read and edit afterward. Moreover, I hate doing PRs processed by Prettier since this change. I really do. Having the possibility to semantically split different groups of classes into separate lines is crucial for readability.
IMO, this one-line hard limitation leads prettier to become uglier. No offense.

Tell me if I need to provide some real examples to prove that.

shaman-apprentice

shaman-apprentice commented on Jan 31, 2024

@shaman-apprentice

Having the possibility to semantically split different groups of classes into separate lines is crucial for readability.

I absolutely agree. I really like prettier, as it keeps code formatted the same and takes away a lot of discussion (thanks for all your great open source contributions!!!). But formatting can also be used for pointing out semantics. For example one class as a hook for third party users, one line for tailwind's class names and one for default theme, which will change with those in next line for dark theme:

<button
  class="
    my-company-component-library-button
    | m-4 p-8 ...
    | bg-color-blue text-color-white ...
    | dark:bg-color-black dark:text-color-yellow ...
  "
>
 ...
</button>

In our team we agree, that using Prettier in combination with tailwind is so hard to read, that we don't want to use it. We have a 50% / 50% discussion about removing Prettier or Tailwind. I find this really frustrating, because Prettier was the promise to me to reduce discussion about formatting. But now we have a discussion about formatting AND usable frameworks.

I would appreciate everything, which enables me to keep above formatting with Prettier.

tbaragao

tbaragao commented on May 2, 2024

@tbaragao

Any solution or workaround for this. I'm using v3.2.5 and still having classes being set to one line.

added theissue type on Mar 3, 2025
removed
type:bugIssues identifying ugly output, or a defect in the program
on Mar 3, 2025
DzmVasileusky

DzmVasileusky commented on Apr 24, 2025

@DzmVasileusky

I am very confused about this issue.
The original intention was to make formatting better for Tailwind users in 2021, and I came here as a Tailwind user to look how to increase readability in 2025.
Because both

<div
    class="
        border-r
        border-b
        border-l
        border-gray-400
        lg:border-l-0
        lg:border-t
        lg:border-gray-400
        bg-white
        rounded-b
        lg:rounded-b-none
        lg:rounded-r
        p-4
        flex
        flex-col
        justify-between
        leading-normal
    "
>

and

<div
    class="border-r border-b border-l border-gray-400 lg:border-l-0 lg:border-t lg:border-gray-400 bg-white rounded-b lg:rounded-b-none lg:rounded-r p-4 flex flex-col justify-between leading-normal"
>

are non-readable.

How about just letting it to respect printWidth and max members count?
It would look like this with printWidth: 80 and max member count - 6

<div
    class="
        border-r border-b border-l border-gray-400 lg:border-l-0 lg:border-t
        lg:border-gray-400 bg-white rounded-b lg:rounded-b-none lg:rounded-r
        p-4 flex flex-col justify-between leading-normal
    "
>

Look how this plugin is working https://www.npmjs.com/package/eslint-plugin-readable-tailwind
It is really doing a great job with one big disadvantage - it is not a prettier plugin but eslint plugin.

It can also be a feature request for the https://github.com/tailwindlabs/prettier-plugin-tailwindcss.
With it we could even group by semantic or place non tailwind classes separately at least.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    lang:htmlIssues affecting HTML (and SVG but not JSX)status:needs discussionIssues needing discussion and a decision to be made before action can be taken

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @ozguruysal@thorn0@fisker@zippoxer@shaman-apprentice

      Issue actions

        P2.x - Group HTML classes by prefix instead of forcing onto one line · Issue #7863 · prettier/prettier