lit / lit-element

LEGACY REPO. This repository is for maintenance of the legacy LitElement library. The LitElement base class is now part of the Lit library, which is developed in the lit monorepo.
https://lit-element.polymer-project.org
BSD 3-Clause "New" or "Revised" License
4.49k stars 318 forks source link

Allow `URL` instances in `css` template tag #1117

Closed hsablonniere closed 3 years ago

hsablonniere commented 3 years ago

Hello team!

The context

Like many other users of LitElement, I'm trying to avoid bundler specific config and ES import syntax to refer to the URL of assets like SVG images. This means, I don't do this:

import checkSvgUrl from '../assets/check.svg';

but I do this:

const checkSvgUrl = new URL('../assets/check.svg', import.meta.url).href;

With this technique, my code works "as is" in any modern browsers without any bundler. I can easily use this in a lit-html template:

render() {
  return html`<img src=${checkSvgUrl}>`
}

The "limitation"

If I want to use this URL in CSS, I need to use unsafeCss like this:

static get styles () {
  return css`
    .foo {
      background-image: ${unsafeCss(checkSvgUrl)}
    }
  `
}

The proposition

As we can see here, LitElement css template tag allows instances of CSSResult and type Number: https://github.com/Polymer/lit-element/blob/master/src/lib/css-tag.ts#L68-L79

I was wondering if we could also allow instances of URL? This way, we could do this:

const checkSvgUrl = new URL('../assets/check.svg', import.meta.url);
// ...
static get styles () {
  return css`
    .foo {
      background-image: ${checkSvgUrl}
    }
  `
}

NOTE: This time, the checkSvgUrl is not the href string but a real instance of URL.

I think it could improve DX with just a few more characters in the source code and it would maybe push users towards this new URL pattern instead of relying on bundler configs and non standard import syntax for assets.

WDYT?

justinfagnani commented 3 years ago

In CSS URLs are the most unsafe thing you can feed untrusted strings to. It's why we disallow arbitrary strings in the first place.

unsafeCSS is the signal that the source of the URL is trusted, so that's really the right way handle this. We could also integrate Trusted Types here so that we allow TrustedHTML values. That would still require wrapping a URL, but it would be a standard wrapper at that point.

hsablonniere commented 3 years ago

Fair enough 😉

sorvell commented 3 years ago

Closing based on https://github.com/Polymer/lit-element/issues/1117#issuecomment-738250603.