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.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Next 14 layout shift (maybe css load after render)

minemos opened this issue · comments

2023-11-23.2.24.30.mov

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

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.

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