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

Sharing styles across custom elements #282

Closed
varunkumar opened this issue Jul 16, 2015 · 22 comments
Closed

Sharing styles across custom elements #282

varunkumar opened this issue Jul 16, 2015 · 22 comments

Comments

@varunkumar
Copy link

We are building a bunch of components for an internal project. These components share some common styles (like font-awesome fonts, custom css framework, etc). As of now, we are sharing these styles across components using /deep/ combinators. I understand from the recent web components meeting that /deep/ combinator and other shadow piercing combinators are going to be removed.

I understand that Shadow DOM provides style boundary and it also helps in abstracting the implementation details of the component. In my use case, I am more interested in the latter than the former. Though style boundary prevents accidental leakage of styles, I still find the ability to selectively pierce the components useful.

Please suggest alternatives for being able to share styles across components. (Custom css properties and named parts model might not be suitable for this use case. I am interesting in sharing classes across components than configuring hooks for theming).

@davidmaxwaterman
Copy link

Someone provided this example to me - perhaps you can adapt it :

var eStyle = document.createElement("style");
eStyle.textContent = "div.boilerplate { color: blue; }"
document.querySelector("#ex2bNameTag").shadowRoot.appendChild(eStyle);

I wonder if it will also work if you have a stylesheet link...

@hayatoito
Copy link
Contributor

FYI. There is a draft spec from @tabatkins, which will make the style sharing more efficient.
http://tabatkins.github.io/specs/construct-stylesheets/

@hayatoito
Copy link
Contributor

In Blink, we calculate the hash value of textContent of <style> element before parsing it. If the hash value is same to one of the cached values, we omit the parsing stage and reuse and share the result.

The draft proposal is a way to resolve this issue officially. Users can feel that this kind of efficiency is guaranteed.

@davidmaxwaterman
Copy link

@hayatoito you're specifically talking about issue 3 in that draft spec? It's a bit over my head, tbh, so I'm not sure how it will help the user - is it just about speed/efficiency, and the user just creates a style element and appends it, like above?

@hayatoito
Copy link
Contributor

@davidmaxwaterman Yes, creating a style element in each shadow tree is an option as a replacement, although I'm aware that that's not a direct replacement and it would be painful for users.

We introduced /deep/ (and ::shadow) to satisfy exactly such a requirement - "Users still find the ability to selectively pierce the components". However, these shadow piercing combinators have been less-loved from other browser vendors, as you might know.

@davidmaxwaterman
Copy link

@hayatoito yeah, but some people have the luxury of only targeting chrome :) Chrome apps and extensions, for example...and I guess some companies can mandate chrome as a browser (though usually it's IE, in my experience, unfortunately).

@michelbio
Copy link

I personally find using /deep/ (and ::shadow) as selectors very convenient, when developing extension for Chrome. It tends to at least keep both the (S)CSS and JS selects more straightforward to work with.

@Nevraeka
Copy link

Varunkumar,
CSS properties are the current way developers are theming in Web Components
right now, at least the ones I know. Polymer developers are as well. It
seems to be where things are headed.

On Thu, Jul 16, 2015 at 1:29 PM, Varunkumar Nagarajan <
notifications@github.com> wrote:

We are building a bunch of components for an internal project. These
components share some common styles (like font-awesome fonts, custom css
framework, etc). As of now, we are sharing these styles across components
using /deep/ combinators. I understand from the recent
https://www.w3.org/wiki/Webapps/WebComponentsApril2015Meeting web
components meeting that /deep/ combinator and other shadow piercing
combinators are going to be removed.

I understand that Shadow DOM provides style boundary and it also helps in
abstracting the implementation details of the component. In my use case, I
am more interested in the latter than the former. Though style boundary
prevents accidental leakage of styles, I still find the ability to
selectively pierce the components useful.

Please suggest alternatives for being able to share styles across
components. (Custom css properties and named parts model might not be
suitable for this use case. I am interesting in sharing classes across
components than configuring hooks for theming).


Reply to this email directly or view it on GitHub
#282.

*Erik Isaksen *

Google Developer Expert HTML5
https://developers.google.com/experts/people/erik-isaksen

The Web Platform Podcast http://thewebplatform.libsyn.com/ Show Host

ReadTheSource.io http://ReadTheSource.io Co-Host

nevraeka@gmail.com nevraeka@gmail.com
*@Eisaksen https://twitter.com/eisaksen *

The Web Platform Podcast Links

Twitter - https://twitter.com/thewebplatform

Google Plus - https://plus.google.com/u/0/106965203807974584370

Stream/Web -http://thewebplatform.libsyn.com/

Facebook - https://www.facebook.com/thewebplatform

iTunes -
https://itunes.apple.com/us/podcast/the-web-platform-podcast/id899384794?mt=2

Stitcher - http://www.stitcher.com/podcast/the-web-platform-podcast

YouTube (not all episodes available) -
https://www.youtube.com/channel/UCjz3j22CyBpy6Qk5SL6UwcQ

RSS - http://thewebplatform.libsyn.com/rss

Github - https://github.com/thewebplatform

Read The Source: Open Source Companion Live Screencast

Twitter - http://hangouts.readthesource.io/

Google Plus - https://plus.google.com/105627089988168968277/

Youtube - https://www.youtube.com/channel/UCVqD-Rd1nMmvbvf-AvQvgZw

Github - https://github.com/readthesource

RSS - http://hangouts.readthesource.io/index.xml

@tabatkins
Copy link

The shadow-piercing combinators are indeed helpful, but they're also (a) terrible for performance, and (b) footguns, as you can easily style things you didn't intend.

@Nevraeka is right - using Custom Properties (soon to be released in Blink) as the theming mechanism is safer and more targeted, and more performant. We expect to add more theming abilities in the future, like perhaps a way to expose an element/subtree from your component as a pseudo-element on the host, so you can do arbitrary styling. But that's in the future, and is just a convenience measure.

@varunkumar
Copy link
Author

Custom properties won't help me always. For example, I want to use font-awesome in my components. Currently, I am using /deep/ combinator for all classes in fa. How can I achieve the same without that? I would end up repeating those classes in all components.

I understand the complexities involved in supporting shadow-piercing combinators. However, I still feel that custom properties wouldn't be just sufficient. I will read about construct stylesheets spec.

@pemrouz
Copy link

pemrouz commented Sep 21, 2015

@varunkumar, fwiw, I hit the exact same problem with font awesome. Custom properties don't help here, but the solution is not to /deep/ all the CSS icons either. What's needed is a more modular font awesome and better tooling in producing/consuming them - so that a Web Component can still be self-contained. To reuse common styles, I think ideally a component stylesheet would use the standard @import:

@import 'fa-circle'

There may be a little repetition, but it's better for the component to declare exactly what it needs rather than assuming it will be there. The browser can deal with caching and optimise the problem of not fetching a duplicate stylesheet more than once.

Until @import is natively supported in Shadow DOM, this can be smoothed over and solved at the framework level (rijs/precss#1) - i.e. simply reading @import's, fetching styles and idempotently prepending <style> tags.

@rniwa
Copy link
Collaborator

rniwa commented Sep 21, 2015

Is fa-circle the name of a CSS file in your example above? If so, that's already supported in shadow DOM since style elements are fully supported.

@pemrouz
Copy link

pemrouz commented Sep 21, 2015

Awesome! I didn't realise @import was already natively supported. What's the current/planned behaviour of other at-rules like @font-face and @keyframes in these style tags?

@rniwa
Copy link
Collaborator

rniwa commented Sep 22, 2015

All those at rules should work just like any other style element in regular DOM except that fonts imported inside a shadow dom, for example, isn't exposed to "light" DOM's stylesheets.

@varunkumar
Copy link
Author

We have started using @import as a workaround.

@dglazkov
Copy link
Contributor

@tabatkins @esprehn

@pemrouz
Copy link

pemrouz commented Sep 23, 2015

All those at rules should work just like any other style element in regular DOM except that fonts imported inside a shadow dom, for example, isn't exposed to "light" DOM's stylesheets.

Correct me if I am wrong @rniwa, but doesn't look like the discussion on @font-face in Shadow DOM has been resolved yet..

@tabatkins
Copy link

Correct. We've never come up with a satisfactory answer to the problem of "the 'font-face' property inherits, but could accidentally refer to completely different @font-face rules outside vs inside the shadow root", which harms composability.

@hayatoito
Copy link
Contributor

Given that we now have http://tabatkins.github.io/specs/construct-stylesheets/, this issue should be tracked form the view of custom elements. Let me add custom-element label.

@trusktr
Copy link
Contributor

trusktr commented Apr 26, 2016

Expanding on @davidmaxwaterman's idea, you could use a tool like @kof's JSS (among others) to generate the repeat styles you need and add them to your roots.

It seems like http://tabatkins.github.io/specs/construct-stylesheets/ might be similar to this JSS idea, with CSS strings instead of object literals, but I don't see any examples in that document (that would be nice @tabatkins!). I suppose it could be something like

// shared-style.js
export default
function myStyle(color) {
  return new CSSStyleSheet(`
    .some-el {
      background: ${color};
    }
  `, options)
}
// other-file.js
import myStyle from '.../shared-style'
let style = myStyle('blue')

// add the style to the root

@kof
Copy link

kof commented Apr 26, 2016

also see cssinjs/jss#220

@domenic
Copy link
Collaborator

domenic commented Apr 26, 2016

This can be rolled into #468 which has a more detailed proposal in #468 (comment) and #468 (comment). That will only allow strings for now, but once constructible stylesheets are a thing it's a straightforward extension.

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