πŸš€Β Β Zermatt v1.1.0 out now!Β With full CSS support (SASS, Tailwind).Β Read more.

Docs
CSS Styling

CSS Styling

Styling Zermatt modules / Build a custom theme.

Zermatt comes with a powerful way to style modules and themes. Whether with Zermatt-native SASS support, or with TailwindCSS, or any other implementation.

View the official SASS site

Architecture

When running npm run dev or npm run build:

  1. Zermatt scans for all .scss files of web/zermatt/**/ folders in vendor, app/code and the current theme.
  2. Those files are processed in order to deal with hierarchy (see below).
  3. A zermatt-lock.scss file is generated and contains one @use per matching .scss file.
  4. ViteJS processes this all-in-one file with the scss preprocessor from vite.config.js.
  5. This creates a dist/zermatt.css file that is used in Maddlen_Zermatt::view/frontend/layout/default_head_blocks.xml

Zermatt exposes a zermattLock() function that can be used to generate a custom zermatt-lock.scss.

View the code on Github

Hierarchy

In short: theme > app/code > vendor

LocationFileContent
vendorA.scss.class_A { color: red; }
vendorB.scss.class_B { color: black; }
app/codeA.scss.class_C { color: blue; }
app/codeC.scss.class_D { color: green; } .class_E { color: yellow; }
themeA.scss.class_F { color: purple; }
themeD.scss.class_E { color: lime; } .class_G { color: olive; }

Result:

.class_B { color: black; }
.class_D { color: green; }
.class_E { color: lime; }
.class_F { color: purple; }
.class_G { color: olive; }

In other words:

  • Hard rewrite: use a file named the same as one lower in the hierarchy.
  • Soft rewrite: use a file named any custom way and update the SCSS as usual.
  • Custom: use a file named anything you like, and write SCSS as usual.

Writing SCSS

Zermatt reads and compiles all .scss files that are in the web/zermatt/**/ folders in vendor, app/code and the current theme. So it is possible to write SCSS in any location in those folders, for example:

.
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ code/
β”‚   β”‚   └── Vendor/
β”‚   β”‚       └── Module/
β”‚   β”‚           └── view/
β”‚   β”‚               └── frontend/
β”‚   β”‚                   └── web/
β”‚   β”‚                       └── zermatt/
β”‚   β”‚                           └── modules/
β”‚   β”‚                               └── vendor-module.scss
β”‚   └── design/
β”‚       └── frontend/
β”‚           └── Vendor/
β”‚               └── theme/
β”‚                   └── web/
β”‚                       └── zermatt/
β”‚                           β”œβ”€β”€ ui/
β”‚                           β”‚   β”œβ”€β”€ typography.scss
β”‚                           β”‚   └── forms.scss
β”‚                           β”œβ”€β”€ modules/
β”‚                           β”‚   β”œβ”€β”€ // Rewrites vendor-module.scss from Vendor_Module
β”‚                           β”‚   β”œβ”€β”€ vendor-module.scss
β”‚                           β”‚   β”œβ”€β”€ // Rewrites from /vendor
β”‚                           β”‚   └── some-scss-file-somewhere.scss
β”‚                           └── layout.scss
└── vendor/
    └── */*/
        └── some-scss-file-somewhere.scss

@use or not?

@use (the deprecated @import) is not required in your SCSS files as long as the imported file is in a web/zermatt folder. If, for some reason, your SCSS files are not in a web/zermatt folder, then you can use @use to import them.

You may also want to completely bypass Zermatt SASS layer (see "Full custom theme") and use your own implementation. You will then need to create a .scss entry point file which will contain your imports.

Full custom theme

It is possible to completely bypass all existing .scss files and use a custom implementation in a theme. Zermatt provides several options.

Option 1: with SASS

The fastest option is to create a .scss entry file in the web/zermatt folder of the theme. Then build around that file.

Implementation:

  1. Create a custom-name.scss entry file in the web/zermatt folder of the theme
  2. In vite.config.js file:
// replace
await zermattLock()
// with
await zermattLock([path.join(path.dirname(fileURLToPath(import.meta.url)),
'/custom-name.scss')])
  1. Write SCSS the usual way

Option 2: without SASS

In vite.config.js file:

// replace
await zermattLock()
// with
await zermattLock([])

And do your thing.

Note: the dist/zermatt.css output file is still generated (with a fake harmless content) in order to avoid network errors as the layout is still calling it. See "Architecture".

Using TailwindCSS

Considerations about using TailwindCSS

The nature of TailwindCSS is so that it would need to watch too many .phtml (or worse PHP) files to work which is bad for performance. This is why, except if you know what you are doing, it is highly recommended to scope TailwindCSS to the current theme only. This implies building a theme from scratch (which is a totally fine option) or deal with conflicts between TailwindCSS and Magento CSS.

That being said, adding TailwindCSS to Zermatt is straightforward.

  1. Init TailwindCSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
  1. Create input.css
@tailwind base;
@tailwind components;
@tailwind utilities;
  1. Update tailwind.config.js to scan the correct files
export default {
  content: ["../../**/*.phtml"], // .phtml files in the current theme
}
  1. Update index.html
<script type="module" src="/zermatt.js"></script>
<link rel="stylesheet" href="/input.css">
  1. Update vite.config.js
import { defineConfig } from 'vite'
import tailwindcss from 'tailwindcss';
import autoprefixer from 'autoprefixer';
 
export default defineConfig({
    css: {
        postcss: {
            plugins: [
                tailwindcss(),
                autoprefixer(),
            ],
        },
    },
    build: {
        manifest: true,
        rollupOptions: {
            output: {
                assetFileNames: (assetInfo) => {
                    if (assetInfo.name && assetInfo.name.endsWith('.css')) {
                        return 'assets/zermatt.css'
                    }
                    return 'assets/[name].[hash][extname]'
                }
            }
        }
    }
})

Tip: in order to restyle non-tailwind phtml files even outside of the theme, use TailwindCSS @apply directive to reconstruct css classes. This is very useful in the context of Zermatt to be able to easily style phtml files from vendor or app/code Zermatt modules.

Conventions and best practices

Namespace files

Ex: vendor-module.scss. To be enforced especially if file lives in app/code or is meant to be distributed.

Scope CSS within their matching Zermatt module

Ex:

<div class="vendor-module" x-data="Zermatt.Module('Vendor_Module')">...</div>

with

.vendor-module {...}