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 Elements]: Custom elements should be display: block by default #224

Closed
hayatoito opened this issue Jul 6, 2015 · 39 comments
Closed

Comments

@hayatoito
Copy link
Contributor

Title: [Custom Elements]: Custom elements should be display: block by default (bugzilla: 24876)

Migrated from: https://www.w3.org/Bugs/Public/show_bug.cgi?id=24876


comment: 0
comment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=24876#c0
Elliott Sprehn wrote on 2014-03-01 08:38:13 +0000.

Almost every custom element I've seen so far has:

<style> :host { display: block } </style>

inside the ShadowRoot, or a rule in the owning page that makes it into display: block since the default of display: inline for unknown elements is really never want you want. I've also seen lots of authors stumble trying to figure out why their custom elements look busted when they first start before they realize they all need this rule.

I think we should consider add some kind of pseudo like :custom and then say the UA sheet has :custom { display: block } to make this simpler.


comment: 1
comment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=24876#c1
Boris Zbarsky wrote on 2014-03-01 20:15:58 +0000.

Custom form controls presumably wouldn't be display:block...


comment: 2
comment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=24876#c2
Elliott Sprehn wrote on 2014-03-03 21:35:39 +0000.

(In reply to Boris Zbarsky from comment #1)

Custom form controls presumably wouldn't be display:block...

Indeed, they probably want to be display: inline-block. What I've observed is that in many modern applications custom elements are placed inside flex boxes so display: block is fine since they end up flexed anyway (if they were inline they end up inside anonymous blocks instead).


comment: 3
comment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=24876#c3
Boris Zbarsky wrote on 2014-03-03 22:15:19 +0000.

Inlines in a flex container don't create anonymous blocks; they just end up with a computed display of "block". The only anonymous anything that happens with flexbox is that text that's a direct child of a flexbox is wrapped in an anonymous flex item.

@rniwa
Copy link
Collaborator

rniwa commented Mar 1, 2016

I don't think we should change the default display type (i.e. we should use display: inline by default). Regardless, we need to make a decision for v1.

@travisleithead @annevk

@rniwa rniwa added the v1 label Mar 1, 2016
@annevk
Copy link
Collaborator

annevk commented Mar 1, 2016

I tend to agree. Paging @esprehn.

@annevk annevk changed the title [Custom Elements]: Custom elements should be display: block by default (bugzilla: 24876) [Custom Elements]: Custom elements should be display: block by default Mar 1, 2016
@domenic
Copy link
Collaborator

domenic commented Mar 7, 2016

I've asked for developers to comment on this thread with their experiences in the hopes that we can meet their needs better. I agree that leaving it display: inline would be simpler and nicer from a spec and implementer point of view, but it seems like we should try to listen to developers on this.

@justinfagnani
Copy link
Contributor

I'm with @esprehn, nearly every element I've ever authored has :host { display: block }. I've made maybe one or two inline custom elements ever.

@silenceisgolden
Copy link

Pardon my ignorance, but does this spec cover the ability to extend elements that are already registered? I would think that it would be block by default unless it extends an element that has a default of inline.

@Robdel12
Copy link

Robdel12 commented Mar 7, 2016

I think I'd rather have then act as display: block rather than inline. It's usually a special case for me to change a component/custom element to inline and even then its inline-block.

@rniwa
Copy link
Collaborator

rniwa commented Mar 7, 2016

The problem here is that it would mean we have to do either:

  1. display value changes when an unresolved custom element becomes upgraded
  2. We change display value for all existing unknown elements with - in its name

I don't think we can do 2 due to backwards compatibility and 1 is very confusing for authors. For starters, authors have to have display: block for :unresolved pseudo class or would see FOC. If they had already specified display: block, then it would be mysterious that display: block is not needed for the actual custom elements.

@domenic
Copy link
Collaborator

domenic commented Mar 8, 2016

Hmm, that is a pretty good argument. Just to clarify for everyone:

  1. means that <x-foo> goes from display: inline to display:block when you register x-foo.
  2. means that <x-foo> is always display: block, even if you never register x-foo.

I agree that (2) is backward incompatible and (1) is pretty horrible. I can't see any way to make this work.

Maybe the best solution we can offer authors is some kind of selector like :potentiallycustom that matches any tag name with - in it, so they can add a one-line :potentiallycustom { display: block; } to their stylesheets. (This is different from :unresolved since it would still work after upgrading.)

@bkardell
Copy link

bkardell commented Mar 8, 2016

oh yeah, +1 for a pseudo, I made this case several years ago now :dashedTag or something would be super useful/fairly straightforward I think. fwiw, at my company we use a custom import mechanism and that puts all of the in visibility: hidden until they are upgraded - this way they reserve space but don't draw some potential horribleness... seems p good.

@robdodson
Copy link

Yeah being able to just do this once would be much nicer than having to auto-include it in all of my hosts

@JanMiksovsky
Copy link

Wouldn't a global rule like :potentiallycustom { display: block; } mean that elements that want to be display: inline-block will still cause FOUC? Same thing for elements that want to be flex, etc. If you're using custom elements from mixture of sources, there's no way to anticipate the display setting desired by each element. We agree that display: block is very common, but it's not universal.

FWIW, in practice nearly every element we create includes a shadow tree, so to prevent FOUC we end up needing to hide unresolved elements anyway. So point #1 hasn't been an issue for us. By the time the element is visible, it's applied its desired display setting.

@bedeoverend
Copy link

We are in the same scenario as @robdodson, but agree with @JanMiksovsky. As an element author it doesn't make sense to use the pseudo selector as it will affect all custom elements, even those written by other authors that potentially want a different default display.

@robdodson
Copy link

By the time the element is visible, it's applied its desired display setting.

If this is the case then wouldn't that give those inline-block and flex elements a chance to override the pseudo selector?

@rniwa
Copy link
Collaborator

rniwa commented Mar 8, 2016

By the time the element is visible, it's applied its desired display setting.
If this is the case then wouldn't that give those inline-block and flex elements a chance to override the pseudo selector?

Well, we're talking about the unresolved/yet-to-be-upgraded elements having a wrong display value here. That is, until the elements get resolved, they would have a wrong display value and may end up in undesirable FOC / bad layout.

@justinfagnani
Copy link
Contributor

it's not just display though, from pre to post upgrade all kinds of things will change - shadow root contents, distribution, and all other style properties. Controlling FOUC will require care in any case, and for styles will involve applying styles to unresovled elements. display: block should reduce, though not eliminate, one of the more potentially jarring sources of FOUC, given that most elements want block.

@justinfagnani
Copy link
Contributor

I missed @rniwa's comment from 3 hours prior. Agree both options sound bad.

@esprehn
Copy link

esprehn commented Mar 8, 2016

I don't think a pseudo makes sense, there's no way to express it across shadow boundaries like you can UA sheets, which means authors copy and paste the rule into each shadow.

It also doesn't really make sense to me to do this globally like that. If the default is inline, but some elements are block, you'd not want to do :custom-element { display: block; }, since you'd break elements which intend to be inline, or cause strange loading behavior.

I think having registerElement make it become block is fine, you should already be managing FOUC using :unresolved.

@rniwa
Copy link
Collaborator

rniwa commented Mar 8, 2016

I think having registerElement make it become block is fine, you should already be managing FOUC using :unresolved.

I don't think that's okay at all. It misleads author to think display: block is always set on custom elements, and it would be rather surprising that it's not when the element had not been upgraded. We don't need any more magical inconsistent behaviors like that on the Web.

@esprehn
Copy link

esprehn commented Mar 8, 2016

I don't think that's any more surprising than today where authors don't realize they're inline by default and end up with collapsed or overflowing inlines all over. I frequently end up answering questions about why an element that contains divs has "strange behavior", it's almost always because they forgot display: block.

Note that much worse things will happen to an unresolved element, ex. it won't have borders, it won't have box-sizing: border-box, it won't style/place its children correctly if used Shadow DOM, and more. Authors should use :unresolved (and they already do) to hide elements while waiting for upgrade. Generally speaking authors completely hide them with :unresolved and only selectively reshow ones where they want to show some content before the upgrade happens. That's pretty exceptional though.

@rniwa
Copy link
Collaborator

rniwa commented Mar 8, 2016

I don't think that's any more surprising than today where authors don't realize they're inline by default and end up with collapsed or overflowing inlines all over.

I disagree.

Generally speaking authors completely hide them with :unresolved and only selectively reshow ones where they want to show some content before the upgrade happens. That's pretty exceptional though.

That would result in FOC when those elements are finally defined. A well behaving web pages should either use defer to load all necessary element definitions (before the initial paint), or specify the dimension on each unresolved element to avoid reflow.

@ojanvafai
Copy link
Member

We have ample evidence that almost every custom element authors create is a block. So, it's a shame for ergonomics to force them to specify it. It's also a shame for custom elements to require a style element just for this one rule. My experience is that it's quite common for this to be the only style rule in a custom element.

Aside from ergonomics, the extra style element has real performance overhead. Even just having the extra style node to do style recalc on ads up when every element on your page is a custom element. You have 2x the DOM for 1x the necessary DOM.

Let's make authors lives a easier and avoid this.

@rniwa
Copy link
Collaborator

rniwa commented Mar 8, 2016

Do most of those custom elements have a shadow DOM? I think I would be okay with making an element with a shadow DOM use display: block by default as that would be backwards compatible.

I don't think either :unresolved not having the same display value or changing display value for all elements with - in its name is acceptable.

I also checked the code of WebKit's perf dashboard that uses Web-Component-style componentization, and it doesn't use display: block as much as you claim it to be. Many of them are display: inline or display: inline-block so I think it really depends on what kind of components you're writing and how you're organizing them. (although it would mean that I have to manually insert display: inline for everywhere in my codebase, so I would personally hate it.)

@rniwa
Copy link
Collaborator

rniwa commented Mar 8, 2016

Having stated my position, if we end up going with the route of change display value upon defineElement (perhaps due to support by Mozilla/Microsoft), then we should just define :defined instead of :unresolved (see the issue #418) and add the following rule to the default UA stylesheet:

:defined { display: block }

Again, my preference is not to do this, and keep display: inline as the default value.

@annevk
Copy link
Collaborator

annevk commented Mar 8, 2016

I still tend to agree with @rniwa that most of the options seem rather magical. I'm not opposed to introducing pseudo-classes and such to assist, but it seems too early to tell what pattern should be made more convenient and how.

@activenode
Copy link

What is the advantage of using display:inline in the first place? Aside of the advantage not having to change something. Aside of that: Why is no one discussing inline-block? Will it bring too much side effects?

@rniwa
Copy link
Collaborator

rniwa commented Mar 8, 2016

@activenode (and everyone else joining this thread now) : See #224 (comment)

@ebidel
Copy link

ebidel commented Mar 8, 2016

There are some good points in this thread. Just want to add my $0.02.

I've spoken with many developers over the years, and custom elements being display: inline by default is a gotcha. It's not what people expect or typically want. I'd love to see us change to display: block or display: inline-block to make life easier. From personal experience building apps, the first thing I do when authoring new elements is add display: block (visual elements) or display: none (non-visual elements) :)

Mindful developers are already dealing with style changes, layout FOUC, and visual FOUC from unupgraded -> upgraded. So IMO, it would be nice for us to optimize for the most common case (display: block). If you throw in @ojanvafai's points on performance, we can optimize both the dev ergonomics and performance.

@bicknellr
Copy link

As long as we're adding :host {display: block;}, why don't we add :host, :host * {box-sizing: border-box;} too? That's what everybody wants, right?

@sjmiles
Copy link

sjmiles commented Mar 8, 2016

Fwiw, I have the same experience as @ebidel. The display:inline default is just not what people expect. Often they put block-level elements inside a host and don't even realize there is a problem until the host reports 0 height, or exhibits strange (to them) rendering behavior.

With respect to #224 (comment), I agree with @esprehn:

I think having registerElement make it become block is fine, you should already be managing FOUC using :unresolved.

@bicknellr
Copy link

Why is block preferable to inline-block?

@domenic
Copy link
Collaborator

domenic commented Mar 8, 2016

Why are people still coming into this thread thinking this is opinion-based? There are technical constraints, discussed in #224 (comment). Listing your favorite sites' percentage of display: block elements is not at all helpful.

@sjmiles
Copy link

sjmiles commented Mar 8, 2016

The technical constraint in #224 (comment) was described as problematic due to being

very confusing for authors

So what is on balance most confusing for authors would seem to be relevant.

@domenic
Copy link
Collaborator

domenic commented Mar 8, 2016

Yes, but it's completely irrelevant how many display: blocks you have. Tell us about how you are not confused by FOUCs on upgrade, but don't tell us about how you use display: block a lot.

@ebidel
Copy link

ebidel commented Mar 8, 2016

Custom elements fall under the extensible web. Luckily, we have a lot of folks with real world experience that can offer actual data points.

The title of this bug is "Custom elements should be display: block by default", so it makes sense that we're still discussing that. @domenic asked for feedback/experience on Twitter and I think that's what we're getting :)

@domenic
Copy link
Collaborator

domenic commented Mar 8, 2016

I'm going to have to lock this issue if people keep failing to read the thread and commenting on something we've already moved past.

@robdodson
Copy link

@rniwa suggested:

Do most of those custom elements have a shadow DOM? I think I would be okay with making an element with a shadow DOM use display: block by default as that would be backwards compatible.

In Polymer land we do make a lot of non-visual elements like iron-ajax, iron-selector, etc. and those don't need to be display: block, nor do they have Shadow DOM. Only our UI elements require display: block and those coincidentally also all have Shadow DOM. Would this be a decent compromise?

@WICG WICG locked and limited conversation to collaborators Mar 8, 2016
@domenic
Copy link
Collaborator

domenic commented Mar 8, 2016

@robdodson that sounds like a decent compromise. Unfortunately this thread has become an unproductive environment, and it sounds like it's moving toward shadow DOM anyway, so it would be best to open a new thread to suggest that for the shadow DOM spec.

@rniwa
Copy link
Collaborator

rniwa commented Mar 8, 2016

We (Apple) had more internal discussions about this, and while we're sympathetic to the developer ergonomics argument made here, we feel that the magical behavior of changing display value at defineElement time or at the time of attaching shadow root is worse than letting developer specify display value themselves.

Furthermore, we're unsure that display: block would be the most popular type. For example, img, canvas, and input are all display: inline. Hence, we don't support the proposal to change the default display value for custom elements or shadow DOM at this point.

@domenic
Copy link
Collaborator

domenic commented Mar 8, 2016

Thanks @rniwa. In the end I think a shadow DOM based solution would end up serving everyone's needs better, and align more with the developer experience based on Polymer and such. It makes intuitive sense to me: the "app-like" non-simple custom elements that want to be laid out in a block-ey fashion are more likely to be the ones that need shadow DOM.

Let's continue discussion of that in #426. I'll close this, although it can be reopened if Mozilla or Microsoft show up with strong support for changing the default here.

@domenic domenic closed this as completed Mar 8, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests