question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Missing button icons: @font-face does not work in shadow dom / LitElement

See original GitHub issue

Reduced Test Case

“not reproducible with a link”

I don’t know how to do a webpack example with codepen or jsfiddle and provide some snippets instead from my reduced test case.

package.json

  "scripts": {
    "start": "webpack-dev-server --open"
  },
  "devDependencies": {
    "css-loader": "^4.3.0",
    "webpack": "^4.44.2",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "@fullcalendar/core": "^5.3.1",
    "@fullcalendar/daygrid": "^5.3.2",
    "lit-element": "^2.4.0"
  }

webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
    },
    devtool: 'inline-source-map',
    devServer: {
        contentBase: './dist',
    },
    module: {
        rules: [
            {
                test: /\.css$/i,
                use: [
                    'css-loader'
                ]
            },
        ],
    },
};
import {LitElement, html, css, unsafeCSS} from 'lit-element';
import {Calendar} from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';

import commonStyles from '@fullcalendar/common/main.css';
import dayGridStyles from '@fullcalendar/daygrid/main.css';

export class AppRoot extends LitElement {

    firstUpdated(_changedProperties) {
        super.firstUpdated(_changedProperties);

        const calendarEl = this.shadowRoot.getElementById('calendar');
        const calendar = new Calendar(calendarEl, {
            plugins: [dayGridPlugin],
        });

        calendar.render();
    }

    static get styles() {
        return [
            unsafeCSS(commonStyles),
            unsafeCSS(dayGridStyles),
            css`
                #calendar {
                    width: 50%;
                }
            `
        ];
    }

    render() {
        return html`
            <div id="calendar"></div>
       `;
    }
}

customElements.define("app-root", AppRoot);

index.html

<!doctype html>
<html>
<head>
    <script src="./main.js" type="module"></script>
</head>
<body>
    <app-root></app-root>
</body>
</html>

Bug Description

I expect to see button icons.

Chrome shows nothing, Firefox shows squares with the unicode point.

I suspect there’s something wrong with loading the @font-face or applying the css. When inspecting the shadow dom element, I can find the @font-face in the styleSheets collection.

Screenshots

Bildschirmfoto von 2020-10-06 14-15-53

What if tried so far

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:8

github_iconTop GitHub Comments

2reactions
mlaruecommented, Oct 7, 2020

You can also copy the “@font-face” from shadow dom (after adding commonStyles) to the outer scope:

...
        render(template, shadowRoot);

        [...shadowRoot.styleSheets]
            .flatMap(styleSheet => [...styleSheet.cssRules])
            .filter(rule => rule.constructor === CSSFontFaceRule)
            .map(rule => {
                const element = document.createElement("style");
                element.append(rule.cssText);
                this.appendChild(element);
            });
...

But still hacky…

(This works also with LitElement when added to firstUpdated().)

1reaction
mlaruecommented, Oct 7, 2020

Now this works also:

import {render, html} from 'lit-html';

import { Calendar } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';

import commonStyles from '@fullcalendar/common/main.css';
import dayGridStyles from '@fullcalendar/daygrid/main.css';

export class AppRoot extends HTMLElement {

    connectedCallback() {
        const shadowRoot = this.attachShadow({mode: 'open'});

        const fontStyle = html`
            <style>
                @font-face {
                  font-family: 'fcicons';
                  src: url("data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALA...AAAAAAAAA=") format('truetype');
                  font-weight: normal;
                  font-style: normal;
                }            
            </style>
        `;
        render(fontStyle, this);

        const template = html`
            <style>${commonStyles}</style>
            <style>${dayGridStyles}</style>
            <style>
                #calendar {
                    width: 50%;
                }
            </style>
            <div id="calendar"></div>
        `;

        render(template, shadowRoot);

        const calendarEl = shadowRoot.getElementById('calendar');
        const calendar = new Calendar(calendarEl, {
            plugins: [dayGridPlugin],
        });

        calendar.render();
    }

}

customElements.define("app-root", AppRoot);

(shortened data url for better visibility)

Read more comments on GitHub >

github_iconTop Results From Across the Web

@font-face doesn't work in Shadow DOM - Rob Dodson
A workaround is to pull your @font-face rules out of the stylesheet for your element, and move them to the top of your...
Read more >
Icon Fonts in Shadow DOM - Stack Overflow
A random example. Sidenote: @font-face does not bleed into shadow. It's the directive setting the relation between fontname and the file where ...
Read more >
How to Create a LitElement Web Component — Heart/Unheart
Web components make use of custom elements and shadow DOM, the :host selector in CSS is targeting the shadow host of the custom...
Read more >
Encapsulating Style and Structure with Shadow DOM
Now that our element has a shadow DOM attached, there is no outlet for the light DOM to render. Let's start fixing these...
Read more >
GSAP target not found with LitElement - GreenSock
All in all, as far as the code goes, the below class DOES work with the exception of GSAP not being able to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found