Multiple layouts in NextJS or conditional css import

Viewed 3387

I'm working on moving legacy app to the 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. What can I do in this case?

I was trying to use styled-jsx, but it brought more problems. I can't wrap the whole css file with thouthands of lines with css.globe`` because there are a lot of errors, such as we don't support nesting etc.

3 Answers

You could place the files in the /public folder and then just manage the for the css manually. A good place for manually managing the included styles would be a custom _document.jsx page.

Note that you work around next by doing this. The files won't get bundled with your other css-files. They will also be available to the public by url.

Convert the import to a CSS Module by changing the name from (for example) public.css to public.module.css.

Then import it as an object.

import styles from 'path-to/public.module.css'

And use it with the className attribute.

<div className={styles.whatever}></div>

Note, the contents of public.module.css are just stock CSS.

.whatever { /*...*/ }

You can apply a conditional style with a ternary.

<div className={someBoolean ? styles.whatever : ''}>

You can define two layout components with dynamic and switch then in _app.js. This article shows the features of dynamic.

On the other hand, we don't support nesting may caused by applying sass/scss file of css compiler in styled-jsx. You could try to make styled-jsx to support sass/scss features.

_app.js

const App = ({ Component, pageProps }) => {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  )
}

Layout.js

import dynamic from 'next/dynamic';

const mapLayoutToComponent = {
  public: dynamic(import("./layouts/Public")),
  admin: dynamic(import("./layouts/Admin"))
}

const Layout = props => {
  const [layoutState, setLayoutState] = React.useState('public');
  const Component = mapLayoutNameToComponent[layoutState];

  return <Component>{props.children}</Component>
}

layouts/Public.js

import '../styles/public.css';

const Public = (props) => {
  return <>{props.children}</>
};

layouts/Admin.js

import '../styles/admin.css';

const Admin = (props) => {
  return <>{props.children}</>
};
Related