Skip to content

Instantly share code, notes, and snippets.

@keithjgrant
Last active May 12, 2017 17:10
Show Gist options
  • Save keithjgrant/d35fc6a72253c91a60c6c6c15f5ce6ff to your computer and use it in GitHub Desktop.
Save keithjgrant/d35fc6a72253c91a60c6c6c15f5ce6ff to your computer and use it in GitHub Desktop.
My CSS formatting preferences, for discussion on “Prettier for CSS”
/*
I agree w/ the philosophy of Prettier, that as few options as possible should be
provided. However issues that are hot-button (e.g. tabs vs spaces) and would actively
prevent a large number of devs from using the tool should be configurable. The the ones
that jump immediately to mind for me are
1) tabs vs spaces (& number of spaces)
2) line length
3) reordering properties (more on that below)
These are my preferences, but I’m putting everything on the table in the spirit of
compromise and a broadly-usable opinionated tool.
*/
.smaller-stuff {
color: black;
background-color: #c3cba1; /* lowercase hex */
font-size: 0.2em; /* leading zero on decimals */
padding: 0; /* unitless zero for lengths */
margin-left: 0 !important; /* space before !important annotation */
}
.input[type="text"] { /* quoted attribute value, using double-quotes */
font: inherit;
}
.multiple > .selectors,
.each-on-their,
.own-line {
color: blue;
}
.comment-preceding-declaration {
/* comment within a ruleset */
margin-left: -1px;
}
.comment-trailing-declaration {
margin-left: -1px; /* comment at end of line -- or should this move to line above? */
}
/* at rule */
@media screen and (min-width: 30em) {
.example {
color: black;
}
.other-example {
background-color: green;
}
}
/* nested rule and nested at-rule */
.foo {
color: black;
font-size: 1rem;
& > .bar {
font-size: inherit;
}
@media (min-width: 25em) {
font-size: 1.25rem;
}
}
/* spaces around combinators */
.foo > .bar {} /* collapse empty blocks to one line? */
/* double-colon syntax for pseudo-elements */
.foo::before {
content: "";
/* this does break in IE8 -- is that acceptable? Leave it to Auto-prefixer to correct if needed */
}
/* Declaration including function in value */
.short-line-length {
background-image: linear-gradient(to bottom, transparent, black); /* spaces following commas (and no spaces before) */
padding: calc(20vw + 10px); /* spaces on both sides of operator */
}
/* when a declaration exceeds the line length, format to
multi-lines like this: */
.long-line-length {
background-image: linear-gradient(
to bottom,
hsla(200, 100%, 50%, 0.9) 10%, /* I'm flexible on the exact */
hsla(300, 100%, 50%, 0.7) 20%, /* indentation scheme here… */
hsla(100, 100%, 50%, 0.9) 40%, /* something in this ballpark. */
hsla(300, 100%, 50%, 0.5) 80%,
hsla(150, 100%, 50%, 0.3) 85%,
hsla(200, 100%, 50%, 0.9) 100%,
);
text-align: right;
}
/*
An important decision will be whether or not we should actively re-order declarations
by their property names. I really hope we do, but this will certainly have to be a
config option between alphabetical vs. categorically-ordered properties, and an "off" option as well.
This is a "nice to have" in my book. It would probably be lower priority initially (and
more work to implement), but I would hope to have a discussion on the possibility.
That then raises the question of what categorically-ordered means. Personally, I agree with
the "outside in" philosophy here:
https://webdesign.tutsplus.com/articles/outside-in-ordering-css-properties-by-importance--cms-21685
This puts properties in roughly this order:
0 - CSS vars at the top
1 - Layout/positioning (position, float, display, flex, grid)
2 - Box model (width, height, margin, padding)
3 - "visual" stuff (borders, color, background)
4 - typography (font, line-height, letter-spacing)
5 - misc (everything else like transition, transform, cursor, etc)
I believe the vast majority of folks who order categorically tend to do something along these lines.
I'm happy to explicitly draw out the entire list, but as long is things were roughly in this general
order, I'd be happy.
*/
/*
* Below are some other things to consider, though I don't really have
* a strong preference either way.
*/
.hex-color-shorthand {
color: #cc9; /* three character abbreviation when possible? */
}
.aligning-prefixes {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* long at-rule. Egads, this one is a mess. No idea what the right solution is. 😱 */
@media screen
and (min-device-width: 1200px)
and (max-device-width: 1600px)
and (-webkit-min-device-pixel-ratio: 2)
and (min-resolution: 192dpi) {
.well-this-is-awkward {
padding: 2em;
}
}
@benfrain
Copy link

benfrain commented May 12, 2017

OK, here's my take. Rather than list everything again, I'll simply point out where my preferences will differ. Some differences I feel strongly about and others, whilst they are my preference I wouldn't care too much if it went another way:

  • Re-ordering properties — strongly disagree with this in a formatter. Furthermore I have absolutely zero interest in it.
  • spacing either 4 spaces or a single tab (agree this should be one of the few configuration options as very divisive)
  • no leading zeroes (it's just wasteful! ;)):
.this {
    opacity: .3;
}

.not-this {
    opacity: 0.4;
}
  • I would like to see trailing declaration comments removed and placed on the line above.

  • Nested rules — would prefer no space above nest but don't feel strongly enough to argue!

  • I don't like the idea of collapsing empty blocks — feels like we are 'moving the cheese'

  • would prefer single colon over double even though the latter is 'correct' according to specs. Simply for not breaking IE8.

  • changing truncating/expanding values for colors seems a step too far for a formatter

  • aligning prefixes — really don't see any value in that. It promotes a level of authoring 'pinicketyness' (yeah, not a real word, I know) I'm just not happy about. They should just indent like a 'normal' declaration. As an aside, I get pretty upset when I see lists of vendor-prefixes in authoring style sheets anyway; hello Autoprefixer!

.this {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.not-this {
    -webkit-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
}
  • I use nesting in a Sass like syntax to promote a single source of truth for each selector so I would be really happy is any formatter could keep nested seelctors and their comments looking something like this:
.bb-Markets {
    display: none;
    transform: translateY(20px);
    transition: opacity .2s, transform .2s;
    z-index: $zi-medium;
    overflow: hidden;
    border-radius: $radius-small;
    /* Override for when switcher visible */
    [data-bb-switcher-level] & {
        display: block;
        animation: bbShowMarketPanel .2s forwards linear;
    }
    /* When selected by user */
    [aria-selected] & {
        color: $color-green;
    }
    /*Positioning context for our pseudo */
    position: relative;
    &:before {
        content: "";
        position: absolute;
        top: 100%;
        margin-top: -1px;
        background-color: color($color-green-4a a(.6));
        height: 1px;
        left: 0;
        right: 0;
    }
}

@ben-eb
Copy link

ben-eb commented May 12, 2017

I have a feeling that leading zeroes might be contentious so I've created a poll for it: https://twitter.com/ben_eb/status/862994803759382528

@keithjgrant
Copy link
Author

keithjgrant commented May 12, 2017

Some thoughts on empty lines:

Devs tend to use empty lines for all sorts of things: between rulesets (or between only certain rulesets to group them up), between groups of related properties, etc. I think some light cleanup by the formatter might be nice, but we don't want to clobber any intended meaning or groupings implied by the white space.

It looks like Prettier, in JS-land, strips empty lines at the beginning and end of a block (inside the braces), removes empty lines from the beginning of the file, and collapses multiple consecutive empty lines down to one. Otherwise it leaves them as authored. I think that actually sounds like a reasonable approach in CSS, too.

@keithjgrant
Copy link
Author

I’ve begun adding individual issues for discussion under Perfectionist: https://github.com/ben-eb/perfectionist/milestone/1

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