Temporary Styling for ViewModels (without injecting into head)

On our larger aurelia applications where there are many routed views, we were running into issues with some conflicts with CSS styles. They were coming from the <require from="style.css" /> in our ViewModels because once loaded, the stay in the head. To mitigate this, I either write the css inline at the top of the template or create a separate view that contains all the css. You can even set the set a build rule to rewrite your sass inside an HTML view if there was need to do so.

Inline Example

<template>
<style>
    .my-style { color:blue }
</style>
<div class="my-style">bla bla</div>
</template>

or using compose…

Style File (my-style.html)

<template>
<style>
    .my-style { color:blue }
</style>
</template>

ViewModel

<template>
<compose view="./my-style.html"></compose>
<div class="my-style">bla bla</div>
</template>

I’m not sure a feature is in the timeline to remove any view loaded css files from the head after routing away but would be a nice to have. Until then, the aforementioned works well for us.

3 Likes

I’m running into the same issues. I don’t like inline styles, so what I’m doing is creating a css file for each custom element I have. And trying to prefix the css class with the name of the custom element.

.my-custom-element-name__class-name

And for specific cases the css is reusable I put in a common css file.

I know that there is an option to <require from="" as="scoped"> but currently just firefox supports it. Once all browsers supports it, it will inject the css on the element, instead of the head.

1 Like

There was a recent fix around scoped CSS in the October release https://github.com/aurelia/templating-resources/issues/304. Not sure if this addresses the issue for browsers other than Firefox.

1 Like

That’s interesting. It worked on chrome, have to test in other browsers.

steps:

  1. On the html file use:
    <require from="./your-component-style.css" as="scoped"></require>

  2. On the js file
    import {useShadowDOM} from 'aurelia-framework'; and use the decorator @useShadowDOM

If you inspect the component, the style will be injected inside the component, not on global scope.

2 Likes

Nice, great to hear that this is working in Chrome now!

Thanks much for that info. I’ll have to make sure I have that version and try that out. That will save some work on my part.

1 Like

I could not get it to work in my version of Chrome (v61) however it worked fine in Firefox. The strange thing is that my version of Chrome (v61) is supposed to support scope but <require from="./test.scss" as="scoped"></require> is not working in Chrome, or IE 11. Let me be more clear, by not working I mean that when I use @useShadowDOM decorator in the viewmodel, I can see the tag injected into the view but then my view doesn’t render properly, as if some of the lifecycle methods just don’t fire.

The scoped seems to work only with the useShadowDOM, it has some pros and cons.

On one hand the shadow dom don’t allow the css injected to leak out, on the other hand it also avoids css to leak in (which I particulary consider as a issue)

In my pov it should use the shadow dom injected scoped to override only the parts of the global that are the same.

1 Like

I thought the shadow-piercing descendant combinator helped with that?

3 Likes

It does, but if you are using third party components or dependencies it may be an issue.

2 Likes

So it may not work with third party since there styles are loaded globally and are not accessible via scope?

1 Like

Here is a plugin to load/unload styles when they are needed: https://github.com/jbockle/aurelia-useable-style-loader

4 Likes