diff --git a/src/runtime/components/css.ts b/src/runtime/components/css.ts index db121b2b..4cf2c471 100644 --- a/src/runtime/components/css.ts +++ b/src/runtime/components/css.ts @@ -7,6 +7,7 @@ import type { NuxtIconRuntimeOptions, NuxtIconRuntimeServerOptions } from '../.. import type { IconifyIconCustomizeCallback } from './shared' import { hash } from 'ohash' import { loadIcon, resolveCustomizeFn } from './shared' +import { insertIconStyle } from './style-order' import { useAppConfig, useNuxtApp, useHead, useRuntimeConfig, onServerPrefetch } from '#imports' // This should only be used in the client side @@ -139,11 +140,7 @@ export const NuxtIconCss = /* @__PURE__ */ defineComponent({ if (import.meta.dev) { style.dataset.nuxtIconDev = name } - const firstStyle = document.head.querySelector('style, link[rel="stylesheet"]') - if (firstStyle) - document.head.insertBefore(style, firstStyle) - else - document.head.appendChild(style) + insertIconStyle(style, document.head, options.cssLayer) selectors.add(iconSelector) } diff --git a/src/runtime/components/style-order.ts b/src/runtime/components/style-order.ts new file mode 100644 index 00000000..74e0de05 --- /dev/null +++ b/src/runtime/components/style-order.ts @@ -0,0 +1,12 @@ +export function insertIconStyle(style: HTMLStyleElement, head: HTMLHeadElement, cssLayer?: string) { + if (cssLayer) { + head.appendChild(style) + return + } + + const firstStyle = head.querySelector('style, link[rel="stylesheet"]') + if (firstStyle) + head.insertBefore(style, firstStyle) + else + head.appendChild(style) +} diff --git a/test/style-order.test.ts b/test/style-order.test.ts new file mode 100644 index 00000000..8e49a7a3 --- /dev/null +++ b/test/style-order.test.ts @@ -0,0 +1,35 @@ +import { Window } from 'happy-dom' +import { describe, expect, it } from 'vitest' +import { insertIconStyle } from '../src/runtime/components/style-order' + +describe('insertIconStyle', () => { + it('appends layered icon styles after existing stylesheets', () => { + const window = new Window() + const { document } = window + const appStyle = document.createElement('style') + const appLink = document.createElement('link') + appLink.rel = 'stylesheet' + document.head.append(appStyle, appLink) + + const iconStyle = document.createElement('style') + insertIconStyle(iconStyle as unknown as HTMLStyleElement, document.head as unknown as HTMLHeadElement, 'base') + + expect([...document.head.children]).toEqual([appStyle, appLink, iconStyle]) + window.happyDOM.abort() + }) + + it('keeps unlayered icon styles before existing stylesheets', () => { + const window = new Window() + const { document } = window + const appStyle = document.createElement('style') + const appLink = document.createElement('link') + appLink.rel = 'stylesheet' + document.head.append(appStyle, appLink) + + const iconStyle = document.createElement('style') + insertIconStyle(iconStyle as unknown as HTMLStyleElement, document.head as unknown as HTMLHeadElement) + + expect([...document.head.children]).toEqual([iconStyle, appStyle, appLink]) + window.happyDOM.abort() + }) +})