Problems with styling of javascript component

Hi Guys,

I’m kind of new to these Polymer Elements, but i’m trying to incorporate a NPM javascript component (leaflet.js) which has an included CSS file that needs to be included before loading the JS.

Initially, I thought the CSS was not being loaded at all, but I can see that via my @StyleSheet annotation it is indeed showing up in the part of the page.

However, when I load the javascript, no styling is being applied.

I’m not sure if this is shadow dom weirdness or if I am missing something simple.

MapView (Server Side Component)

@Tag("map-view")
@Route("mapview")
@JsModule("./src/views/dashboard/map-view.js")
@StyleSheet(value = "https://unpkg.com/leaflet@1.6.0/dist/leaflet.css")
class MapView extends PolymerTemplate<MapView.MapViewModel> {
    Logger log = LoggerFactory.getLogger(this.getClass());

    public MapView(){

    }

    public static interface MapViewModel extends TemplateModel {
        // Add setters and getters for template properties here.
    }
}

map-view.js

import {html, PolymerElement} from '@polymer/polymer/polymer-element.js';

class MapView extends PolymerElement {

    static get template() {
        return html`
<style include="shared-styles">
                :host {
                    display: block;
                }
            </style>
<h3>Map View</h3>
<dom-module id="map-dom-view">
<div id="mapid" style="width: 100%; height: 500px;"></div>
<vaadin-button on-click="loadLeaflet">Load</vaadin-button>
</dom-module>
`;
    }

    static get is() {
        return 'map-view';
    }

    static get properties() {
        return {
            // Declare your properties here.
        };
    }

    ready(){
        super.ready();
        console.log("Ready");
    }

    connectedCallback() {
        super.connectedCallback()
        console.log("Connected Callback");
    }

    loadLeaflet(){
        import('leaflet/dist/Leaflet.js').then((leafletModule) => {
            // leaflet is now imported
            var mymap = L.map(this.$.mapid).setView([51.505, -0.09]
, 13);
        });
    }

}

customElements.define(MapView.is, MapView);

There’s no errors in the console - everything looks like it’s loading up OK.

I am working to replicate the quick start: https://leafletjs.com/examples/quick-start/

Running vaadin 14.1.1

So if I copy the CSS manually into the shared-styles of the shadow DOM, the CSS loads.

Is there a way to be able to link these in from a URL? or from the node modules itself?

Have you tried @CssImport(value = "https://unpkg.com/leaflet@1.6.0/dist/leaflet.css", themeFor = "map-view")? this will add the css into the shadow dom shared-styles.

I haven’t used @CssImport for an external css file but I think it should work? If not, you could download the leaflet css into the frontend folder and import it from there.

Amazing Kaspar - this works!

I can’t use it for external CSS, but that’s OK, I can link to the version in node_modules.

Oh actually, no this doesn’t work.

I thought CSS was loading because I had a tile layer on. But using @CssImport still doesn’t import the CSS. I need to manually include it in my .js file in the block for it to work.

Yeah this doesn’t seem to be working at all. Having the same issue with font-awesome icons not working inside the shadow dom.

I’m having to load all CSS into the block of the element to get any styling at all - I must be missing something here because somehow the vaadin styling comes into the shadow dom

Yeah this doesn’t seem to be working at all. Having the same issue with font-awesome icons not working inside the shadow dom.

I’m having to load all CSS into the style block of the element to get any styling at all - I must be missing something here because somehow the vaadin styling comes into the shadow dom

Any updates? I have the same problem.

I had found a workaround for this which is adding the polymer component to the DOM rather than the shadow DOM, that way global css added via @CssImport gets applied to the polymer component. Example code can be found in the comment in this post.
https://vaadin.com/forum/thread/17875021/npm-module-css-file-failed-to-load-for-dhtmlx-gantt

But it’s a workaround and not the actual solution, i’m trying to use a <dom-repeat items ="list"> element in the polymer template when using this workaround and i get a
Cannot read property 'querySelector' of undefined error

Which is probably because the dom repeater uses the shadow dom, which doesn’t exist with the workaround.

Are you using the [:host]
(https://developer.mozilla.org/en-US/docs/Web/CSS/:host()) Syntax for the shadow DOM css selectors?

Nope I am not. Where should this be used?

It is explained [here]
(https://github.com/vaadin/vaadin-themable-mixin#readme). A better tutorial about styling in general but also about shadow dom styling has been promised to come very soon.

Thank you for the link.

But it looks awfully complicated, i just want to assign a css file that the shadow DOM uses for an external javascript library which i have integrated in using polymer component. Isn’t there a simple way to just define the css file to use?

Unfortunately, it doesn’t seem to work like that Nissim. The whole point of polymer components is they render their own shadow DOM and styles have rules around what is allowed to affect the display of the elements in the shadow DOM. They are designed to be independent.

So yes, it is complex, and if you’re going to use polymer views that’s just the way it is by the looks of it.

I’ve just spent a ton of time getting the vaadin login views to look right because they do behave the same way.

Aha I see, thanks for the answer Ben.

For any one else who had the same problem. There is a workaround, it probably has it’s drawbacks but it can be done.

Integration of external javascript libraries can be done without the shadow DOM like I have mentioned here in this [post]
(https://vaadin.com/forum/thread/17875021/npm-module-css-file-failed-to-load-for-dhtmlx-gantt)

This way you can add CSS for the javascript library to the global scope and then attach the polymer template directly to the DOM instead of shadow DOM. That way the css will get applied to your polymer template.