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

Styling of elements where attachShadow(...) not allowed #376

Closed
nazar-pc opened this issue Feb 1, 2016 · 25 comments
Closed

Styling of elements where attachShadow(...) not allowed #376

nazar-pc opened this issue Feb 1, 2016 · 25 comments

Comments

@nazar-pc
Copy link

nazar-pc commented Feb 1, 2016

Question started in #110, which is related, but since #110 is closed now, better move conversation here.
The main issue is that after /deep/ was deprecated and some native elements are disallowed to have Shadow Root it becomes practically impossible to extend those native elements, because styling is one of the key features during button, progress or input extension.

There was few ideas in comments of linked issue, but the last (which is a compromise to avoid complicating things too much) is to state in specification something like following:

Shadow Root in following elements list_of_elements_here MUST contain <shadow></shadow> in the root and MAY contain any number of <style>...</style> elements for styling purposes, any other elements are NOT allowed.

_list_of_elements_here_ is basically blocklist of elements where atttachShadow(...) was not allowed. Effectively this only allows to inherit native Shadow DOM entirely and only add some styling to it.

Hopefully, some solution will be found till v1 release, re-implementing native semantic and work on accessibility for those elements is tricky, there should be a way to inherit all that goodness.

@hayatoito
Copy link
Contributor

That seems what we tried to achieve in the era of v0 spec, but I regret to say that we have failed to define the well-defined rendering behavior of native elements if they are used in such a way.

See https://www.w3.org/TR/2014/WD-shadow-dom-20140617/#html-elements-and-their-shadow-trees as the historical record.

@nazar-pc
Copy link
Author

nazar-pc commented Feb 1, 2016

Can you also point to some discussion where blocking issues regarding that approach are listed?

@hayatoito
Copy link
Contributor

The following might be helpful for you to understand the problem space:
https://code.google.com/p/chromium/issues/detail?id=234020
Note that supporting styling of native elements was not our primary goal there. The approach might be similar, but the goal could be different.

Regarding with the discussion about the spec itself, it is difficult for me to point any useful discussion. I guess that's because this approach has not gotten much attention from folks. If someone knows some discussion we can point, please tell us here.

@annevk
Copy link
Collaborator

annevk commented Feb 1, 2016

Basically we need to advance https://github.com/domenic/html-as-custom-elements somehow to figure out what we can do here.

@nazar-pc
Copy link
Author

nazar-pc commented Feb 1, 2016

I've seen https://github.com/domenic/html-as-custom-elements a long time ago already. It tries to tackle an issue fundamentally, which is definitely a bright happy (and far) future, but I have a feeling that most folks don't need it (at least initially).

What most of times people want to have is:

  • input text/passwoord or textarea with pre-configured border, paddings, colors
  • progress element's bar and value with customized colors (using existing even vendor-specific pseudo-elements)
  • button that have predefined background, color, border

This is the reason I decided to boil down the whole issue to just styling alone. Strictly speaking it works like style attribute, but allows to use attributes selectors, pseudo-elements, pseudo-classes and other features like in regular CSS applied to this element (which is currently only doable with html /deep/ element).

Anytime in future when working with custom Shadow Roots on those elements is defined it will be possible to allow more than <style> and <shadow> elements without breaking backward compatibility. Let's assume UA Shadow Root as black box for now and just inherit as indivisible whole thing.

@annevk
Copy link
Collaborator

annevk commented Feb 1, 2016

So the reason you want to attach a shadow root is to attach styles to the host element? You don't care about the shadow tree? Is there no simpler way to do that? @tabatkins?

@nazar-pc
Copy link
Author

nazar-pc commented Feb 1, 2016

Exactly (except for button which works in Chromium right now, but in blocklist for v1).

Custom progress element as one of the simplest examples: styling and scripting
For buttons and inputs it is a bit more complex.

@hayatoito
Copy link
Contributor

You might be also interested in #300 for styling.

I do not think attaching a shadow root to a native element does not solve a styling issue (from outside) nicely.

@nazar-pc
Copy link
Author

nazar-pc commented Feb 2, 2016

I agree, mentioned proposal is great, but this issue is specifically about internal styling of element, possibility to extend native element and give it different, let's say, default styling.

Here is an example:
2016-02-02 13-40-47
And source code for this part, where first half are extended elements with multiple improvements and default styling, while second half are raw native elements as they are (Chromium):

<button icon="home" is="cs-button" type="button">Button</button>
<input is="cs-input-text" type="text">
<input disabled is="cs-input-text" type="text">
<button force-fullsize icon="home" is="cs-button" type="button"></button>
<cs-icon icon="home"></cs-icon>
<textarea is="cs-textarea"></textarea>
<nav is="cs-nav-tabs">
    <button is="cs-button" type="button">One</button>
    <button is="cs-button" type="button">Two</button>
</nav>
<section is="cs-section-switcher">
    <article>One</article>
    <article>Two</article>
</section>
<label is="cs-label-switcher">
    <input checked type="radio" value="0"> Zero
</label>
<label is="cs-label-switcher">
    <input checked type="radio" value="1"> One
</label>
<nav is="cs-nav-pagination" page="1" pages="20"></nav>
<progress is="cs-progress" value="20"></progress>
<br>
<br>
<button icon="home" type="button">Button</button>
<input type="text">
<input disabled type="text">
<button force-fullsize icon="home" type="button"></button>
<cs-icon></cs-icon>
<textarea></textarea>
<nav>
    <button type="button">One</button>
    <button type="button">Two</button>
</nav>
<section>
    <article>One</article>
    <article>Two</article>
</section>
<label>
    <input checked type="radio" value="0"> Zero
</label>
<label>
    <input checked type="radio" value="1"> One
</label>
<nav page="1" pages="20"></nav>
<progress value="20"></progress>

As you can see, it is very convenient to be able to greatly improve native element with [is] while preserving its semantics and accessibility features. I'm trying to always extend native elements in contrast to Polymer team, they try to re-implement all the elements from scratch

@hayatoito
Copy link
Contributor

Thank you for sharing it. I guess you are using type extension. https://w3c.github.io/webcomponents/spec/custom/#dfn-type-extension

AFAIK, we cannot style internal of elements even if we use type extension. A type-extension just acts as label so that we can style elements with the label from outside, right?

Thus, backing to the proposed approach:

Shadow Root in following elements list_of_elements_here MUST contain in the root and MAY contain any number of <style>...</style> elements for styling purposes, any other elements are NOT allowed.

I am wondering how this works and what is the expected behavior. Could you tell us the concrete example how it should work?

@nazar-pc
Copy link
Author

nazar-pc commented Feb 4, 2016

Yes, I'm using type extension.

By internal styling I meant element itself, nothing deeper than it is available from outside.

If you don't mind I'll give Polymer example:

<dom-module id="cs-input-text">
    <template>
        <style>
            :host {
                border : 10px solid black;
                color  : red;
            }

            :host([disabled]) {
                color : blue;
            }

            :host([compact]) {
                width : auto;
            }

            :host([full-width]) {
                width : 100%;
            }
        </style>
        <shadow></shadow>
    </template>
    <script>
        Polymer({
            is      : 'cs-input-text',
            extends : 'input'
        });
    </script>
</dom-module>
<!-- usage -->
<input is="cs-input-text">
<input is="cs-input-text" disabled>
<input is="cs-input-text" disabled compact>
<input is="cs-input-text" full-width>

Shadow Root of input[is=cs-input-text] will contain UA's Shadow Root without any changes + <style> element to give element additional default styling. Other elements than <style> MUST be forbidden till future versions of spec which will define how it works.

@hayatoito
Copy link
Contributor

Thank you. Maybe I misunderstood the concept of "internal styling".
To me, it looks "styling from outside by default". :)

Having said that, I still do not think it is a good idea to use attechShadow() for this purpose.
Can we have a more lightweight approach?, such as

document.registerDefaultStyle("input", condition, style) or something?

@nazar-pc
Copy link
Author

nazar-pc commented Feb 4, 2016

To me, it looks "styling from outside by default". :)

Exactly

I have nothing against any alternative approach, the main point just to make this possible.

I do not personally like using imperative syntax for styling purposes, there should be a way to use <style> nodes for this. Maybe introduce something like Style Root that can only contain CSS? This would help to avoid any ambiguity.

...
createdCallback : function () {
    var s = document.querySelector('style#something');
    this.attachStyle(s); // and/or this.createStyleRoot()
}
...

@hayatoito
Copy link
Contributor

Thanks. BTW, one of the primary reasons we removed /deep/ is it's too powerful and it's very style-engine unfriendly combinator in terms of the performance.

If we are allowed to ban a combinator, we could have the following declarative rules without significant performance penalty:

@global-compound-selector-rule {
 /* This rule applies to any element, even if it is in a descendant shadow tree.
  However, we are not allowed to use any combinator in a selector here. */
 input {
     border : 10px solid black;
     color  : red;
 }

 input([disabled]) {
     color : blue;
 }

 input([compact]) {
     width : auto;
 }

 input([full-width]) {
     width : 100%;
  }
}

Just as a naive idea.

@hayatoito
Copy link
Contributor

Let me close this issue tentatively. Please feel free to re-open this if someone still wants to support this use case.

@rniwa
Copy link
Collaborator

rniwa commented Apr 26, 2016

We're having a hard time following this discussion because there is a lot of different use cases and ideas being discussed here. Could someone compile a list of concrete use cases that are meant to be addressed by this issue?

@domenic
Copy link
Collaborator

domenic commented Apr 26, 2016

@rniwa are you referring to #468? This discussion was closed and its use case remains unaddressed I believe, or rather the specs have evolved significantly so that it's not very applicable.

@rniwa
Copy link
Collaborator

rniwa commented Apr 26, 2016

Oh oops, yeah.

@nazar-pc
Copy link
Author

Actually the idea was to be able to somehow style elements that extend native ones (type extension if spec didn't change in this respect) because of Shadow Root absence on those and #468 actually covers this use case. So I'm completely satisfied with approaches in #468 and don't need this to be reopened.

@rniwa
Copy link
Collaborator

rniwa commented Apr 26, 2016

Since we're opposing to having type extensions (is attribute, etc...) in custom elements so the approach depicted in the issue #468 would not work for builtin elements that do not support shadow roots.

@nazar-pc
Copy link
Author

Do you mean it will not be supported at all? Where can I find discussion or anything about it?

@rniwa
Copy link
Collaborator

rniwa commented Apr 26, 2016

Custom elements will be supported but only for ones that don't extend subclasses of HTMLElement. See http://www.w3.org/2016/04/05-webapps-minutes.html We opposed but I guess the working group's consensus to keep it in the draft until it becomes clear that the feature won't be implemented by all major browser vendors even though we've already said so (i.e. don't support it).

@nazar-pc
Copy link
Author

Haven't found what you said following the link.

This would be very frustrating if not implemented at all.

As developer who is using Polymer and Shadow DOM (native in Chrome, full polyfill in other browsers) I do not see any sane reason to re-implement, say, input[type=password] or button[type=submit] if it is already present in browser and contains all semantic and accessibility features out of the box. I want just style it a bit, add few methods and events. I'm not intending to change UA Shadow Root or something like this.

The same about progress - all I need is to set max=100 by default and apply default styling I need to element itself (:host). Why should this require me to implement element from scratch?

@rniwa
Copy link
Collaborator

rniwa commented Apr 30, 2016

@nazar-pc
Copy link
Author

I see valid points in wiki, but IMO how it works in Chrome now is perfectly fine as for initial implementation. It doesn't scale, this is true, it doesn't give any access to UA Shadow DOM, but it gives some benefits inaccessible otherwise as well.

Rebuilding native elements as custom elements is perfect idea and I really hope we'll be there some day, but it feels like it may take 5+ years until it will be available for developers, however type extension already works in Chrome and it even works reasonably well with polyfill.

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

No branches or pull requests

5 participants