Repository: unocss/unocss (2025-07-21T14:26:04Z)

Issue:
When using presetWind4, set important: '#__nuxt', --un-text-opacity is undefined
### UnoCSS version

66.3

### Describe the bug

When using presetWind4({ important: '#__nuxt' })
if you set any font color, the following style will be generated in the console.
color: color-mix(in oklab, var(--colors-red-DEFAULT) var(--un-text-opacity), transparent) /* oklch(70.4% 0.191 22.216) */;
 --un-text-opacity is gray and it is undefined.

### Reproduction

https://unocss.dev/play/#version=66.3.3&html=DwCwjABAxgNghgZwQXgEQBcCmAPdBaAVmxgi1zwCdMATCAMwHsA7fAIwZmtQD4AoCCCAYBbTL2AB6cNyA&config=JYWwDg9gTgLgBAbzgEwKYDNgDtUGEJaYDmANHGFKgM6owDq2yALHAL5zpQQhwDkArlggBjKlV4AoCagAekWCgwBDfgBt4aTDnyFgRABQIJccpRowqALjgBtYydPVaDLM0P2HcUPJhKsMa14AYmECX2xUKF4SDzYAShiTAF0Y1jiJIA&css=PQKgBA6gTglgLgUzAYwK4Gc4HsC2YDCAyoWABYJQIA0YAhgHYAmYcUD6AZllDhWOqgAOg7nAB0YAGLcwCAB60cggDYIAXGBDAAUKDBi0mXGADe2sGC704AWgDuCGAHNScDQFYADJ4Dc5sAACtMLKAJ5gggCMLPK2ABR2pPBIcsoAlH4WAEa0yADWTlBYqEw2yFjK3Bpw5LxxAOTllVDoYpSMYgAs3vUZ2gC%2BmsBAA&options=N4IgLgTghgdgzgMwPYQLYAkyoDYgFwJTZwCmANCBCXAA5LwCWAbifocSQL5A

### System Info

_No response_

### Validations

- [x] Read the [Contributing Guidelines](https://github.com/unocss/unocss/blob/main/.github/CONTRIBUTING.md).
- [x] Check that there isn't [already an issue](https://github.com/unocss/unocss/issues) that reports the same bug to avoid creating a duplicate.
- [x] Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/unocss/unocss/discussions) or join our [Discord Chat Server](https://chat.antfu.me).
- [x] The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.


Discussion:

Patch:
diff --git a/packages-presets/preset-wind4/src/postprocess/important.ts b/packages-presets/preset-wind4/src/postprocess/important.ts
index 7f2042cc20..3628af929a 100644
--- a/packages-presets/preset-wind4/src/postprocess/important.ts
+++ b/packages-presets/preset-wind4/src/postprocess/important.ts
@@ -17,20 +17,21 @@ export function important({ important: option }: PresetWind4Options): Postproces
   }
 
   return [
-    option === true
-      ? (util) => {
-          // If the util is a property layer, we should not add `!important` to it
-          if (util.layer === 'properties')
-            return
+    (util) => {
+      // If the util is a property layer, we should not add `!important` to it
+      if (util.layer === 'properties')
+        return
 
-          util.entries.forEach((i) => {
-            if (i[1] != null && !String(i[1]).endsWith('!important'))
-              i[1] += ' !important'
-          })
-        }
-      : (util) => {
-          if (!util.selector.startsWith(option))
-            util.selector = `${option} ${wrapWithIs(util.selector)}`
-        },
+      if (option === true) {
+        util.entries.forEach((i) => {
+          if (i[1] != null && !String(i[1]).endsWith('!important'))
+            i[1] += ' !important'
+        })
+      }
+      else {
+        if (!util.selector.startsWith(option))
+          util.selector = `${option} ${wrapWithIs(util.selector)}`
+      }
+    },
   ]
 }


Test patch:
diff --git a/test/assets/output/preset-wind4-important-string.css b/test/assets/output/preset-wind4-important-string.css
new file mode 100644
index 0000000000..243758b563
--- /dev/null
+++ b/test/assets/output/preset-wind4-important-string.css
@@ -0,0 +1,20 @@
+/* layer: properties */
+@property --un-text-opacity{syntax:"<percentage>";inherits:false;initial-value:100%;}
+@property --un-bg-opacity{syntax:"<percentage>";inherits:false;initial-value:100%;}
+@property --un-scale-x{syntax:"*";inherits:false;initial-value:1;}
+@property --un-scale-y{syntax:"*";inherits:false;initial-value:1;}
+@property --un-scale-z{syntax:"*";inherits:false;initial-value:1;}
+/* layer: default */
+#app :is(.text-red){color:color-mix(in srgb, var(--colors-red-DEFAULT) var(--un-text-opacity), transparent);}
+#app :is(.text-opacity-50){--un-text-opacity:50%;}
+#app :is(.after\:m-4)::after{margin:calc(var(--spacing) * 4);}
+#app :is(.dark .dark\:bg-blue){background-color:color-mix(in srgb, var(--colors-blue-DEFAULT) var(--un-bg-opacity), transparent);}
+#app :is(.selection\:bg-yellow) *::selection,
+#app :is(.selection\:bg-yellow)::selection{background-color:color-mix(in srgb, var(--colors-yellow-DEFAULT) var(--un-bg-opacity), transparent);}
+#app :is(.important\:scale-100){--un-scale-x:100% !important;--un-scale-y:100% !important;scale:var(--un-scale-x) var(--un-scale-y) !important;}
+@supports (color: color-mix(in lab, red, red)){
+#app :is(.text-red){color:color-mix(in oklab, var(--colors-red-DEFAULT) var(--un-text-opacity), transparent);}
+#app :is(.dark .dark\:bg-blue){background-color:color-mix(in oklab, var(--colors-blue-DEFAULT) var(--un-bg-opacity), transparent);}
+#app :is(.selection\:bg-yellow) *::selection{background-color:color-mix(in oklab, var(--colors-yellow-DEFAULT) var(--un-bg-opacity), transparent);}
+#app :is(.selection\:bg-yellow)::selection{background-color:color-mix(in oklab, var(--colors-yellow-DEFAULT) var(--un-bg-opacity), transparent);}
+}
\ No newline at end of file
diff --git a/test/assets/output/preset-wind4-important-true.css b/test/assets/output/preset-wind4-important-true.css
new file mode 100644
index 0000000000..ecd2a6d501
--- /dev/null
+++ b/test/assets/output/preset-wind4-important-true.css
@@ -0,0 +1,15 @@
+/* layer: properties */
+@property --un-text-opacity{syntax:"<percentage>";inherits:false;initial-value:100%;}
+@property --un-bg-opacity{syntax:"<percentage>";inherits:false;initial-value:100%;}
+@property --un-scale-x{syntax:"*";inherits:false;initial-value:1;}
+@property --un-scale-y{syntax:"*";inherits:false;initial-value:1;}
+@property --un-scale-z{syntax:"*";inherits:false;initial-value:1;}
+/* layer: default */
+.text-red{color:color-mix(in srgb, var(--colors-red-DEFAULT) var(--un-text-opacity), transparent) !important;}
+.text-opacity-50{--un-text-opacity:50% !important;}
+.dark .dark\:bg-blue{background-color:color-mix(in srgb, var(--colors-blue-DEFAULT) var(--un-bg-opacity), transparent) !important;}
+.important\:scale-100{--un-scale-x:100% !important;--un-scale-y:100% !important;scale:var(--un-scale-x) var(--un-scale-y) !important;}
+@supports (color: color-mix(in lab, red, red)){
+.text-red{color:color-mix(in oklab, var(--colors-red-DEFAULT) var(--un-text-opacity), transparent) !important;}
+.dark .dark\:bg-blue{background-color:color-mix(in oklab, var(--colors-blue-DEFAULT) var(--un-bg-opacity), transparent) !important;}
+}
\ No newline at end of file
diff --git a/test/preset-wind4.test.ts b/test/preset-wind4.test.ts
index 2113f2076c..28069af0ec 100644
--- a/test/preset-wind4.test.ts
+++ b/test/preset-wind4.test.ts
@@ -469,3 +469,45 @@ describe('preset-wind4', () => {
     `)
   })
 })
+
+describe('important', () => {
+  it(`should add " !important" at the end when "true" unless it's already marked important`, async () => {
+    const uno = await createGenerator({
+      presets: [
+        presetWind4({
+          important: true,
+        }),
+      ],
+    })
+
+    const { css } = await uno.generate([
+      'text-opacity-50',
+      'text-red',
+      'important:scale-100',
+      'dark:bg-blue',
+    ].join(' '), { preflights: false })
+
+    await expect(css).toMatchFileSnapshot('./assets/output/preset-wind4-important-true.css')
+  })
+
+  it(`should prefix selector with provided important string and wrap the original selector in ":is()"`, async () => {
+    const uno = await createGenerator({
+      presets: [
+        presetWind4({
+          important: '#app',
+        }),
+      ],
+    })
+
+    const { css } = await uno.generate([
+      'text-opacity-50',
+      'text-red',
+      'important:scale-100',
+      'dark:bg-blue',
+      'after:m-4',
+      'selection:bg-yellow',
+    ].join(' '), { preflights: false })
+
+    await expect(css).toMatchFileSnapshot('./assets/output/preset-wind4-important-string.css')
+  })
+})