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

Tool for generating custom-style wrapper for external stylesheets #2429

Closed
ebidel opened this issue Sep 10, 2015 · 34 comments
Closed

Tool for generating custom-style wrapper for external stylesheets #2429

ebidel opened this issue Sep 10, 2015 · 34 comments

Comments

@ebidel
Copy link
Contributor

ebidel commented Sep 10, 2015

Users want to use external stylesheets (or sass compiled css) with our styling system. <link rel="import" type="css"> has been deprecated. It would be great to have a tool to help with this.

Reference: Polymer/old-docs-site#1347

@pensierinmusica
Copy link

This is super important! And it's getting waaay too complicated. Users need to be able to use any CSS preprocessor they want (e.g. SASS, Less, cssnext). Easily. One should be able to read the docs and know how to do it in 1 min.

It was all fine until external stylesheets have been deprecated. Isn't there any way to bring them back? External stylesheets, in pure, simple, CSS still looked like the most natural and logical way to go about it. Produce your CSS however you want, then just tell Polymer where it is.

Please get this fixed asap and get it done right. It's making my UX with Polymer a nightmare. Besides, it needs to be a stable feature: it can't be chaged every often, or it will keep breaking existing code.

@homertherefore
Copy link

Essentially this issue #2429 is asking us to find hacky ways to now generate our preprocessor CSS and output the results inside HTML to tie into our component, when the current implementation is reasonable and a natural way of development, keeping CSS in a CSS file.

Forcing things like CSS to only be usable by components inside HTML seems like a poor decision. CSS preprocessors aren't going away, they are vital and very powerful through module/plugins to enhance and allow developers to write less & do more. Added with wanting to generate style guides from CSS source files commenting (kss for example), it is quite a severe disadvantage embedding it in HTML.

The only single limitation in external files at the moment is being able to use CSS vars which are readily available inside a Polymer component. Yet, this is still a benefit in my opinion, as I can focus on my styling in the external file, while leverage the style block in the component to define where/what is exposed in vars/mixins that can be overridden, keeping a meaningful level of abstraction.*

  • Edited: In testing, it seems sass already allows these to go through (I'm using sass/compass), and it just ignores the var(...) & @apply(...) statements in your styles, while still overridable within a component making use of it. The only limitation being the override exists inside the parent component. @pensierinmusica thanks for the suggestions. 👍

@pensierinmusica
Copy link

@homertherefore as you can probably imagine from my previous post I couldn't agree more :)

Btw, in my experience there are already viable ways to use CSS vars in external files, take a look at cssnext, and postcss-custom-properties (to be used in comination with gulp-postcss). Hope this helps!

As for the rest, looking forward to hear some feedback from the Polymer team (in particular @ebidel and @addyosmani). Cheers!

@ghost
Copy link

ghost commented Sep 18, 2015

I'm inclined to agree with the previous comments. I don't really see an advantage to limiting developers/component designers to one (and that) way of including styles, when the external option seemed to be working just fine.

I'd also love to hear the reasoning that went into this decision. Perhaps there are problems inherent with the external stylesheets that I'm not aware of, but I can't see any real reason to exclude that option from where I sit.

@arthurevans
Copy link

To clarify: <link rel="import" type="css"> is deprecated, not removed. And we're planning to deliver a tool to wrap stylesheets. I'd be very surprised indeed if we removed the previous solution before we delivered a tool.

To answer the previous questions, this was deprecated because the HTML Imports spec declares that imported documents are parsed as HTML, which caused issues with the type="css" solution:

"This allows a file to contain pure css text like a stylesheet file, but it causes the file to parse as HTML which has too many negative side effects: possible security concern, performance issue, and generates warning message in chrome." (see: #2198)

If you're wondering why <link rel="stylesheet"> and @import are out, it's because they're handled natively by the browser: there's no way for Polymer to shim the styles before they're loaded. (see #2367, #2300)

I know it's an unwelcome change to many, but hopefully that helps explain the current status.

@homertherefore
Copy link

@arthurevans Thank you for providing some clarity. Security and performance concerns are a very valid reason to consider another opinion without a doubt.

It is understandable with everything still largely flagged experimental that things have a chance to be deprecated, but seeing a useful feature deprecated shows it can't be banked on sticking around for long. And if there's a better approach, rightly so.

A method of style loading was viable from @ebidel's article on HTML imports, though the spec may of chanced since, which shows we're allowed to import CSS files normally outside of the component dom-module/template declaration.

Taking that concept, and how Polymer is using the syntax suggested on the styling module docs, could both concepts be used to handle external file that are contextually aware of the component?

<link id="comp-style" rel="stylesheet" href="style.css">
<dom-module>
  <template>
    <style is="custom-style" include="comp-style"></style>
  </template>
</dom-module>

If it is possible, this could allow us to still generate our external files by any means, and hopefully a way for Polymer to access the resource more safely/efficiently. It also avoids the need for extra tools to meet devs needs.

@arthurevans
Copy link

@homertherefore I defer to @sorvell & @ebidel here, but I think @ebidel's article shows loading standard CSS rules in an import using a regular <style> tag or <link> tag, separate from Polymer. That's not a problem.

The problem with what you propose is that as soon as the browser hits the <link rel="stylesheet">, it downloads the stylesheet, parses the styles, and injects them into the document head. So they may already affect the display of the document before Polymer can do anything about them.

The problem is that to shim the rules for shady DOM, Polymer needs to load the CSS rules in a way that prevents the browser from parsing them as CSS.

When all browsers have native shadow DOM, the requirement to shim the styles goes away, and we can use standard <link rel="stylesheet"> tags.

@drarmstr
Copy link

I hope a better solution can be found. Requiring an extra tool can be problematic for those with more limited/rigid tool-chain requirements...

Perhaps some other tag could be used here and then have the shim do it's own de-duping and AJAX request instead of relying on a built-in browser download mechanism? Anyway you look at it, this current solution likely won't match the eventual native browser implementation...

@panuhorsmalahti
Copy link

Re: CSS variables in external files. This already works with LESS out of the box.

my-style-component.less, (compiled to identical .css file)

:host {
    --my-color: #009cd9;
}

Then I can simply import the styles to another component:

<link rel="import" href="../../components/my-style-component/my-style-component.html"/>
<dom-module id="my-component">
<link rel="import", type="css", href="../../components/my-component/my-component.css"/>
<template>
<style include="my-style-component"></style>
</template>
</dom-module>

and finally using the CSS variable in another component's less file, my-component.less:

.application {
    color: var(--my-color);
}

@MaKleSoft
Copy link

So I've created a gulp plugin that wraps css files into style modules. You can use it with regular css files or stick it between your favourite preprocessor and gulp.dest:

var stylemod = require('gulp-style-modules');

// Wrap css files
gulp.src("./src/**/*.css")
    .pipe(stylemod())
    .pipe(gulp.dest("./src"));

// Use with preprocessor (e.g. stylus)
gulp.src("./src/**/*.styl")
    .pipe(stylus({use: [nib()]}))
    .pipe(stylemod())
    .pipe(gulp.dest("./src"));
}

Hope this makes things easier for some people.

@ebidel
Copy link
Contributor Author

ebidel commented Nov 5, 2015

We also recently created a web service that does the wrapping if you don't want a build tool.

Polystyle: https://poly-style.appspot.com/demo/

Produces CORS enabled dom style modules from an external stylesheet.

@pensierinmusica
Copy link

Proposal to @ebidel and @arthurevans: since we're in Polymer, why don't we simply create an element for this specific purpose?

Example:

<link rel="import" href="/../bower_components/polymer/polymer.html">

<dom-module id="my-element">

  <dom-css url="postcss/my-element.css"></dom-css>

  <template>

    <!-- All the HTML goes here -->

  </template>

  <script>
    Polymer({is: "my-element"});
  </script>

</dom-module>

I named it dom-css but whatever you think makes more sense is fine. Wouldn't this be much easier and more linear to work with?

It would easily allow to include external stylesheets and satisfy the requirement that @arthurevans mentioned in #2429 (comment).

Then for deploy the vulcanize process could take care of everything and merge files as necessary to optimize loading time.

Looking forward to hear your thoughts, cheers!

@MaKleSoft
Copy link

@ebidel Looks interesting! But just off the top of my head I can think of a bunch of reasons why this will not be feasible me (and probably a lot of other users):

  • Security (Piping my css through a third-party server? Nope.)
  • Integrity (No way of knowing if the service breaks my styles at some point without me doing anything).
  • Reliability (Service uptime?)
  • Performance (Caching might still work, but using CDNs ist probably out of the question with this approach)
  • Offline availability (I distribute most of my apps as downloadable packages (Cordova, Chrome Web apps etc, but even for hosted apps I can usually work on my app without an internet connection. Not with this approach)

Does vulcanize still work with this? If so, that would solve at least some of these issues. Still, since I use gulp in my workflow anyway, just adding a step to my build process is by far the simplest solution for me right now. Looking forward to seeing what you guys come up with though!

@ebidel
Copy link
Contributor Author

ebidel commented Nov 5, 2015

@pensierinmusica there really should be and it's what the old deprecated way was essentially doing. dom-css would theoretically just run the style shimmer.

@MaKleSoft agreed. This isn't for everyone, but a lot of people are lazy and/or don't love build steps.

  • Readability: it's on GAE. This couldn't be an issue.
  • Integrity: should be no issue. It's just a full insertion, as is
  • Fetched stylesheets are cached when they're used in the system
  • offline avail - yea...nothing can be done here. A tradeoff of using this convenience.

AFAIK, vulcanize doesnt work with external resources, so this wouldn't work well wit it

@pensierinmusica
Copy link

@ebidel cool, is the Polymer team going to create this element and add it to the catalogue?

As for the vulcanization process, if I understand correctly, it would be enough to make sure that the url parameter represents the relative path to the CSS file respective to where the HTML custom element is located. This way vulcanize can substitute any <dom-css> elements with a direct inlining of the CSS inside the <template> tag.

Looking forward to hear your thoughts!

Custom element with <dom-css>

<link rel="import" href="/../bower_components/polymer/polymer.html">

<dom-module id="my-element">

  <dom-css url="postcss/my-element.css"></dom-css>

  <template>

    <!-- HTML goes here -->

  </template>

  <script>
    Polymer({is: "my-element"});
  </script>

</dom-module>

Final "vulcanized" version

<link rel="import" href="/../bower_components/polymer/polymer.html">

<dom-module id="my-element">

  <template>

    <style>

      /* Custom styling goes here */

    </style>

    <!-- HTML goes here -->

  </template>

  <script>
    Polymer({is: "my-element"});
  </script>

</dom-module>

@madeleineostoja
Copy link

Another option is to use cheerio or similar to parse and preprocess inline styles in a buildstep. Here's an example I found for postcss (forked from gulp-postcss) - https://github.com/StartPolymer/gulp-html-postcss. But yeah agree with all the above - a best practices/official tool to deal with this would be great.

@ebidel
Copy link
Contributor Author

ebidel commented Nov 19, 2015

No plans on an an element that that I'm aware of. I've had a lot of
luck with the gulp plugin mentioned above.

On Thu, Nov 19, 2015, 12:05 AM Sean King notifications@github.com wrote:

Another option is to use cheerio or similar to parse and preprocess inline
styles in a buildstep. Here's the example I found for postcss (forked from
gulp-postcss) - https://github.com/StartPolymer/gulp-html-postcss. But
yeah agree with all the above - a best practices/official tool to deal with
this would be great.


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

@pensierinmusica
Copy link

@ebidel imho an offcial Polymer element would be very convenient to use. Also @arthurevans what do you think about the proposal above? #2429 (comment)

Cheers!

@ebidel
Copy link
Contributor Author

ebidel commented Nov 21, 2015

Does vulcanize already handle the case of inlining a <link rel="import" type="css"> resource with the --inline-css flag?

@Jamtis
Copy link

Jamtis commented Dec 13, 2015

Related to less/less.js#2715.

@ebidel
Copy link
Contributor Author

ebidel commented Dec 21, 2015

Based on the two options in this bug, I think we should close:

@MaKleSoft
Copy link

@ebidel The gulp plugin solves the problem completely for my use case so I'm ok with closing this issue.

@ebidel
Copy link
Contributor Author

ebidel commented Dec 21, 2015

love community tools :)

@ebidel ebidel closed this as completed Dec 21, 2015
@pensierinmusica
Copy link

Imho Polymer should provide native support for external stylesheets.

#2429 (comment)

@madeleineostoja
Copy link

For anyone still following this, put together a little gulp plugin that lets you process chunks of HTML inline - gulp-process-inline. So you could just write your Sass/PostCSS/whatever in <style> tags/module and pass it through this + gulp-sass/etc.

@pensierinmusica
Copy link

Thanks @seaneking :)

@pensierinmusica
Copy link

@ebidel and @arthurevans, considering that HTTP/2 is getting more and more adopted, vulcanization soon won't be necessary anymore. Then, once shadow DOM is available in all browsers, we should be able to directly use external stylesheets with <link rel="stylesheet">. Correct? Cheers

@Jamtis
Copy link

Jamtis commented May 8, 2016

I understand the securtiy concerns @arthurevans mentioned but (to me) this is really inconvenient, almost disturbing.
The way to the future web doesn't lay in the mile-long pipelines of gulp!
Ok, once every browser I want to adress supports ShadowDom I am comfortable. But until then I am forced to add yet another build step, I almost feel like coding in C/Java.
That's not the web I want to use and foster.
So far about my opinion on the decision from the polymer team.

Enough complaining, if I understood the problem correctly the stylesheet has to be fetched without affecting the layout of the site, so it can be parsed by Polymer.
How about XHR, it's async and content independent?

Finally, @arthurevans said that the external stylesheets are deprecated not removed.
Question is when will they be removed, I hope AFTER all browsers support ShadowDOM.

@pensierinmusica
Copy link

@Jamtis +1

@equinusocio
Copy link

equinusocio commented Aug 17, 2017

And what if we use webpack instead of gulp?!

@MeTaNoV
Copy link

MeTaNoV commented Sep 28, 2017

@equinusocio good question, I have the same issue!

@MeTaNoV
Copy link

MeTaNoV commented Sep 28, 2017

@equinusocio , found out that webpack-polymer-loader has an option for it called processStyleLinks, that you can use then in conjunction with the css-loader.

@ronalson
Copy link

Is there an official updated regarding the tool to wrap stylesheets mentioned above? Or a more streamlined process for get through the problems discussed on this issue?

I'm just starting on polymer and I would like to understanding whats the best approach for this kind of workflow - writing scss/css and importing it on each component.

I understand how the loader mentioned by @MeTaNoV can help. However, as the <link rel="stylesheet" href="file1.css"> is deprecated, feels counterproductive to adopt this syntax on new components (specially with upcoming 3.0 release).

@equinusocio
Copy link

equinusocio commented Feb 15, 2018

@ronalson Check Polymer Skeleton. It is the most advanced starter kit based on polymer 3 and postcss (but you can use less, sass or css). Using webpack you can import the style inside each component like that:

import css from './style.pcss';
import template from './template.html';

export default class SkButton extends PolymerElement {
  static get template() {
    return html([`<style>${css}</style> ${template}`]);
  }
}

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