Skip to content

Frontend styling

Choose the right styling layer

Easy8 has more than one styling layer. Identify which layer the screen already uses before you add styles.

  • Design System components (see Design system) are styled through their props. Do not restyle them from your plugin.
  • Existing legacy screens, ERB views, and easy_ui integrations use the legacy Easy styles under app/frontend/src/shared/stylesheets/easy/.
  • Vuetify overrides live under app/frontend/src/shared/stylesheets/vuetify/.
  • Tailwind utility classes are available globally, but only those used in app/frontend/src. Classes that appear only in your plugin are not compiled. See Tailwind utilities.

Extend the layer the screen already uses; do not move a screen to another styling system just because you touch it.

Main locations

  • app/frontend/src/<module>/stylesheets/: styles owned by a frontend module.
  • app/frontend/src/shared/stylesheets/easy/_base.scss: main legacy Easy stylesheet entrypoint.
  • app/frontend/src/shared/stylesheets/easy/_common-assets.scss: shared legacy exports for variables, abstracts and themes.
  • app/frontend/src/shared/stylesheets/easy/variables/: legacy Easy variables.
  • app/frontend/src/shared/stylesheets/easy/themes/: themes and brand values.
  • app/frontend/src/shared/stylesheets/vuetify/: Vuetify overrides.
  • app/frontend/src/shared/stylesheets/tailwind/index.css: Tailwind theme and source scanning.

General rules

  • Keep styles in the same layer as the feature you are editing.
  • Keep selectors as flat as possible. Prefer classes over long descendant chains.
  • Avoid !important unless you are fixing a real override problem that cannot be solved cleanly.
  • Reuse existing variables, mixins, and placeholders before introducing new values or abstractions.
  • Keep feature-specific rules close to the owning component, page, or pattern.
  • Do not add or extend custom styles in Vue <style> blocks, including <style scoped>. Put new declarations in the owning module's external SCSS files. Shared components follow the external stylesheet structure of their owning shared layer.
  • Follow naming already used in the edited area instead of forcing a new naming convention into old code.

Tailwind utilities

Tailwind v4 is compiled through PostCSS and loaded on every page: the base layout includes vite_stylesheet_tag 'tailwind.css', so utilities are available without importing anything.

The theme lives in app/frontend/src/shared/stylesheets/tailwind/index.css. It disables Tailwind's own source detection (source(none)) and scans app/frontend/src explicitly, so a class only survives the build if it appears literally in that tree. A class used only in your modification plugin is stripped; style the plugin with its own stylesheet or with a class that the core already uses. Do not build class names dynamically (`gap-ms${size}`), because they will be stripped.

What the utilities resolve to

The Tailwind theme maps to the legacy Easy variables (--easy__*), not to the Design System tokens.

--spacing-ms1: var(--easy__spacing--ms-1);   /* gap-ms1, p-ms1, m-ms1 ... */
--color-front: var(--easy__color--front);    /* bg-front, text-front ... */
--color-font-muted: var(--easy__color--text-muted);

There is no --Scale-Size-* or --Content-* utility, so a Design System component styled with utilities mixes two token families.

Choosing

Use a Design System component and its props where one fits. For the layout left over:

Use When
Tailwind utilities The surrounding module already uses them, the component sits on legacy or easy_ui foundations, or you need a handful of one-off layout declarations.
Module-owned SCSS Custom CSS is clearer than utilities, for example for component states, media or container queries, or substantial layout such as a scrollable feed. Put the rules in app/frontend/src/<module>/stylesheets/, namespace them under the module root class or another unique module-owned class for teleported content, and use the token family established by the module.

Load module styles through the module's existing Vite asset path. For a new microapp, import its SCSS aggregate from the module's JavaScript or TypeScript entrypoint, normally under app/frontend/entrypoints/. For an existing module, extend its current loader and styles/ or stylesheets/ structure, including source main or index imports and standalone stylesheet entrypoints loaded with vite_stylesheet_tag.

SCSS reuse

The codebase uses modern Sass module syntax with @use and @forward.

  • Use @mixin when the style needs configuration or reusable generated output.
  • Use placeholders with @extend %placeholder for fixed shared declaration groups.
  • Prefer extending placeholders, not concrete HTML selectors or unrelated component classes.
  • When working in legacy Easy styles, look for reusable assets in utils/abstracts/ and shared exports from _common-assets.scss.
  • Many legacy pattern files expose @mixin styles; wire them through the owning entrypoint instead of scattering duplicate imports.

Themes and branding

To change colours, fonts or logos, see Theme and custom branding.