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

Difficult to create reusable styles (style guide) #1052

Closed
zinkkrysty opened this issue Dec 25, 2014 · 19 comments
Closed

Difficult to create reusable styles (style guide) #1052

zinkkrysty opened this issue Dec 25, 2014 · 19 comments
Labels

Comments

@zinkkrysty
Copy link

Polymer is great for encapsulating styles and functionality so it doesn't leek into the main document.

However, when building a larger web application using Polymer, sharing styles is very important to the maintainability of the project. Also, with increasing popularity of SASS in web design, there are numerous libraries that make designer's life easier and stylesheets more maintainable.

Currently in Polymer, there are limited ways of sharing styles, all with serious issues that make building a web application in Polymer resembling a bit the entangled mess of a spaghetti bowl for web designers. These ways are the following, however the issues are obvious and hard to find workarounds to, without affecting the maintainability of the project codebase:

  1. Using /deep/ to target all shadow DOMs
    • Every selector needs to have body /deep/ in order to propagate the shared styling. Adds a lot of overhead to the stylesheet, also making things like selector + selector behave unexpectedly.
  2. Importing the same stylesheet for many elements
    • Seems more like a hack, which is bad for performance
  3. The <core-style> to reuse CSS declarations directly.
    • This method is very promising, however because of writing styles directly in the <core-style> tag, we can't use the power of pre-processors or including external stylesheets

CSS can indeed be hard to maintain and this is confirmed by the very numerous and strict ways of achieving this job (read BEM, style guides, specificity managing, etc.).

I believe having a great living style guide is one of the important keys to solving the CSS maintainability problem, however it is very hard to find a way to do this properly with Polymer and web components.

This issue is connected to the fact that when building a Polymer app, it tends to go into the direction where your app is a Polymer element itself and made out of other Polymer elements, making it hard to have a common stylesheet that applies to elements in your app.

More specifically, how would we style basic elements like h1 and h2, making them share the style for a consistent look across the app, no matter where they are situated in the Shadow DOM tree?

@kgryte
Copy link

kgryte commented Dec 26, 2014

Re: 1. You should actually measure performance. I do not believe the hit will be as bad as you think. Furthermore, the principle idea is that Polymer components should be small and self-contained. In which case, CSS declarations should be relatively limited and scoped. If you find yourself with numerous/lengthy component styles and/or managing components with global styles, you may want to rethink how you are building your components and designing your application.

Re: 2. You can use pre-processors and external stylesheets, but, in order to do so, you need a build step. Numerous ways to do this; e.g., use Make, gulp, grunt, <insert_favorite_task_runner> to insert compiled stylesheets into a core-style HTML template. If you are already using, say, Browserify and Vulcanize, you have to run a build step anyway. Just add another step to the flow. Setting up watchers in Make is easy; dido with grunt and gulp.

Ah, and one further point re: 1, if you create a shared asset folder (say of CSS stylesheets: reset, normalize, etc), your components can import those shared assets without a hit to performance, assuming your setup enables deduping.

@zinkkrysty
Copy link
Author

Regarding your suggestion to 1., I agree that Polymer elements should be small and self-contained. However, when building an entire app in Polymer, you tend to go in the direction that your app itself is an element, therefore defeating its purpose. That is the case at least in my experience, because things like data binding only work within Polymer elements and self binding templates, and it's probably bad architecture to make your whole app a self-binding template (it seems like a hack nevertheless).

As I guess that you have more experience than I do, I'd like to hear your points about you think a proper Polymer app should be built/designed having these considerations about shared styles in mind.

It would also be interesting to introduce the concept of using Shadow-less elements (#222) whose purpose should be to allow deliberate use of shared assets and styles. That would be a 4th approach to this issue.

As for your no.2 reply, that is an interesting approach, and it's worth exploring. I was testing a setup where it's a cross between a Rails app and a Poylmer app using the emcee gem, and I'm not sure how I would achieve that directly, but there should be a way.

@ebidel
Copy link
Contributor

ebidel commented Dec 27, 2014

I've had a lot of luck creating a shared _element.scss stylesheet to include shared vars/styles in elements. This gets baked into the element's stylesheet when it's generated by sass. (example). With something like this, you're not including huge stylesheets in each element and are able to share styles quite easily.

@zinkkrysty
Copy link
Author

That seems a quite pragmatic way to try to manage this.

However, you end up importing a lot of SASS and ultimately some CSS in each element:

@import "compass/css3/transition";

@import "font-awesome/font-awesome.scss";

@import "element";

How can we design web components so we avoid this unnecessary repetition?

@ebidel
Copy link
Contributor

ebidel commented Jan 4, 2015

It's a common practice to include everything inside the components import that is depends on. This should include all of its dependencies and markup. As such, it makes sense to include/import any css the component needs. Importing compass files are harmless. They're only mixins and won't bloat the output .css file. For things like fonts, we usually use an HTML Import to bring it in as a dependency at the top of the element's import:
https://github.com/Polymer/font-roboto/blob/master/roboto.html

The benefit of this is that all elements that reference this same import URL will be de-duplicated, yet the element still has all of the things (fonts in this case) it depends on.

@ssorallen
Copy link
Contributor

I interpreted the "overhead" of "Using /deep/ to target all shadow DOMs" to be a comment on the work required to use existing libraries with custom elements that use shadow DOM and not a comment on performance. If you wanted to use a pre-built CSS framework like Bootstrap, putting a single <link> in the head would likely not work as expected if your pages use any shadow DOM: you'd have to modify the library and prepend body /deep/ to many of its selectors or forego the shadow DOM like @zinkkrysty mentioned (#222).

@ebidell, is the current suggestion to add a <link> to the library in each custom element and let the browser de-dupe the multiple references to the stylesheet?

@Nevraeka
Copy link

@ssorallen As a general note on CSS...version 0.8 is being tested now with optional Shadow DOM so theming could also be achieved a bit more like we would expect it to be based on current best practices. /deep/ is a hammer and should be used in moderation as necessary. Shared styles can be achieved in a few ways.

  • Using a CSS precompiler as your core styling distribution at build time that concat to the appropriate component files (as @ebidel points out) & vulcanize
  • Using <core-style> (as described in @PascalPrecht 's article);
  • use ::content and shallow Shadow Roots (probably hard to achieve when using other peoples components with yours but the idea is sound)
  • "Hulk Smash" style by using global body /deep/ selectors (similar to !important)
  • wait until Shadow DOM is optional

A combination of these might be a good way to go to see what works for you. You can git checkout -b 0.8-preview to use the 0.8 version if you like but keep in mind that it is a preview and not a release yet so it's buggy.

@ebidel
Copy link
Contributor

ebidel commented Jan 13, 2015

Is the current suggestion to add a <link> to the library in each custom element and let the browser de-dupe the multiple references to the stylesheet?

I wouldn't recommend including huge libraries like boostrap.css like this.

@ssorallen
Copy link
Contributor

Thanks for the round up, @Nevraeka.

@Nevraeka
Copy link

👍 @ssorallen

@zinkkrysty
Copy link
Author

Oh that's very neat, @Nevraeka ! Optional Shadow DOM seems like a good solution, until we can have a more versatile <core-style> element.

Using the project's own styleguide is similar to using an external library such as Bootstrap, which is now a pain with Shadow DOM and the way styles aren't inherited by custom elements.

I wonder if it would be a good idea that you can turn Shadow DOM on/off for any element that you use, even if it's a core element or a paper element. That way, you can have a custom CSS style guide that would impact those elements as well.

I am not sure where the fine line is between Shadow DOM being very useful or just a pain to work with in big projects. Any tips from someone with experience here?

@esprehn
Copy link

esprehn commented Feb 8, 2015

Using lots of <style> elements will be the most performant option in
Chrome. You don't want to "bake" your common styles into a single sheet in
all your components, instead you want to do something like:

...

We then share the common.css sheet internally between all widgets that used
it, and the this-widget.css sheet will be shared between all of this
elements that use it.

On Fri, Jan 16, 2015 at 7:47 PM, Cristian Andrei [email protected]
wrote:

Oh that's very neat, @Nevraeka https://github.com/Nevraeka ! Optional
Shadow DOM seems like a good solution, until we can have a more versatile
element.

Using the project's own styleguide is similar to using an external library
such as Bootstrap, which is now a pain with Shadow DOM and the way styles
aren't inherited by custom elements.

I wonder if it would be a good idea that you can turn Shadow DOM on/off
for any element that you use, even if it's a core element or a paper
element. That way, you can have a custom CSS style guide that would impact
those elements as well.

I am not sure where the fine line is between Shadow DOM being very useful
or just a pain to work with in big projects. Any tips from someone with
experience here?


Reply to this email directly or view it on GitHub
#1052 (comment).

@sorvell sorvell added 0.8 and removed 0.8 labels Mar 5, 2015
@Meligy
Copy link

Meligy commented Apr 14, 2015

@esprehn is <style> more performant than <core style ref=".." > in that case?

@esprehn
Copy link

esprehn commented Apr 14, 2015

I assume core-style just inserts a <style> so it should perform about the
same.

On Mon, Apr 13, 2015 at 8:45 PM, Mohamed Meligy [email protected]
wrote:

@esprehn https://github.com/esprehn is <style> more performant than in that case?


Reply to this email directly or view it on GitHub
#1052 (comment).

@clintwood
Copy link

Doesn't this issue simply highlight a limitation or shortcoming with related WebComponent specifications.

To me it feels like we trying to hack out a solution specifically around theming existing components and none seem natural and/or intuitive... Am I missing this completely?

@cmawhorter
Copy link

@clintwood That was my take away after building an internal app with polymer last year. I just found a chat transcript from last month talking about this stuff, so it seems like it's at the forefront.

I just hope it gets resolved in a way that doesn't just trade bootstrap for polymer-ui. I'd really like to be able to use a la carte components without a huge styling headache.

@tjsavage tjsavage added the 0.5 label May 21, 2015
@tjsavage
Copy link
Contributor

Closing this issue due to age and the release of version 1 of Polymer - please feel free to re-open if this is incorrect.

@cmawhorter
Copy link

Even 1.0 doesn't feel like a good solution to the theming problem: https://www.polymer-project.org/1.0/docs/devguide/styling.html#custom-css-mixins

CSS4 will go a long way to alleviating the generic website theming problem but polymer/WebComponents feel clunky to me. Which is why I don't bother changing default polymer styles... who wants that headache.

A brief somewhat off-topic Web Component rant:

It seems to me that shadow dom and a chunk of the other web component spec serves to recreate what is essentially an <iframe> in a terrible way.

My $0.02 -- Extending iframe would've solved what web components aimed to in a backwards compatible way.

And an even more off-topic rant... entire SPA frameworks have been built to recreate <frame>. The new web is insane.

Edit: Oops. html swallowed.

@jaichandra
Copy link

@ebidel What's the best practice for including a shared library in an element. I understand that the import is de-duplicated, but what's the performance impact on including a large shared style module. Will it get copied in the DOM for each element and parsed separately?

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

No branches or pull requests