Multiple layouts in NextJS or conditional css import #22136
Replies: 9 comments 10 replies
-
Absolutely the same case. I thought it's very common case when you have admin and public part with different css, but I still can't find a solution :( |
Beta Was this translation helpful? Give feedback.
-
In my opinion, the following three features are needed to make this work.
Example (NOTE: This code is from my imagination and is not official): import { useRouter } from 'next/router';
// The D mode in https://github.com/webpack/webpack/issues/14893
// But, this mode is not implemented yet.
const commonSheetUrl = new URL('../styles/common/global.css', import.meta.resolve);
const adminSheetUrl = new URL('../styles/admin/global.css', import.meta.resolve);
function App({ Component, pageProps }) {
const { asPath } = useRouter();
const isAdmin = asPath === '/admin';
return (
<>
<Head>
{!isAdmin && <link rel="preload" href={commonSheetUrl} as="style" />}
{!isAdmin && <link rel="stylesheet" href={commonSheetUrl} />}
{isAdmin && <link rel="preload" href={adminSheetUrl} as="style" />}
{isAdmin && <link rel="stylesheet" href={adminSheetUrl} />}
</Head>
<Component {...pageProps} />
</>
);
} My gut feeling is that it would be difficult to solve this problem with a user-side workaround, and it appears that improvements to the Next.js build system are needed. |
Beta Was this translation helpful? Give feedback.
-
Loading unnecessary style sheets cannot be avoided, but the style sheets can be scoped to minimize their impact. Depending on the use case, this workaround may be available. // pages/_document.tsx
import Document, { Html, Head, Main, NextScript, DocumentContext, DocumentInitialProps } from 'next/document';
import { ReactElement } from 'react';
type MyDocumentProps = {
theme: 'common' | 'admin';
};
type MyDocumentInitialProps = MyDocumentProps & DocumentInitialProps;
export default class MyDocument extends Document<MyDocumentProps> {
static async getInitialProps(ctx: DocumentContext): Promise<MyDocumentInitialProps> {
const initialProps = await Document.getInitialProps(ctx);
const pathname = ctx.req?.pathname;
const theme = pathname === '/admin' ? 'admin' : 'common';
return { ...initialProps, theme };
}
render(): ReactElement {
return (
<Html data-theme={this.props.theme}>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
} // pages/_app.tsx
import '../styles/common/global.scss';
import '../styles/admin/global.scss';
function App({ Component, pageProps }) {
// ...
} // styles/common/global.scss
// NOTE: The level of detail has been increased from 1 to 11
// because of the combination of attribute selectors and element selectors.
// This may result in unexpected style overrides.
[data-theme='common'] {
body {
background: 'blue';
}
}
// You can use `:where` to reduce the level of detail.
// NOTE, however, that this is not supported in Safari 13.x and below.
// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/:where
// :where([data-theme='common']) {
// body {
// background: 'blue';
// }
// } // styles/admin/global.scss
// NOTE: The level of detail has been increased from 1 to 11
// because of the combination of attribute selectors and element selectors.
// This may result in unexpected style overrides.
[data-theme='admin'] {
body {
background: 'red';
}
}
// You can use `:where` to reduce the level of detail.
// NOTE, however, that this is not supported in Safari 13.x and below.
// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/:where
// :where([data-theme='admin']) {
// body {
// background: 'red';
// }
// } |
Beta Was this translation helpful? Give feedback.
-
I have read that inside if (someCondition){
import('../styles/rtl.css');
} but would this code run on the client and/or on the server? if server, does it run for every request? EDIT: it seems to work on a new nextjs project |
Beta Was this translation helpful? Give feedback.
-
The solutions mentioned above are great, but the styles always apply after moments from the page's initial load, which makes great layout shifting. |
Beta Was this translation helpful? Give feedback.
-
The solution that I found was to move the styles from the css file into a style tag in the layout where I wanted them to apply. What I wanted and what it seems this thread it about Unfortunately this seems to apply it to all pages. Solution example export default function Layout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<>
<style>
{` CSS Here `}
</style>
<>
)
} That way the css loads only on subpages within this layout. Ordinarily I would just use tailwind but I had to style an external component. Sorry for posting on an old thread! Just wanted to help anyone new who might be having a similar issue. |
Beta Was this translation helpful? Give feedback.
-
Cannot believe such a simple and common feature is impossible to implement in the all-mighty nextjs |
Beta Was this translation helpful? Give feedback.
-
Thennnnnn, do it for us
Get Outlook for iOS<https://aka.ms/o0ukef>
…________________________________
From: Yusuf Sabbag ***@***.***>
Sent: Friday, October 25, 2024 5:24:09 AM
To: vercel/next.js ***@***.***>
Cc: chiefdeals ***@***.***>; Comment ***@***.***>
Subject: Re: [vercel/next.js] Multiple layouts in NextJS or conditional css import (Discussion #22136)
Cannot believe such a simple and common feature is impossible to implement in the all-mighty nextjs
—
Reply to this email directly, view it on GitHub<#22136 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/A6G4PMBSOTJEQBF6RRMCMHLZ5IZ6TAVCNFSM6AAAAABQTFLVUCVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTCMBVGIYTMMI>.
You are receiving this because you commented.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I’m working on moving legacy app to Nextjs. The app has two layouts: public and admin part. Every layout has it’s own css files. Because of the nextjs restrictions when you can import css only in custom _app.js file I can’t split layouts. I don’t want to include admin css to the public layout and vice versa and the modules solution will be a problem as I have quite large CSS with a bunch of rules that aren't pure.
I'm importing the public css such as
Then for the admin layout I've tried to add the CSS manually like:
But the admin styles are placed after the public styles within the header.
What can I do in this scenario? Also is there is a way to customize the placement of the styles from webpack?
Beta Was this translation helpful? Give feedback.
All reactions