prettier icon indicating copy to clipboard operation
prettier copied to clipboard

When box-shadow has multiple values (separated by comma) it'd be prettier to put each value on a separate line

Open erusev opened this issue 5 years ago • 14 comments

Prettier 1.16.4 Playground link

--parser css

Input:

box-shadow:
  0px 1px 0 0 #fff,
  0px 2px 0 0 #eee;

Output:

box-shadow: 0px 1px 0 0 #fff, 0px 2px 0 0 #eee;

Expected behavior:

box-shadow:
  0px 1px 0 0 #fff,
  0px 2px 0 0 #eee;

When each value is on a separate line, the whole value feels significantly easier to read.

erusev avatar Apr 02 '19 12:04 erusev

I would love something like this!

IlanVivanco avatar Jan 28 '21 11:01 IlanVivanco

I agree with this. box-shadow with multiple values looks better with each value on a separate line.

How about other properties like background, background-image, text-shadow, @font-face#src?

background-image (from Lea Verou Patterns)

background-image:
  linear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%, black),
  linear-gradient(45deg, black 25%, transparent 25%, transparent 75%, black 75%, black);

text-shadow (from MDN docs)

text-shadow:
  1px 1px 2px red,
  0 0 1em blue,
  0 0 0.2em blue;

font-face (from MDN docs)

@font-face {
  font-family: "Open Sans";
  src:
    url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"),
    url("/fonts/OpenSans-Regular-webfont.woff") format("woff");
}

I would argue that these all look prettier with separate lines when they are separated with commas, particularly when there are more than 2 values.

I think such a rule will need some consideration for which CSS properties are enhanced by splitting across lines and which ones are not. font-family for example, looks worse when split:

font-family

font-family:
  'Helvetica Neue',
  Helvetica,
  system-ui,
  sans-serif;

ricealexander avatar Jan 28 '21 19:01 ricealexander

Could we implement this please as soon as possible. I think it's time to improve this ugly style behavior. It's one of the worst behavior in Prettier.

I prefer always multiline when multiple values.

Bad

box-shadow: 0 0 10px black, 0 0 0 1px black;

Good

box-shadow: 
  0 0 10px black, 
  0 0 0 1px black;

just-do-it

y0nd0 avatar Mar 11 '21 00:03 y0nd0

And variables:

$shadow:
  0 0 0 1px #5b9dd9,
  0 0 2px 1px rgba(30, 140, 190, 0.8);

From: https://github.com/stylelint-scss/stylelint-scss/blob/HEAD/src/rules/dollar-variable-colon-newline-after/README.md

Airkro avatar Jan 08 '22 10:01 Airkro

I have a proof-of-concept PR that implements this here: https://github.com/prettier/prettier/pull/13260. It hard-codes specific properties to always wrap if they have more than one value. (Notably, I skipped font-family since as another commenter pointed out it doesn't look great wrapped.)

sciyoshi avatar Aug 08 '22 21:08 sciyoshi

Note that since it looks at the property, it won't apply to SASS variables.

sciyoshi avatar Aug 08 '22 21:08 sciyoshi

It seems like this might need some more discussion as to the preferred behavior - I've narrowed down the two primary decisions that would need to be made.

1. Always wrap lists

We can choose to always use the new wrapping behavior for lists with two or more elements, or only do it if the line would wrap anyways.

1.a - Always wrapping lists:

.selector {
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.1),
    0 1px 2px 0 rgba(0, 0, 0, 0.2);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.1),
    0 1px 2px 0 rgba(0, 0, 0, 0.2),
    0 1px 2px 0 rgba(0, 0, 0, 0.2);
}

1.b - Only use new wrapping if line needs to wrap:

.selector {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.2);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.1),
    0 1px 2px 0 rgba(0, 0, 0, 0.2),
    0 1px 2px 0 rgba(0, 0, 0, 0.2);
}

2. Only wrap certain properties

Orthogonal from the above, we can choose to apply this new wrapping behavior only for certain properties (like box-shadow, background-image, etc) while keeping the existing behavior for others (notably, font-family, but also transition-property). This makes sense if those properties often have many short elements, but makes the behavior inconsistent and possibly unexpected.

2.a - Only apply new wrapping to certain properties:

.selector {
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.1),
    0 1px 2px 0 rgba(0, 0, 0, 0.2),
    0 1px 2px 0 rgba(0, 0, 0, 0.2);
  font-family: -apple-system, BlinkMacSystemFont,
    avenir next, avenir, segoe ui, helvetica neue, helvetica,
    Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
  transition-property: opacity, color, transform, box-shadow,
    margin, padding;
}

2.b - Apply new wrapping behavior to every property:

.selector {
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.1),
    0 1px 2px 0 rgba(0, 0, 0, 0.2),
    0 1px 2px 0 rgba(0, 0, 0, 0.2);
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    avenir next,
    avenir,
    segoe ui,
    helvetica neue,
    helvetica,
    Cantarell,
    Ubuntu,
    roboto,
    noto,
    arial,
    sans-serif;
  transition-property:
    opacity,
    color,
    transform,
    box-shadow,
    margin,
    padding;
}

sciyoshi avatar Aug 09 '22 16:08 sciyoshi

Personally, I prefer "always".

fisker avatar Aug 09 '22 16:08 fisker

Another thing, where should we put !important?

fisker avatar Aug 09 '22 16:08 fisker

Personally, I prefer "always".

Thanks @fisker - can you clarify here? You mean option 1.a and 2.b?

Another thing, where should we put !important?

Right now (in the PR), it goes on the same line as the last item in the property list.

sciyoshi avatar Aug 09 '22 16:08 sciyoshi

1.a, only personal opinion, we need more discussion.

fisker avatar Aug 11 '22 07:08 fisker

How about "wrap if any list item contains more than 2 spaces"?

thorn0 avatar Aug 16 '22 06:08 thorn0

That could work as well as an alternative for #2 where it doesn't require special-casing the property names.

sciyoshi avatar Aug 16 '22 13:08 sciyoshi

Let's do it (https://github.com/prettier/prettier/issues/6024#issuecomment-1216191051) then, shall we?

thorn0 avatar Aug 29 '22 12:08 thorn0