Csswg-drafts: [css-syntax-3]: Voluntary semicolons

Created on 10 Aug 2020  Â·  13Comments  Â·  Source: w3c/csswg-drafts

Allow semicolon to be voluntary after a Declaration when followed by newline or block closing.

let

div {
  background: red
  color: green
}

behave the same as

div {
  background: red;
  color: green;
}

link to the spec section:
https://www.w3.org/TR/css-syntax-3/#typedef-semicolon-token

Related links
https://teamtreehouse.com/community/does-the-semicolon-have-to-be-added-after-each-declaration-in-a-rule-or-is-it-optional (2017)

I can imagine that I am not the first one to raise an issue/proposal on that feature. But I could not find any. Links to issues and sources are welcome.

Closed Rejected as Wontfix by CSSWG Resolution Closed Rejected as Wontfix by Editor Discretion Commenter Not Satisfied css-syntax-3

Most helpful comment

This would be a significant syntax change, and would introduce us to all the wonders and horrors of Javascript's ASI feature. It would make formatting values across multiple lines (useful for larger declarations, like multiple background layers, or the grid-template shorthand) fraught and complicated.

Given that we've dodged the bullet on ASI for several decades so far, I'm very strongly against any attempt to introduce it.

All 13 comments

This would be a significant syntax change, and would introduce us to all the wonders and horrors of Javascript's ASI feature. It would make formatting values across multiple lines (useful for larger declarations, like multiple background layers, or the grid-template shorthand) fraught and complicated.

Given that we've dodged the bullet on ASI for several decades so far, I'm very strongly against any attempt to introduce it.

@timreichen I'm rejecting your proposal, but please let me know if you're okay with that, or if you feel strongly that we should reconsider.

I think we should reconsider because this proposal has multiple aspects to consider:

  • Simplicity
    I was always a fan of simplicity for users. If a parser can figure it out by itself without big impact, then let the parser do it.
  • Native
    In my experience lots of people use transpilers (less, sass, scss, stylus etc.) to basically polyfill featues that lack in css. This is such a case. This along with proposals like nesting will make css more usable natively instead of using a transpiler.
  • for aesthetics
    Code without semicolons look better imo. But since the omission is voluntary, no damage is done to anybody and it gives users more control over their code.
  • More in alignment with javascript
    Since JS allowed the omission for its code, I struck me weird that css requires them. This will make the web standard more aligned to each other.

I agree there has to be a good solution about multiline declarations like grid-template.

grid-template: 
            "a a a" 40px
            "b c c" 40px
            "b c c" 40px / 1fr 1fr 1fr;
color: green;
grid-template: 
            "a a a" 40px
            "b c c" 40px
            "b c c" 40px / 1fr 1fr 1fr
color: green

One option would be analizing the indent if semicolons are omitted.
But ident-token cannot contain : or " by specs so it would be very obvious for a parser what token must be an ident-token and what a Component value without relying on indentation.

What do you think?

@timreichen this is a big request, and I don’t think the benefits you outline come anywhere near close to matching the risks involved in making the change. If you want to write without semicolons you can use the original SASS syntax, but as far as I’m aware the SCSS syntax with semicolons is by far the more popular option. Until/unless that kind of developer preference changes, I don’t think we will consider doing this.

Yup, afaik SCSS syntax is preferred by a strong majority of the Sass userbase. Less also sticks close to standard CSS syntax; Stylus aligns with Sass by using indents and no semicolons.

A noticeable trend here is that CSS preprocessors tend to either stay close to standard CSS syntax, merely adding some useful features, or they go far from CSS syntax and make indentation matter. If indentation is significant, then semicolons are just visual noise, and should be removed.

I like significant-whitespace languages; Python is my primary programming language at the moment, and I wish it had leaned slightly more into whitespace so I didn't have to use so many :s. But I think you have to commit to that. JS is in a worst-of-both-worlds place, where whitespace is slightly significant, allowing semicolons to be omitted most of the time, but you have to always be on watch for the handful of places where it'll screw you up (like putting something on a newline past a return, or starting a line with an array literal, etc). I really don't want CSS to follow along there.

Notably:

I was always a fan of simplicity for users. If a parser can figure it out by itself without big impact, then let the parser do it.

Simplicity is a difficult sword to wield. Being able to write less characters can look simpler, but if it means users have to memorize more rules about how to format their values, it can backfire and actually make the feature more complex to use. "Properties are always separated by semicolons" (current CSS) is a simple rule; "properties are always indented one level in from their selector, and lines with further indentation are just continuing the previous line" (Sass/Stylus) is a simple rule. "Semicolons can be omitted, but be careful about how you linebreak when you spread a property over multiple lines, because whether or not it interprets you correctly depends on some heuristics" is not a simple rule.

Agreed, scss is prefered, but afaik not because it uses semicolons to close declarations but because provided some other reasons (article). Also it tries to stay close to the standard which is css, so kinda of a circular argument for this proposal.
I also agree that css should not go by indentation like sass or stylus to omit semicolons.

About JS

I know what you mean. The return of nothing in js is weird, but I think that is not a problem with semicolons/newlines but the fact that JS doesn't have obligatory return values and interprets a single line return like return undefined.
CSS thankfully doesn't do anything like that.

Simple rule

How about: In a block aident-token is followed by a :. All subsequent tokens are Component value until the next ident-token.

The goal of that would be not to make people memorize any complex rules but: You can write a declaration in a block with or without semicolon at the end. Both are handled the same by the parser.

Note that all the keywords in properties are ident-tokens as well.

But not followed by :, or what keywords are you thinking of?
Just for clarification: I created a simple incomplete regex mockup to demonstrate the rule I described that works the same with and without semicolons.

Besides the discussion as to whether this is desirable, I would be extremely surprised if this was web compatible, For two reasons:

1) As tab mentioned, breaking declaration across multiple lines is a common practice for properties that take long values, and this break up has been done so far without consideration for possible semi-colon insertion. If we started injecting them, it is pretty much certain that the way we inject them would break some of these pages. This might be possible to address with something like your "Simple Rule" in https://github.com/w3c/csswg-drafts/issues/5413#issuecomment-671550148, but there's more:

2) The second reason is similar to https://wiki.csswg.org/faq#error-handling-in-selectors-aka-breaking-pages-by-making-them-work (quoting the relevant part here, tuned to apply to this problem rather than the original one):

> Forgetting a semicolon at the end of a line is an easy mistake to make, so lots of people have made it. Moreover, when a page doesn't quite look the way the author expected, a common strategy is to write more CSS rules until it does, rather than trying to understand why the existing rules do not create the expected result.
> 
> Then, when the page looks good, the author ships it, including all mistaken cruft that doesn't do anything. This dead code might even survive later redesigns.
> 
> Effectively, even though it is not intentional, many pages that have been fixed through additional css declarations now depend on this sort of cruft not to work. More often than not, “randomly“ changing the background, the size, the borders, or the display value of some elements in the page will break it badly. It doesn't matter that the source of the “randomness“ is the author's previous mistakes. Injecting semi-colons would fix the syntax error, but that would break the page.

And so, even if we agree that semi-colon injection is desirable, this is unlikely to be something that can be changed, as it would probably break countless sites.

 Response to 1.

The goal would be the parser to behave the same, with and without semicolons. This is possible with a simple rule as described above.

 Response to 2.

Forgetting a semicolon at the end of a line is an easy mistake to make, so lots of people have made it.

With this proposal, it would not be a mistake anymore. Concerning future css written code, I think it speaks more for this feature than against it.

Moreover, when a page doesn't quite look the way the author expected, a common strategy is to write more CSS rules until it does, rather than trying to understand why the existing rules do not create the expected result.

I see what you mean. But changes on sites would only occur, if the css was invalid with the current specs in the first place. But css is changing all the time. Let's assume somebody wrote a property name in the past that was ignored by the specs at the time and it was implemented as a feature in css afterwards: That also potentially changes/breaks sites.
So I don't agree we should show consideration for invalid css in that manner, else css would not be allowed to implement any new features/properties.

@tabatkins that might be.

div {
  border: 1px solid red
  color: green
}

The rule though is only concerned about where a list of Component values (1px solid red) ends and the next declaration (color) starts. It wouldn't matter if it is a keyword or not.

I see what you mean. But changes on sites would only occur, if the css was invalid with the current specs in the first place. But css is changing all the time.

"The CSS was invalid in the first place" is not a reason to break things. We don't have a moral right to bust older code just because it was wrong; it's written already, it's published, people are viewing pages with it, and if we change things around it, those pages might break.

We do occasionally make things that were previously invalid become valid; technically any addition to the language is doing that. Generally we believe there's a good chance we aren't affecting anyone (or at least, affecting a negligible number) by doing so; when, rarely, we believe there might be some decent impact, we try to measure it before we make the change.

This change is almost certain to have an impact on pages. It's not limited to a single property we're changing, or a single type of value. Leaving off a semicolon between declarations (thus ignoring both of them due to invalid syntax) can happen anywhere, to any property, and it's a common enough mistake that I know I've made it several times.

This doesn't necessarily mean we couldn't do it! We could carefully run searches over a corpus of public code, and probably instrument a browser's CSS parser to see how often it's encountered in the real world. However, to justify that effort, we'd have to have some pretty substantial benefit; that testing is expensive in terms of engineer time in the first place, and it's likely to show us some decent amount of accidental "usage" of the current parser's behavior, so we need something compelling enough that we can make a decent argument for making the change despite the breakage we observe (assuming it's a small enough amount, which we're not sure of).

This change does not do that, in my opinion. The sole benefit is that authors get to omit a single character from the end of their declarations. The downside is that if we ever have property syntax that contains an ident followed by a :, we'd need to engineer around this parsing behavior, and authors would have to be very careful about it as well. (And that is potentially valid syntax in a custom property with "*" grammar, which can take any value at all!) It still doesn't let authors actually just rely on indentation in their stylesheets, since they still need to wrap the declarations in {} (and that change is genuinely impossible in a backwards-compatible way, since Selectors grammar already allows "ident followed by colon" as a common thing).

The CSS Working Group just discussed [css-syntax-3]: Voluntary semicolons, and agreed to the following:

  • RESOLVED: Reject proposal, no change to semicolons

The full IRC log of that discussion
<dael> Topic: [css-syntax-3]: Voluntary semicolons

<dael> github: https://github.com/w3c/csswg-drafts/issues/5413

<dael> TabAtkins: I rejected but b/c syntax status we need wg approval. Commentor suggested we allow ; after declarations to be voluntary

<dael> TabAtkins: Producing something like JS automatic ; injection

<dael> TabAtkins: Rejected, I don't think it's good in JS and don't want to spread. Good indentation design is fine, but having this maybe and maybe not is bad

<dael> TabAtkins: Seeking WG approval to reject and we're not adding ; optional

<dael> Rossen_: I believe in the issue comments there's agreement from group members

<astearns> +1 to reject

<hober> +1

<miriam> +1

<dael> TabAtkins: Yeah. florian and astearns commented in issue saying not to add

<jfkthame> +1

<fantasai> +1

<dauwhe_> +1

<dael> Rossen_: Any objections to Reject proposal, no change to semicolons

<dael> RESOLVED: Reject proposal, no change to semicolons

Was this page helpful?
0 / 5 - 0 ratings