Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

troccoli's avatar

Two layouts but different sans font

First of all, I'm not sure if this relates to Tailwind, Vite, Laravel, or maybe even Flux. If you think I would be better off asking in one of those project directly please let me know.

I have a new Laravel 12 project. In it I have two separate parts: a public, and am admin part.

The public part uses our brand style, while I want the admin one to use the default Flux style.

One of the difference is the font used for the sans family The public uses Google's Work Sans, so I have the following in my app.css

@theme {
    --font-sans: 'Work Sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    ...
}

How can instead use, for example, Instruments Sans for the admin part?

The public and admin parts use two separate layouts, but as far as I know I cannot have Vite produce two separate CSS files (I did try)

0 likes
5 replies
LaryAI's avatar
Level 58

Certainly! Here’s how you can handle different font families for your public and admin layouts in a Laravel 12 + Vite + Tailwind setup, without needing two separate CSS files.

Solution: Use CSS Variables and Layout-specific Classes

1. Define Both Fonts in Your CSS

In your main CSS (e.g., app.css), define both font families as CSS variables, each under a unique class:

/* app.css */
:root {
    --font-sans-public: 'Work Sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    --font-sans-admin: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}

/* Optional: fallback for Tailwind's font-sans */
.font-sans-public {
    font-family: var(--font-sans-public);
}
.font-sans-admin {
    font-family: var(--font-sans-admin);
}

2. Use Tailwind’s fontFamily Customization

If you want to use Tailwind’s font-sans utility, you can override it per layout using a custom class:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        'sans-public': ['var(--font-sans-public)'],
        'sans-admin': ['var(--font-sans-admin)'],
      },
    },
  },
}

3. Apply the Class in Your Blade Layouts

Public Layout:

<body class="font-sans-public">
    <!-- Public content -->
</body>

or with Tailwind utility:

<body class="font-sans-public font-sans-public">
    <!-- Public content -->
</body>

Admin Layout:

<body class="font-sans-admin">
    <!-- Admin content -->
</body>

or with Tailwind utility:

<body class="font-sans-admin font-sans-admin">
    <!-- Admin content -->
</body>

4. Load Both Fonts

Make sure both fonts are loaded in your HTML (e.g., via Google Fonts CDN in your layouts):

<!-- In public layout -->
<link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;700&display=swap" rel="stylesheet">

<!-- In admin layout -->
<link href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;700&display=swap" rel="stylesheet">

5. Result

Now, each layout will use its own font, but you’re still using a single CSS file. No need to split your Vite build.


Summary:

  • Define both fonts as CSS variables and/or Tailwind custom font families.
  • Apply the appropriate class at the layout level.
  • Load the correct font in each layout’s <head>.
  • No need for multiple CSS files or Vite configs.

Let me know if you need a more detailed example or help with your tailwind.config.js!

troccoli's avatar

Although @laryai answer would work, it looks and feels a bit clunky.

Does anyone have any other suggestion?

martinbean's avatar

The public and admin parts use two separate layouts, but as far as I know I cannot have Vite produce two separate CSS files (I did try)

@troccoli Why do you think so? Of course you can; you just need to specify the additional entry point in your vite.config.js file:

  export default defineConfig({
      plugins: {
          laravel({
              inputs: [
                  'resources/css/app.css',
+                 'resources/css/admin.css',
              ],
              refresh: true,
          }),
      },
  });
troccoli's avatar

@martinbean

Because I tried it and it doesn't do what you think. It produces only one CSS file

export default defineConfig({
  plugins: [
    laravel({
      input: [
        'resources/css/app.css',
        'resources/css/admin/app.css',
        'resources/js/app.js'
      ],
      refresh: [`resources/views/**/*`],
    }),
    tailwindcss(),
  ],
})

and this is the public/build/manifest.json

{
  "resources/css/admin/app.css": {
    "file": "assets/app-DL4dikLy.css",
    "src": "resources/css/app.css",
    "isEntry": true
  },
  "resources/css/app.css": {
    "file": "assets/app-DL4dikLy.css",
    "src": "resources/css/app.css",
    "isEntry": true
  },
  "resources/js/app.js": {
    "file": "assets/app-eMHK6VFw.js",
    "name": "app",
    "src": "resources/js/app.js",
    "isEntry": true
  }
}
martinbean's avatar

@troccoli Then use different names for the style sheets, as they’re clearly conflicting.

If you’re creating an admin style sheet, call it admin.css and not “app.css”:

  export default defineConfig({
      plugins: [
          laravel({
              input: [
                  'resources/css/app.css',
-                 'resources/css/admin/app.css',
+                 'resources/css/admin.css',
                  'resources/js/app.js',
              ],
              refresh: true,
          }),
          tailwindcss(),
      ],
  });

Please or to participate in this conversation.