Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom 'void' or self-closing elements (HTML parser changes) #624

Closed
pfrazee opened this issue Jan 30, 2017 · 44 comments
Closed

Custom 'void' or self-closing elements (HTML parser changes) #624

pfrazee opened this issue Jan 30, 2017 · 44 comments

Comments

@pfrazee
Copy link

@pfrazee pfrazee commented Jan 30, 2017

This was discussed in #113

It would be very nice to be able to declare Custom Elements as void or self-closing. Given that element names are already a little lengthy (from the required dash) there are times where avoiding the name repetition would preferable.

Presently, all custom elements must be used as:

<my-element></my-element>

And I'd like to be able to do self-closing:

<my-element />

Or void:

<my-element>

Perhaps by a static getter in the class definition

customElements.define('my-element', class extends HTMLElement {
  static get isVoid() { return true }
})

Any chance we can reopen this discussion?

@rniwa
Copy link
Collaborator

@rniwa rniwa commented Jan 30, 2017

This would require a HTML parser change. We might be able to do this (self-closing) if we restricted to elements with - in its name.

@annevk
Copy link
Contributor

@annevk annevk commented Jan 31, 2017

Nobody wanted to change the HTML parser the last time around. What changed?

@rniwa
Copy link
Collaborator

@rniwa rniwa commented Jan 31, 2017

Well, I didn't want a parser change to be part of v1 since that would have required a lot more compatibility checks. Now that v1 is out the door, I think it might be worth checking whether there is an actual Web compatibility issue or not.

@annevk
Copy link
Contributor

@annevk annevk commented Jan 31, 2017

@rniwa whatwg/html#919 (comment) has pretty good rationale for why we nevertheless probably shouldn't do it.

@pfrazee
Copy link
Author

@pfrazee pfrazee commented Jan 31, 2017

That's a credible reason, so the question is, how much do we care about self-closing tags? Enough to fight that battle?

App devs can work around this using custom templating engines, but that's a shame when you consider that part of the appeal of Custom Elements is getting away from non-native solutions.

@Jamesernator
Copy link

@Jamesernator Jamesernator commented Apr 4, 2017

I would definitely like to see self-closing tags, a good amount of tags I've found useful can be often described from their attributes e.g. <x-markdown src="./some-info.md"></x-markdown> which would be a lot nicer as just <x-markdown src="./some-info.md" />.

@rniwa
Copy link
Collaborator

@rniwa rniwa commented Apr 4, 2017

@annevk I don't agree with @hsivonen assertion that we should not make changes to the parser. There are many things that are security sensitive. In theory, the security of websites can rely on the absence of any Web feature and become vulnerable when any new feature is introduced. But we don't stop introducing new features just because of such a concern. I can be convinced if this turns out a be real security concern, but given the importance of the motivating use cases, I'm not at all convinced we can't make any changes here.

@Jamesernator
Copy link

@Jamesernator Jamesernator commented Apr 5, 2017

@rniwa Yeah I don't think the argument is strong enough to suggest that we should never change the parser ever and stop adding features to html. By the html definition <x-markdown /> should be an error anyway even though browsers recover and wrap following content in it.

It's weird too because the html document even specifies that tags from other namespaces can be self-closing, it just seems weirdly inconsistent. Is there a particular reason every element can't be self-closed?

@annevk
Copy link
Contributor

@annevk annevk commented Apr 5, 2017

@rniwa I still don't see how minor changes here and there to the HTML parser actually accomplishes what folks want, which is custom elements that can take the place of arbitrary HTML elements, such as <li> or <td>. And what it does do is make the HTML parser less reliable and a source of bugs and problems across the ecosystem.

@Jamesernator
Copy link

@Jamesernator Jamesernator commented Apr 5, 2017

@annevk Just speaking for myself but I'm sure others would like it too but I'd certainly find self-closing tags an improvement and assuming only <x-foo /> form is allowed (initially at least) it shouldn't conflict with <p> like behaviours which I feel should be a separate issue given that it's far more complicated.

And from what I'm aware isn't it the case that a correct parser should consider this an error anyway <x-markdown /> (assuming this still applies https://www.w3.org/wiki/Validating_your_HTML#Different_browsers_interpret_invalid_HTML_differently) so correct parsers shouldn't break (just fail) if given <x-markdown />, the thing is the addition of virtually anything to HTML could potentially make the HTML parser a source of bugs, e.g. simply adding another void tag or auto-closing (like <p>) (and plenty of other things I'm sure) would mean existing parsers would be invalid . For those reasons I'm definitely not happy with the argument that we can't extend HTML because some parsers might break.

@annevk
Copy link
Contributor

@annevk annevk commented Apr 6, 2017

@Jamesernator HTML parsers do not fail and that document seems out-of-date at best. The HTML parser we care about is defined at https://html.spec.whatwg.org/multipage/syntax.html#parsing and any change would have to be a change to that algorithm.

@annevk annevk added the v2 label Sep 4, 2017
@annevk annevk changed the title Custom 'void' or self-closing elements Custom 'void' or self-closing elements (HTML parser changes) Feb 18, 2018
@annevk
Copy link
Contributor

@annevk annevk commented Mar 5, 2018

There's no interest in changing the HTML parser for void elements. The bar for changes is too high and the ergonomic benefit is too low.

@annevk annevk closed this Mar 5, 2018
@abitrolly
Copy link

@abitrolly abitrolly commented Apr 30, 2018

Just to clarify - there are these two types of elements:

  1. void - <my-element>
  2. self-closing - <my-element/>

It seems logical that modifying parser to catch new void elements is not good, because nobody knows if custom element should be void or not just by looking at the tag. But what is the problem with self-closing tags?

abitrolly added a commit to abitrolly/metamask-status that referenced this issue Apr 30, 2018
Custom elements can not be self-closing too
WICG/webcomponents#624
@annevk
Copy link
Contributor

@annevk annevk commented Apr 30, 2018

I should have been more clear, my statement applies to self-closing tags too.

@abitrolly
Copy link

@abitrolly abitrolly commented Apr 30, 2018

Then how high would be the bar for changes if we concentrate only on self-closing tags without touching void elements?

@annevk
Copy link
Contributor

@annevk annevk commented Apr 30, 2018

It's still too high. There's basically only interest in security fixes and non-normative changes.

@abitrolly
Copy link

@abitrolly abitrolly commented Apr 30, 2018

So people are doomed to double their simple <custom-element></custom-element> names till the end of internet?

@annevk
Copy link
Contributor

@annevk annevk commented Apr 30, 2018

As far as the text/html format goes that's where we're at.

@amkuipers
Copy link

@amkuipers amkuipers commented May 21, 2018

as a developer using custom elements I would really like self-closing custom elements. It makes no sense to me if I have a <custom-box color='RED' /> , that my browser even stops and ignores the remaining html code. I must specify a separate closing tag for the custom-box before it even works.

  • Developer friendly: allow self-closing custom elements for custom element users

Another motivation is; when someone is using the custom element and that element has no nested content or elements, that developer wants to cleanup its code by changing it to a self closing element. It just looks ugly.

Another motivation is; when the custom element needs a separate closing element, the developer might assume that the custom element accepts content; which it might not.

  • I would vote for the custom element IDE to issue a warning on ignored content for:

<custom-box color="RED">ignored text</custom-box>
<custom-box color="RED"><p>ignored child element with text</p></custom-box>

@thomas-darling
Copy link

@thomas-darling thomas-darling commented May 26, 2019

#624 (comment)
... There's basically only interest in security fixes and non-normative changes.

#624 (comment)
So people are doomed to double their simple <custom-element></custom-element> names till the end of internet?

#624 (comment)
As far as the text/html format goes that's where we're at.

@annevk Sorry, but I simply cannot accept this.

This is a very real problem for those of us who write large web apps, and something that causes quite a bit of daily frustration, wasted time, and bloated code.

The ergonomics of a language matters, and saying we just have to live with it because you do not feel like ever evolving the language in any way, that's just plain unacceptable to me.

Please either provide a valid reason why <foo/>, which as I understand it is currently invalid, can't simply be interpreted as <foo></foo> - or reopen this issue so we can have some actual progress.

@pvh
Copy link

@pvh pvh commented May 27, 2019

Hi @thomas-darling, as a fellow commenter and person also disappointed by the position taken here I just wanted to encourage you to apologize for writing to the project maintainers the way you just did.

The work these people do is difficult and involves trading off a great many factors for an audience of billions. As (I assume) you don't employ anyone else here, you don't have the right to demand work or outcomes from them. If you did work with these people, I hope you'd have the good manners never to speak to your colleagues that way.

Further, this kind of attitude is simply self-defeating. Nobody wants to help a jerk, and treating maintainers this way will only predispose them against your positions.

If you want someone to change their mind, you should try convincing them instead of telling them they're wrong. (One way to convince someone is to have many people politely offer a dissenting opinion, which is what I attempted.)

@pfrazee
Copy link
Author

@pfrazee pfrazee commented May 27, 2019

Let's pause the conversation about etiquette, just to keep the conversation on track.

I would very much like for this issue to be revisited. @annevk who could we lobby to make this change happen? If we had some idea of the WGs or teams to discuss this with, I'm sure there are plenty of people here who'd be interested in making our case to those people.

@annevk
Copy link
Contributor

@annevk annevk commented May 27, 2019

Ultimately, you'd need to convince browsers to change their HTML parser. As I alluded to above, that seems unlikely to happen, but you're welcome to try again.

As an alternative I've been wondering if we should revive "XML5", which would allow for solving this problem, as well as declarative shadow trees. Unfortunately there's not much appetite for that either. At least so far.

@andreasplesch
Copy link

@andreasplesch andreasplesch commented Jun 3, 2019

Let me add the specific example of A-Frame - a large Mozilla effort using custom elements which would benefit quite substantially from self-closing tags since all content is in attributes.

Related, but somewhat off-topic, is the use of Unknown Elements to carry meta-information (<databasefield name='partID' value='xyz' />), or in custom extensions.

@vectorjohn
Copy link

@vectorjohn vectorjohn commented Jun 14, 2019

This may not matter, since it's browser vendors that need convincing, but it really makes no sense not to allow any tag to self close. Its semantically and unambiguously equivalent to spelling out the whole close tag.

Arguments about ergonomics or "writing big apps" aside (they don't convince me, that's just wishy washy), the real reason in my opinion for self closing tags is they communicate intent better than not having them. When making a custom component for which nested content will never make sense, it's a bad idea to have markup that kind of sort of implies that it might do something. It's just another place for errors. A self closing tag means "the child content of this element is meaningless, and should even be considered an error". You need look no further than the humble meta tag. Why would the interface want to imply that it might mean something to write <meta>hello</meta>? I suppose component authors can do runtime checks to validate things like that.

On the other hand, to me it doesn't matter that much either way. It just seems like such a trivially silly thing to have in the html5 spec.

@abitrolly
Copy link

@abitrolly abitrolly commented Jun 14, 2019

@pfrazee
Copy link
Author

@pfrazee pfrazee commented Jun 14, 2019

Don't know about everybody else, but I would gladly take self-closing elements as a solution to this.

@pvh
Copy link

@pvh pvh commented Jun 14, 2019

Absolutely. I was only frustrated by the lack of self-closing custom elements and have no interest in custom void elements.

@rniwa
Copy link
Collaborator

@rniwa rniwa commented Jun 14, 2019

Note that either support self-closing or void elements DO require a parser change. The cost isn't so much about updating the parser but it's that every HTML parser implementation in the world would have to update the parser or else we'd get XSS vulnerability everywhere :( Not saying it's impossible or it's a bad idea but the cost isn't just in the web browser but everything that touches the HTML content in general.

@alshdavid
Copy link

@alshdavid alshdavid commented Jul 4, 2019

I don't care about custom void elements, but custom self closing elements would be incredible.

Imagine

<fa-icon style="solid" type="cross" />
@thomas-darling
Copy link

@thomas-darling thomas-darling commented Jul 4, 2019

@rniwa
Could you, or someone else, please explain how adding support for self-closing elements, i.e. <foo/>, would actually introduce an XSS vulnerability? - preferably with an example.

Maybe I'm missing something, but I don't see a problem here - and I'm probably not alone :-)

@mutech

This comment was marked as off-topic.

@Rob-pw
Copy link

@Rob-pw Rob-pw commented Oct 31, 2020

I understand this isn't feasible, but for whatever reason should it one day be possible in the future.

@dy
Copy link

@dy dy commented Nov 1, 2020

@annevk, W3C:

There's no interest in changing the HTML parser for void (self-closing) elements. The bar for changes is too high and the ergonomic benefit is too low.

Also W3C:

In case of conflict, consider users over authors over implementors over specifiers over theoretical purity.

@rniwa, regarding every HTML parser implementation in the world would have to update - isn't that the case of the HTML design principle above?

@trusktr
Copy link

@trusktr trusktr commented Jan 30, 2021

As I alluded to above, that seems unlikely to happen, but you're welcome to try again.

@annevk Perhaps the issue should be re-opened so we can continue trying.

Can someone link to the XSS vulnerabilities?

Is it possible to have a new space to work in, with new parsing rules without the error-guessing semantics or special tree mangling rules?

<html ></html>

The following would be valid:

<html >
  <script src="foo.js" />
  <div class="single-div-challenge" />
  <gltf-model src="path/to/helmet.gltf" />
</html>

There would be no void elements. Only <foo></foo> and <foo />. But I suppose this means stuff can not appear on screen as soon as possible, because closing tags need to be found. We can make an exception: The closing </html> tag is inserted after the first piece of incorrect markup is removed, and no more markup is loaded, and an error is output to console.

Based on this idea, if we write

<html >
  <script src="foo.js" />
  <div>
    <gltf-model src="path/to/helmet.gltf">
  </div> <!-- error thrown at this point -->
  <img src="..." />
</html>

The result may be the same as the following HTML from today:

<html>
  <script src="foo.js"></script>
  <div> </div>
  <img src="..." />
</html>

If we write

<html >
  <script src="foo.js" />
  <div>
    <div>
    <gltf-model src="path/to/helmet.gltf">
  </div> <!-- error thrown at this point -->
  <img src="..." />
</html> <!-- error thrown at this point -->

The result may be as if we wrote

<html>
  <script src="foo.js"></script>
</html>

The only special mangling rules would be the automatic addition of <body>. Beyond that, all else would be what-you-write-is-what-you-get, or parser would need to abort with an error.

So this,

<html >
  <p><div /></p>
</html>

could either result in an HTMLParagraphElement having an HTMLDivElement child, which is something we can do when we create a tree with imperative JavaScript, or it would throw a parser error (instead of mangling).

Or we update HTMLParagraphElement's implementation so that it actually calls removeChild on any element at runtime (triggering MutationObserver and custom element life cycles) rather than it being parser magic.

If <p><div /></p> would make a parser error and stop the parsing, then

<html >
  <div>
    <p><div /></p>
  </div>
  <img />
</html>

would either be like writing

<html>
</html>

or parsing errors could be localized to the smallest known error area, in which case the last result would instead be

<html>
  <div> </div>
  <img />
</html>

Basically in that last case, after removing/ignoring the bad <p><div /></p> and throwing an error to devtools console, the parser would continue to see if it can continue without the known-bad piece (as if we never wrote it).

Some elements should always be self closing, and the parser should error when they are not.

For Custom Elements, which may be defined later after parsing, maybe there's no enforcement. Or maybe there's a way to map custom element names to booleans indicating if they should be self-closing or not (perhaps like script type=selfclosingtags that is lighter-weight than JS, and actual customElements.define calls can happen later?).


We need self-closing abilities for all elements, and void elements are just a source of ambiguity (elements either have children, or they don't).

Be gone void elements! 👻

The vast majority of libraries and frameworks (every one that I have ever tried) does not accept void elements, and treats them as errors.

JSX is fairly popular (used in React, Preact, Solid.js, Surplus, and a bunch more) and it is an error to write a void tag in JSX.

Vue, Angular, Svelte all throw errors on void elements.

This equates to every major framework disallowing void elements.

Clearly people don't want the ambiguity from void elements.

If ignoring void elements helps to make all tags self-closeable, let's do it.

@Jamesernator
Copy link

@Jamesernator Jamesernator commented Jan 30, 2021

This would require that custom element definitions happen in a script tag before any custom elements are encountered during parsing

Parser blocking on scripts is always fairly expensive, this is why new features (e.g. module scripts) don't allow it, and there's even features in the works specifically to disable the behaviour entirely (e.g. feature policy).

Anything that requires new sync scripts is almost certainly not going to gain any implementer interest.

A warning after the fact might be viable, as browsers could simply set a bit while parsing and then check and warn during upgrade.

@trusktr
Copy link

@trusktr trusktr commented Jan 30, 2021

Good point. I felt iffy writing it; knew someone would mention it.

I believe in my personal cases it would be fine (I would prefer to focus on making a pleasant loading experience with off-main-thread CSS animation). And with a custom-element-heavy applications, the experience may be no good without the JS anyway.

I updated it to replace that part with a shorter simpler idea.

@zamfofex
Copy link

@zamfofex zamfofex commented Jan 30, 2021

@trusktr: Although I don’t think your specific idea is easily feasible (and also, I don’t think preventing elements like <meta>, <link>, <br> from having self‐closing or void tags actually helps with anything at all), I do agree that it makes sense to wish for a fresh new HTML parsing mode that removes certain struggles from authors. Anne’s “XML 5” idea seems like a more sensible approach.

On the other hand, however, I really don’t think it’s actually going to happen any time soon, if ever at all. It seems that implementors are consistently really sceptical of changing parser behavior, mostly because of difficult security analysis that needs to be made on their implementations.

In addition, of course, is the very difficult implied questions of “What about APIs such as .innerHTML?” Should those APIs keep the old parser behavior, or should they reflect the new parser mode? Note that a lot of existing libraries might expect the old parser behavior, and break (perhaps in subtle ways) if it’s different.

There is very little ergonomic benefit in changing the parser now, compared to all the potential problems and questions that arrive from it.

@abitrolly
Copy link

@abitrolly abitrolly commented Feb 7, 2021

And here is the link to HTML design documents and specifically to Priority of Constituencies which is broken by reasons given by @annevk for closing this issue.

https://www.w3.org/TR/html-design-principles/#priority-of-constituencies

3.2. Priority of Constituencies

In case of conflict, consider users over authors over implementors over specifiers over theoretical purity. In other words costs or difficulties to the user should be given more weight than costs to authors; which in turn should be given more weight than costs to implementors; which should be given more weight than costs to authors of the spec itself, which should be given more weight than those proposing changes for theoretical reasons alone. Of course, it is preferred to make things better for multiple constituencies at once.

@zamfofex
Copy link

@zamfofex zamfofex commented Feb 7, 2021

Since this is the second time this same statement has been brought up in this issue, I wanted to mention that no‐one seriously cares about that document, at least not since 2007, when the document was last updated.

It’s not an unreasonable statement, but over time, people have come to realize that it doesn’t actually work well (for the Web, at least). It doesn’t really matter if “authors really want it”, if implementors don’t implement it, either because they can’t or because they don’t want to, the specification becomes moot, as a series of problems arrive.

If the spec is implemented inaccurately in ways that leave discrepancies between it and implementations (in incompatible ways), new implementations won’t want to follow it and risk breaking existing websites. They will prefer to try to copy the behavior of existing implementations, and that opens the opportunity to the implementations themselves to differ. (Which is exactly what the spec is trying to avoid!)

Also note that whatever merit that the aforementioned “Priority of Constituencies” paragraph has is limited to making decisions, not changing them. In this case, the decision of “not allowing either void or self‐closing custom elements” was already made implicitly when custom elements were specified without it. Changing that now has different implications than when it was first specified.

@WaltzingPenguin
Copy link

@WaltzingPenguin WaltzingPenguin commented Apr 20, 2021

Not being able to make custom elements self closing starts to introduce some serious room for error when dealing with slots.

This renders the default content of the slot:
<my-element></my-element>

This renders the slot as empty (replaced with whitespace):
<my-element> </my-element>

The difference between the two is easy to miss and is problematic, especially when distributing components to outside users. <my-element /> would be much clearer.

@rob2d
Copy link

@rob2d rob2d commented Jun 2, 2021

It's mainly a matter of making things idiomatic for humans; Like any code, but especially a declarative templating system, HTML shouldn't be meant to just be written but to be read since it's basically a templating language (obviously there is more into that like reliance on DOM; but the XML semantics weren't just a coincidence/side effect of the functionality).

Been working with building components in a custom Web Component library for the past few months and in terms of interfaces it has been a little bit redundant with this aspect and it's hard to make an interface that is more pleasant as there has to be an extra level of consideration trading off the name specificity of a simple custom element ; with web components you need to repeat everything 2x even if it is a simple or self-contained. Issue is especially obvious with web components when you consider slotted vs not slotted elements, and matters where users might either need to nest content or not.

I can't make pretend personally that it would be painless for browser engines to do this, and I definitely respect the work of these developers, but semantic issues like this in 2021 should probably be a relative priority if web components are at least aiming to make things more idiomatic or succinct /jmho.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet