- From: Philip Walton <notifications@github.com>
- Date: Fri, 28 Aug 2015 11:31:27 -0700
- To: w3c/webcomponents <webcomponents@noreply.github.com>
- Message-ID: <w3c/webcomponents/issues/298/135854945@github.com>
Thanks @hayatoito, I'm familiar with custom properties and the experimental [CSS @apply rule](http://tabatkins.github.io/specs/css-apply-rule/) that the Polymer team is using. I still, however, think that custom properties do not go quite far enough. Since I've already written this down for a talk I'm giving, I'll just post my notes here since I don't think this is documented anywhere else: *** Given the following basic shadow DOM for an `<awesome-list>` element, consider how its styling could be exposed to 3rd-party users: ``` <shadow-root> <style></style> <ul> <li></li> <li></li> <li></li> </ul> </shadow-root> ``` ## Custom properties If the `<awesome-list>` author exposed list item styles via custom properties like this: ```html <shadow-root> <style> li { margin: var(--awesome-list-item-margin, 2em); } </style> ... </shadow-root> ``` Then this would work just fine: ```css awesome-list { --awesome-list-item-margin: 2em; } ``` This is great for many use cases, but what if I wanted to have no bottom margin on the very last item in the list? With custom properties, this can't be done unless the element author has specifically exposed that as yet another custom property. ```html <style> li { margin: var(--awesome-list-item-margin, 1em); } li:list-child { margin: var(--awesome-list-item-last-margin, var(--awesome-list-item-margin)); } </style> ``` Which would then be implemented like so: ``` awesome-list { --awesome-list-item-margin: 2em; --awesome-list-item-last-margin: 2em; } ``` Once you consider the total number of pseudo-classes in existence (:active, :hover, :focus, :nth-child, etc.), it's easy to see how this can quickly get out of hand -- especially if you're exposing a number of properties for customization. It's also a little bit clunky because you're conceptually styling two different elements, but you're authoring those intentions in the same selector, so it's probably not super clear to other's skimming that code what's going on. ## Custom pseudo-elements Custom pseudo-elements make this quite a bit easier, and also have the advantage of already being familiar to CSS developers. If there were a way to declare that list items is styleable through the pseudo-element name `::item`, it makes everything a lot easier. ```css awesome-list::item { margin: 2em; } awesome-list::item:last-child { margin-bottom: 0; } awesome-list::item:hover { background-color: yellow; } ``` ### Declarative syntax The `pseudo` attribute is already used in the Shadow DOM of native HTML elements like the `<audio>` tag, so using that makes the most sense: ``` <ul> <li pseudo="item"></li> <li pseudo="item"></li> <li pseudo="item"></li> </ul> ``` ## Unresolved questions * Should pseudo-element rules defined outside of the element always trump styles defined inside the element, regardless of selector specificity? (E.g. should `awesome-list::item` trump `:host ul li.some-matching-class`?) * Should pseudo-element selectors work when prefixed with the universal selector (or implied universal selector), or should they require a custom element prefix? * Is the [CSS @apply rule](http://tabatkins.github.io/specs/css-apply-rule/) needed if custom pseudo-elements exist? It seems like it's unnecessary for styling elements in a shadow root, though perhaps it'll be a good addition for general custom property usage in non-Web Component scenarios. --- Reply to this email directly or view it on GitHub: https://github.com/w3c/webcomponents/issues/298#issuecomment-135854945
Received on Friday, 28 August 2015 18:32:59 UTC