Hi,
while upgrading from 9.1.1
and 9.2.3
to 9.3.1
we're experiencing a regression in the angular frontend regarding the order of style injections. It seems that previously the injection order was preserved / similar to the one declared in angular.json
which is good because we want to override some variables and styles from the lepton-x theme. This is no longer possible because the style injector is always injecting the lepton styles after the ones provided by angular.
Question 1)
Do you know how I can load my style at the very bottom? Do I need to provide my own Style Load Factory / LPX_PRO_STYLE_TOKEN
or LPX_LAYOUT_STYLE_FINAL
or LPX_STYLE_FINAL
?
Question 2) Is this something you're planning to fix? Because in the code I've seen this comment
const linkElem = this.createLinkElem(style, direction, resolve);
//TODO: find a better way for understand style laaded by angular json
const appStyles = document.querySelector(
'link[rel="stylesheet"][href*="styles"]'
);
Which leads me to think that this could be improved.
Kind Regards, Marc
11 Answer(s)
-
0
In ABP 9.3.x, the LeptonX theme and style injection mechanism for Angular was updated, and the order of style injection may no longer match the order in
angular.json
. This can affect your ability to override LeptonX theme variables/styles with your own styles.To ensure your custom styles are loaded after the LeptonX theme, you should inject your override styles dynamically at runtime, or use higher CSS specificity or
!important
as a workaround. The current ABP LeptonX style loader does not provide a built-in configuration to guarantee your styles are injected last viaangular.json
order.You do not need to provide your own
LPX_PRO_STYLE_TOKEN
,LPX_LAYOUT_STYLE_FINAL
, orLPX_STYLE_FINAL
unless you want to fully customize the style loading process. The current loader does not expose a public API for reordering, but you can create a custom provider to control style injection order if necessary.The ABP team is aware of the limitation, as indicated by the
//TODO
comment in the code. However, there is no official fix or configuration for this in 9.3.x. You can follow the official LeptonX theme documentation and community article for best practices and updates:- To override LeptonX theme variables, add your custom CSS to
styles.scss
and use CSS variables as shown below:
- To override LeptonX theme variables, add your custom CSS to
:root { --lpx-logo: url('/assets/images/logo.png'); --lpx-logo-icon: url('/assets/images/logo-icon.png'); --lpx-brand: #edae53; }
If you need to guarantee order, inject your custom style sheet dynamically after the app starts, or use a workaround like importing your CSS at the end of the main style file.
This is a known area for improvement, and you can track updates or provide feedback via the official channels.
Sources:
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
-
0
Hi,
I didn't really get an answer for this topic before it was auto-closed. Could you have another look into this, or give me some feedback on what the right approach would be on providing global styling, that can override LeptonX Themes?
Kind Regards, Marc
-
0
Hi,
I didn't really get an answer for this topic before it was auto-closed. Could you have another look into this, or give me some feedback on what the right approach would be on providing global styling, that can override LeptonX Themes?
Kind Regards, Marc
Hello Marc,
The questions are automatically closed when we do not get interaction. Seeing that, we will be managing this issue internally. You can follow the process here https://github.com/abpframework/abp/releases
Until we publish the fix, you can extend the default service to override the related function.
import { DOCUMENT, inject, Injectable } from '@angular/core'; import { LPX_STYLE_FINAL, LpxStyle, StyleService } from '@volo/ngx-lepton-x.core'; @Injectable({ providedIn: 'root', }) export class MyStyleService extends StyleService { private myDocument = inject<Document>(DOCUMENT); constructor() { super(inject(LPX_STYLE_FINAL), inject(DOCUMENT)); } override loadStyle(style: LpxStyle, direction: 'ltr' | 'rtl'): Promise<HTMLStyleElement | void> { return new Promise(resolve => { const linkElement = this.createLinkElem(style, direction, resolve); const styleLinks = Array.from( this.myDocument.head.querySelectorAll('link[rel="stylesheet"]') ); const firstStyleLink = styleLinks[0]; if (firstStyleLink) { firstStyleLink.insertAdjacentElement('beforebegin', linkElement); } else { this.myDocument.head.appendChild(linkElement); } this.lastInjectedStyle = linkElement; resolve(linkElement); }); } }
Then, in your
app.config.ts
export const appConfig: ApplicationConfig = { providers: [ // ... { provide: StyleService, useClass: MyStyleService, }, ], };
You can let us know if you need further assistance. Thank you for your cooperation.
-
0
We have the same issue I think on the Lepton (non-X) theme... How would we resolve that?
-
0
-
0
Ours looks like this:
<link rel="stylesheet" href="lepton4.css"> <link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="ngx-datatable-index.css"> <link rel="stylesheet" href="ngx-datatable-icons.css"> <link rel="stylesheet" href="ngx-datatable-material.css"> <link rel="stylesheet" href="fontawesome-all.min.css"> <link rel="stylesheet" href="fontawesome-v4-shims.min.css">
And in production (with ABP 9.2) we have:
<link rel="stylesheet" href="lepton4-X4OK76EB.css"> <link rel="stylesheet" href="ngx-datatable-index-ALC7J2LN.css"> <link rel="stylesheet" href="ngx-datatable-icons-YZZVGCGU.css"> <link rel="stylesheet" href="ngx-datatable-material-QROZ42NV.css"> <link rel="stylesheet" href="fontawesome-all.min-V43YH5Q7.css"> <link rel="stylesheet" href="fontawesome-v4-shims.min-5GHJGPBV.css"> <link rel="stylesheet" href="styles-3O3IHLFY.css">
-
0
Hello,
I have tested the lepton theme to produce this. Here is my finding:
- If styles.css is present, your injected styles go before it.
- If not, your injected styles go at the end of
<head>
. - The sequence determines which styles take precedence (last loaded usually wins in CSS).
This logic ensures your custom styles are positioned relative to the main stylesheet, affecting which styles are applied or overridden.
You can also see it in the source code:
//theme-lepton/src/lib/providers/styles.provider.ts export function injectStyle(injector: Injector) { const rendererFactory = injector.get(RendererFactory2); const domInsertion = injector.get(DomInsertionService); rendererFactory .createRenderer(document.body, null) .addClass(document.body, 'abp-application-layout'); const appStyles: HTMLElement = document.querySelector('link[rel="stylesheet"][href*="styles"]'); let content: StyleContentStrategy; if (appStyles) { const domStrategy = DOM_STRATEGY.BeforeElement(appStyles); content = new StyleContentStrategy(styles, domStrategy, undefined, { id: LEPTON_STYLE_ELEMENT_ID, }); } else { content = CONTENT_STRATEGY.AppendStyleToHead(styles, { id: LEPTON_STYLE_ELEMENT_ID }); } domInsertion.insertContent(content); }
If you think that your version does not rely on this configuration, you can create a separate ticket and I can assist further in the thread. Thank you for your cooperation.
-
0
Thanks, I have created a new thread. https://abp.io/support/questions/9848/stylecss-loaded-in-wrong-order
-
0
I've fixed the issue now. We had a this in the
styles
array inangular.json
:"node_modules/@yaireo/tagify/dist/tagify.css",
after lepton4.css but before thengx-datable
one's.Moving it to the end, it worked
-
0
Thank you for the response. I am happy to hear that your problem has been solved. Is there anything I could assist besides?
-
0
Thanks, we're good. Have a nice day :)