Re: [cssom][css-display][css-cascade] revisiting "default display"

On Fri, Sep 6, 2013 at 4:41 PM, Mike Sherov <mike.sherov@gmail.com> wrote:
> On Fri, Sep 6, 2013 at 3:08 PM, Tab Atkins Jr. <jackalmage@gmail.com> wrote:
>> Getting the initial value *kinda*
>> helps *today*,
>
> I'm not talking about "initial value",

Apologies, I was using words imprecisely.  I'm also talking about
"default value" - it would be pretty silly of me to be discussing the
use-cases for "initial value" when we already have a keyword that does
exactly that.

>> because most people still use either display:block or
>> display:inline for everything, but that's it.  As flexbox and grid
>> become more popular, elements will commonly be intended to use those
>> displays, and then the "default value" is worthless.
>
> I don't think so. I'm talking about "default value" which is different than
> "intended" value. I'm not sure why you think any author would expect calling
> .show() on a hidden div to result in grid or flexbox? Authors expect calling
> .show() on a div results in display:block. I know because they reported bugs
> on this when it doesn't do this right.

Think about what I'm saying again.  Yes, *today*, calling .show on a
<div> means I probably want it to be display:block, *because that's
the most reasonable display value for a <div> in today's technology*.
Sure, occasionally you'll use a <div> for inline-block or table, but
that's rare.

*Tomorrow*, that will no longer be the case.  Flexbox and grid, when
they penetrate sufficiently to be generally reliable, will hit *hard*
and wide.  They'll be used *constantly*, for all sorts of things,
*particularly* JS-using apps, and any "significant" container in the
page (which is the sort of thing I expect .show() to usually be called
on). Making .show() default to "block" when it can't figure anything
else out might still be what you have to do, but only because there's
nothing else you *can* do, because you can't figure out the right
display value without understanding the page as only a human can.
Finding a default value for .show() will be something you do for minor
convenience, not something that's actually good and useful a majority
of the time.

Thus, I'm perfectly okay with it remaining slightly annoying to figure
out the default value of display, at least given only this use-case.

>> I'm curious why jQuery uses an iframe hack.
>
> So we don't have to keep a large list of elements. It's smaller, code wise,
> to do the hack and is future proof as you mention.

I don't really understand - I'd suspect the code weight would be
roughly the same, within tens of characters.  You literally just have
an object-map with tagnames as keys and display values as values, and
when someone calls .show() on an element, you feed its tagname through
the object, defaulting to "inline" if it's not found.  Definitely
higher performance and lower memory weight than creating a whole
iframe (which presumably sticks around between calls), creating an
inserting an element into it, then asking it for its computed style
and checking 'display'.

Its only downside, as mentioned, is that when HTML adds a new
block-level element, the behavior will be wrong until someone fixes
it, or an author manually adds the new tagname to the map.

>> Is it just to be
>> future-proof?  Just keeping around an array of default-block element
>> names should be sufficient if you're not trying to be robust against
>> future element additions (and if it's exposed, authors can just add to
>> it in that case until jQuery updates).
>
> Requiring developers to have to add their element to a large array? It's
> easier for them to fix the "div {display:none;}" declaration than to have to
> manipulate an array (which presupposes they are serving their own copy of
> jQuery). It's also easier for them to just do .css('display', 'block').

I think you must have misunderstood my suggested simpler workaround -
see above for the description.  This wouldn't involve someone actually
modifying jQuery source code, just at run-time adding a key to an
object hanging off of something.

> But
> your suggestion presupposes they are aware of the issue. I'm trying to make
> it something that devs don't ever have to even think about. jQuery already
> provides them a solution so they don't have to think about this problem. I'm
> just asking for the spec to provide this functionality in a declared API.
>
>> The only way to actually let an element be hidden by default and then
>> show with the correct display type is for authors to use "box: none;"
>> in the first place, rather than "display:none".
>
> I agree. Unfortunately, I'm a library developer, not an end author. I'm not
> saying we shouldn't have box:none either, though. I agree we need it as
> well, specifically for the use case of .hide(). It allows the library to
> just apply "box:none;" and remove it on .show().

You can continue using your existing iframe-based workaround or my
suggested tagname-to-value workaround just fine; authors never have to
think about it.

The relevant question, as always, is not "how simple is it?", but
rather "how useful is it?".  From what I can tell, it's slightly
useful now, will decrease to only marginally useful in the near
future, and in any case has easy workarounds.

>> "display:none" is
>> just a pernicious legacy mistake.
>
> Calling "display:none" "legacy" is about 5-10 years too early.
> window.getDefaultComputedStyle() is a backwards compatible solution that
> works today in Firefox and doesn't require any intervention from the author.

I don't understand what you mean by "too early".  display:none was a
mistake, full stop.  It's not a display type at all.  It's a
conflation of layout management and box construction which is
defensible from a theoretical standpoint, but not a practical one.
We've known this for many years, but it hasn't been sufficiently
important for anyone to fix yet.

>> So I still don't think it's worthwhile to add back default values.  It
>> simply doesn't help this use-case sufficiently to be worthwhile imo.
>
> But it does. I believe I've shown how it does, and how it sufficiently
> addresses the problem. You haven't shown me how it doesn't solve the
> problem, except mentioning that some people may expect a default to flexbox
> or grid. I don't believe that's a good counterargument, but perhaps I've
> missed something.

You're attempting to argue that the value of a property after applying
the UA stylesheet, but before applying author stylesheets, is a useful
guess for the value the author intends anyway, which helps a function
like .show() to function.  This relies on the assumption that authors
don't usually change the value of a given property from the
UA-supplied default - whenever they use a <div>, they keep it as
display:block most of the time.  My argument was pointing out that no,
the author will increasingly override the UA-provided default in the
cases you're arguing for as we move into the future.

> BTW, if you need another use case for this, it also solves the problem for
> when someone tries to accidentally call .show() on an element that has
> default "display:none", like a <input type=hidden>. You may think that's
> non-sensical, but all an author has to do is $('form').children().show(),
> and you're accidentally showing hidden inputs.

This is why the idea maintains at least marginal value (it is indeed
rare to change the 'display' value from the default on default-hidden
elements), but again, either of the workarounds discussed in this
thread so far are quite simple and handle this case well.

Note, though, a case where this will fail - calling .show() on a <div
hidden>, using solely the "default value" semantics", will keep it
hidden.  You have to special-case this logic anyway for some elements.

~TJ

Received on Saturday, 7 September 2013 00:15:25 UTC