Skip to content

anoyomoose/inactive-unocss-preset-quasar

 
 

Repository files navigation

THIS PROJECT IS NOT ACTIVE

I played with it a bit, but did not achieve what I wanted. I'm just publishing it in case the original author of this project wants to pick up some of my changes.


unocss-preset-quasar

UnoCSS preset for Quasar Framework v2. Replaces Quasar's Sass-based CSS with UnoCSS, exposing all ~383 Quasar variables as CSS custom properties and supporting both Material Design 2 (standard Quasar look) and Material Design 3 styles.

Based on unocss-preset-quasar, but many changes were made to the MD2 preset. The author of the original package seems to be focusing on MD3, while I am first focusing on getting MD2 as identical to Quasar as possible. In that process, I have broken a significant portion of his MD3 work. Contrary to what the paragraph above here claims, Material Design 3 is in no way operational.

Installation

In your Quasar project:

#TODO this is for the original project, update

pnpm add unocss unocss-preset-quasar @iconify-json/mdi

Quick Start

1. Configure quasar.config.js

import UnoCSS from 'unocss/vite'
import { QuasarPreset, MaterialDesign2 } from 'unocss-preset-quasar'

export default defineConfig((ctx) => ({
  build: {
    extendViteConf(viteConf) {
      viteConf.plugins.push(
        UnoCSS({
          presets: [
            QuasarPreset({
              style: MaterialDesign2,
            })
          ]
        })
      )
    }
  }
}))

2. Strip Quasar's Sass import

Quasar's app-vite injects import 'quasar/dist/quasar.sass' into the entry point. Replace it with virtual:uno.css via a Vite plugin added to the same extendViteConf:

viteConf.plugins.push(
  {
    name: 'quasar-strip-sass',
    enforce: 'pre',
    transform(code, id) {
      if (code.includes("import 'quasar/dist/quasar.sass'")) {
        return code.replaceAll(
          "import 'quasar/dist/quasar.sass'",
          "import 'virtual:uno.css'"
        )
      }
    }
  },
  UnoCSS({ presets: [QuasarPreset({ style: MaterialDesign2 })] })
)

Variable Customization

Via Sass file (recommended)

The preset auto-discovers src/css/quasar.variables.scss (or .sass) in your project root. Any standard Quasar Sass variable overrides in that file are picked up automatically — no extra config needed.

// src/css/quasar.variables.scss
$primary: #ff0000;
$button-border-radius: 8px;

Via JS config

Pass overrides directly in quasar.config.js. Keys use camelCase versions of the Quasar Sass variable names (without the $ prefix):

QuasarPreset({
  style: MaterialDesign2,
  variables: {
    primary: '#ff0000',
    buttonBorderRadius: '8px',
    bodyFontSize: '16px',
  }
})

JS overrides take highest priority in the UnoCSS resolution pipeline (component shortcuts, --q-* CSS custom properties).

Sass bridge for <style lang="scss">

At startup the preset writes a generated Sass file to .quasar/unocss-resolved-variables.scss containing all resolved variable values — including any JS overrides. Import it at the top of your variables file to make those values available in <style lang="scss"> blocks:

// src/css/quasar.variables.scss
@import '../../.quasar/unocss-resolved-variables';

// Any $variable assignments below this line override the bridge values
// in <style lang="scss"> blocks (but NOT in UnoCSS output)
$primary: #ff0000;

The .quasar/ directory is already in .gitignore in standard Quasar projects (it is generated on every dev server start / build).

How the bridge works and where values come from

The bridge file contains the fully resolved values from all layers of the pipeline, including JS config overrides. When you import it at the top of your quasar.variables.scss, all those values become available as $variables in every <style lang="scss"> block in your project.

If you only use the Sass file (no JS config): Everything stays in sync automatically. The preset reads your Sass file, resolves the values, writes them to the bridge, and the Sass preprocessor uses the same file. UnoCSS output and <style lang="scss"> blocks see identical values.

If you only use JS config (no Sass file overrides below the import): The bridge file carries the JS values into <style lang="scss"> blocks if you've imported it as described above. Everything stays in sync.

If you set the same variable in both JS config AND your Sass file (below the import): They diverge. The bridge import sets the variable to the JS value, but your Sass assignment immediately overrides it. So:

  • UnoCSS output uses the JS value (JS wins in the resolution pipeline)
  • <style lang="scss"> blocks use your Sass file value (it comes after the bridge import, so it wins in Sass)

This only happens when the same variable has different values in both places. To keep things simple: override each variable in one place only.

Approach UnoCSS output <style lang="scss"> Recommendation
Sass file only Yes Yes Best for most projects
JS config only (with bridge import, no overrides below it) Yes Yes Good for config-driven setups
Both with same values Yes Yes Redundant but safe
Both with different values JS value Sass value Avoid — causes mismatch

CSS Custom Properties

All resolved variables are emitted as --q-* CSS custom properties on :root:

:root {
  --q-primary: #1976d2;
  --q-button-border-radius: 3px;
  --q-body-font-size: 14px;
  /* ... all ~383 variables */
}

These can be read in plain CSS (var(--q-primary)), overridden at runtime via JavaScript (document.documentElement.style.setProperty('--q-primary', '#f00')), or inspected in DevTools.


Material Design 3

Use MaterialDesign3 instead of MaterialDesign2:

import { QuasarPreset, MaterialDesign3 } from 'unocss-preset-quasar'

QuasarPreset({
  style: MaterialDesign3,
  sourceColor: '#806cb0',   // palette seed color
})

When MD3 palette generation is active, a full harmonized color scheme is derived from sourceColor. The resulting tokens are emitted alongside standard variables, prefixed with md3-:

:root {
  --q-md3-primary-container: #ecdcff;
  --q-md3-surface-variant: #e7e0ec;
  /* ... */
}

Do not override individual brand colors ($primary, $secondary, etc.) in your variables file when using MD3 palette mode — use sourceColor to control the entire palette instead.

To force palette generation on or off regardless of which style is active, use generateMd3Palette:

QuasarPreset({
  style: MaterialDesign2,
  sourceColor: '#806cb0',
  generateMd3Palette: true,   // force on even with MD2
})

TailWind

presetWind4 is included, so all Tailwind4 CSS compact utility classes are available - but in case of conflict, the Quasar definition wins.

Note that Quasar padding and margin classes are translated to Tailwind, which uses rem under the hood rather than px. The results are the same with Quasar default settings, but if you change for example the font size away from the default 16px, this can have an effect on these classes.


Variable Priority

Variables are resolved in the following order (later layers win):

1. Quasar built-in defaults
2. Style defaults (MD2 or MD3 can override Quasar defaults)
3. MD3 palette (if enabled, overrides brand colors)
4. User's quasar.variables.scss / .sass file
5. JS config (variables option) — highest priority

This resolution order applies to UnoCSS output (component CSS, --q-* custom properties). The resolved values are also written to the bridge file, so they flow into <style lang="scss"> blocks too — unless you override them again below the bridge import in your Sass file (see "How the bridge works" above).


API Reference

QuasarPreset(options)

Option Type Default Description
style QuasarStyle required MaterialDesign2 or MaterialDesign3
sourceColor string MD3 palette seed color (hex)
generateMd3Palette boolean | null style default Force MD3 palette on (true) or off (false); null/undefined defers to the style
variables Partial<QuasarVariables> JS variable overrides (highest priority); flows into <style lang="scss"> via the bridge file
variablesFile string | false auto-discover Path to Sass variables file, or false to disable auto-discovery
resolvedVariablesPath string .quasar/unocss-resolved-variables.scss Output path for the generated Sass bridge file
plugins (keyof QuasarPlugins)[] Quasar plugins whose classes to include in the safelist
iconSet QuasarIconSet Icon set
presetWebFonts WebFontsOptions Roboto via Bunny Fonts Web fonts config passed to @unocss/preset-web-fonts

Exports

import { QuasarPreset, MaterialDesign2, MaterialDesign3 } from 'unocss-preset-quasar'
import { type QuasarStyle } from 'unocss-preset-quasar/styles'
import { type QuasarTheme } from 'unocss-preset-quasar/theme'

Architecture Notes

  • Base preset: presetWind4() (Tailwind Wind v3 compatible) provides utility classes.
  • Shortcuts: Regex patterns that match Quasar class names (q-btn, q-card, etc.) and expand to UnoCSS utility strings. Component files each export shortcuts and optionally preflights for raw CSS.
  • Preflights: Raw CSS injected for things that cannot be expressed as utilities (keyframes, complex selectors, repeating-linear-gradient).
  • Safelist: Classes that UnoCSS must always generate, even when not found in scanned templates. Required for dynamically-added classes (ripple, color modifiers, transitions).
  • CSS Layers: components (-1) → default (1) → utilities (2). Root-level layout defaults use layer-components: so utility classes always win.

Development

git clone https://github.com/simsustech/unocss-preset-quasar.git
cd unocss-preset-quasar
pnpm i
pnpm run build
cd packages/dev # or cd packages/docs
pnpm run dev

License

MIT

About

UnoCSS preset for Quasar Framework

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Vue 58.5%
  • TypeScript 24.5%
  • CSS 9.1%
  • JavaScript 7.0%
  • Other 0.9%