ben-rogerson / twin.macro

🦹‍♂️ Twin blends the magic of Tailwind with the flexibility of css-in-js (emotion, styled-components, solid-styled-components, stitches and goober) at build time.
MIT License
7.89k stars 184 forks source link

Next 14 layout shift (maybe css load after render) #840

Open minemos opened 9 months ago

minemos commented 9 months ago

https://github.com/ben-rogerson/twin.macro/assets/24834933/bc12dae0-41e8-4501-addb-2476085b0169

copied from example project using app dir and next 14

package.json

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@emotion/css": "^11.11.2",
    "@emotion/react": "^11.11.1",
    "@emotion/server": "^11.11.0",
    "@emotion/styled": "^11.11.0",
    "cssnano": "^6.0.1",
    "next": "14.0.3",
    "react": "^18",
    "react-dom": "^18",
    "tailwind-scrollbar-hide": "^1.1.7"
  },
  "devDependencies": {
    "@babel/core": "^7.23.3",
    "@babel/plugin-syntax-typescript": "^7.23.3",
    "@babel/preset-react": "^7.23.3",
    "@babel/preset-typescript": "^7.23.3",
    "@emotion/babel-plugin": "^11.11.0",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "autoprefixer": "^10.4.16",
    "babel-loader": "^9.1.3",
    "babel-plugin-macros": "^3.1.0",
    "babel-plugin-styled-components": "^2.1.4",
    "eslint": "^8",
    "eslint-config-next": "14.0.3",
    "postcss": "^8.4.31",
    "styled-components": "^6.1.1",
    "tailwindcss": "^3.3.0",
    "twin.macro": "^3.4.0",
    "typescript": "^5"
  },
  "babelMacros": {
    "twin": {
      "preset": "emotion"
    }
  }
}

src/app/GlobalStyles.js

"use client";

import React from "react";
import { Global } from "@emotion/react";
import { css, GlobalStyles as BaseStyles } from "twin.macro";

const GlobalStyles = () => (
  <>
    <BaseStyles />
    <Global styles={css({})} />
  </>
);

export default GlobalStyles;

src/app/layout.tsx

import "./globals.css";
import GlobalStyles from "./GlobalStyles";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <GlobalStyles />
        {children}
      </body>
    </html>
  );
}

src/app/page.tsx

/** @jsxImportSource @emotion/react */
"use client";
import "twin.macro";

const App = () => (
  <div tw="flex flex-col items-center justify-center h-screen">
    <div tw="flex flex-col justify-center h-full gap-y-5">asdf</div>
  </div>
);

export default App;

It caused layout shift

seems like css is load after rendering

ben-rogerson commented 9 months ago

This looks like an issue between Emotion and Next - Emotion probably needs to have a style cache set.

Check this thread for some examples on this.

minemos commented 9 months ago

That can't be solution I think. (Also I tried)

I think problem is about server component and client component.

But that component (registry) also using client component.

To use full features in next js app dir, we need to use server component.

Anyway, point is server component is rendered at server but server have no css to render So client re render, and it cause layout shift

isahuja2 commented 4 weeks ago

@minemos - did you find any solution for the above issue?