tw-in-js / use-twind-with

Twind integration packages for frameworks & libraries with examples
MIT License
67 stars 17 forks source link

Using shim and avoiding FOUC #13

Closed steakscience closed 3 years ago

steakscience commented 3 years ago

In twind docs, it recommends that we add hidden to <html> to avoid flash of unstyled content. The shim should auto-remove this once everything is good.

However, when using hidden with @twind/next, the hidden will never be removed and the page will remain hidden forever

What should I do to avoid FOUC instead?

sastan commented 3 years ago

If you are using @twind/next the hidden is not necessary. All required styles are injected during SSR into the page and there should be no FOUC.

steakscience commented 3 years ago

Thanks for the quick response!

I am using the instructions here and I can reliably get FOUC every time.

It should flash white the first time you load this

sastan commented 3 years ago

It seems the SSR does not injected the CSS into the rendered page. Did you adjust your pages/_document.js?

Something like:

import withTwindDocument from '@twind/next/shim/document'
import twindConfig from '../twind.config'

export default withTwindDocument(twindConfig)
steakscience commented 3 years ago

I am adding classes into _document.js to add a background and text color

import withTwindDocument from '@twind/next/shim/document'
import twindConfig from '../twind.config'
import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  render() {
    return (
      <Html className="bg-background-app text-body text-base">
        <Head />
        <body className="font-sans">
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default withTwindDocument(twindConfig, MyDocument);
sastan commented 3 years ago

After re-checking I found that the styles are there in the response. But the styles applied to html and body are not included in the response.

Looking into it.

sastan commented 3 years ago

It seems that we do not get the whole html but only the main markup and that is why we do not detect the classes on html and body.

As a temporary workaround you could make sure that the classes are added using a explicit tw call within the app. Sorry for that – I try to find a better solution.

pages/_app.tsx

import type { AppProps /*, AppContext */ } from 'next/app'

import { tw } from 'twind'

import withTwind from '@twind/next/shim/app'
import config from '../twind.config'

function MyApp({ Component, pageProps }: AppProps) {
  // Ensure classes from _document are available during SSR
  tw`font-sans bg-gray-500 text-sm text-base`
  return <Component {...pageProps} />
}

export default withTwind(config, MyApp)
steakscience commented 3 years ago

@sastan Thank you!