When adding Tailwind CSS to my Next.js app, the MDX styling through next-mdx-remote stops working properly

I've integrated MDX into my Next.js project using next-mdx-remote.

While following JetBrains WebStorm's detailed tutorial on building a blog with MDX, they utilized Bootstrap for styling. However, I opted for Tailwind CSS as my preferred CSS framework.

The issue arises when I install Tailwind CSS or any other CSS based on it like FlowBite, causing the MDX page to lose its styling.

Expected Result:
Actual Outcome after adding Tailwind

  • tailwind.config.js
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

  • _app.tsx

import "../styles/globals.css";
import type { AppProps } from "next/app";
import Head from "next/head";
import Script from "next/script";
import Nav from "../components/Nav";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <Head>
        {/* <link
          rel="stylesheet"
          href="https://unpkg.com/@themesberg/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d7b1bbb8a0b5bea3b297e6f9e5f9e7">[email protected]</a>/dist/flowbite.min.css"
        /> */}
      </Head>
      <Script src="https://unpkg.com/@themesberg/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1e787271697c776a7b5e2f302c302e">[email protected]</a>/dist/flowbite.bundle.js" />
      <Nav />
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;
  • globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}
  • [blogId].tsx
// import fs from "fs";
import matter from "gray-matter";
import path from "path";
import { serialize } from "next-mdx-remote/serialize";
import { MDXRemote } from "next-mdx-remote";

import { connectToDatabase } from "../../utils/mongodb";
import { ObjectId } from "mongodb";

const BlogPg = ({ frontMatter: { title }, MDXdata }) => {
  return (
    <div className="px-5 md:px-80 py-10">
      <p className="text-5xl mb-4">{title}</p>
      <MDXRemote {...MDXdata} />
    </div>
  );
};

export const getStaticPaths = async () => {

  let { db } = await connectToDatabase();

  const posts = await db.collection("blogs").find({}).toArray();

  const paths = posts.map((post) => ({
    params: {
      blogId: post._id.toString(),
    },
  }));

  return {
    paths,
    fallback: false,
  };
};

export const getStaticProps = async ({ params: { blogId } }) => {
  // const fileContent = fs.readFileSync(
  //   path.join("posts", blogId) + ".mdx",
  //   "utf-8"
  // );

  let { db } = await connectToDatabase();

  const post = await db
    .collection("blogs")
    .find({ _id: new ObjectId(blogId) })
    .toArray();

  const { data: frontMatter, content } = matter(post[0].text);
  const MDXdata = await serialize(content);

  return {
    props: {
      frontMatter,
      blogId,
      MDXdata,
    },
  };
};

export default BlogPg;

Answer №1

To make some changes, replace content with purge and include

require('@tailwindcss/typography')
in the plugins section of your tailwind.config.js. For the new typography styles to take effect, wrap your <MDXRemote .../> component with a div having a class of prose.

  • Update tailwind.config.js

    module.exports = {
      purge: [
        "./pages/**/*.{js,ts,jsx,tsx}",
        "./components/**/*.{js,ts,jsx,tsx}",
      ],
      theme: {
        extend: {},
      },
      plugins: [require('@tailwindcss/typography')],
    };

  • Modify \[blogId\].tsx
...
            <div className="prose">
    
              <MDXRemote {...MDXdata} /> 
            </div>
        </div>
      );
    };
...

Answer №2

I successfully resolved a similar issue and wanted to share my solution.

Why isn't the markdown rendering showing any styling? I discovered that in my global.css file, there was a @tailwind base that was resetting the default CSS styling, causing the lack of styling for my rendered Markdown.

How did I fix this problem? I made a modification in the tailwind config by adding:

plugins: [require("@tailwindcss/typography")],

In the HTML element containing the markdown content, I added the following class:

<article className="prose lg:prose-xl">
{myMarkdownContent}
</article>

This solution was found at: https://github.com/tailwindlabs/tailwindcss-typography/blob/master/README.md

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on setting a background image to a div element

I'm facing an issue with a div setup like this: https://i.sstatic.net/4nuyO.png My goal is to remove a specific section of the circle shape displayed below: https://i.sstatic.net/09IWX.png The desired outcome is to achieve a final shape similar to ...

Error in Next.js: .env variable not defined

I recently transitioned my project from React to Next.js and encountered an issue where my environment variables are showing as undefined, even though they were functioning correctly in React. Can someone provide some guidance or assistance with this probl ...

Steps for adjusting the margin of a section using the p tag

Newbie CSS inquiry here... Here's what I currently have in my stylesheet: #topheader { position: absolute; width: 100%; height: 100px; background-color: #D1E6DA; font-size: 200%; } I want to include the following: p { margi ...

What steps can be taken to view the logs of a Next.js project that has been deployed on Google App Engine's

Recently, I put together a Next.js project using the Isomorphic admin theme. My next step is to deploy this project on Google App Engine. After reading through this informative discussion thread, I structured my app following the guidelines provided in th ...

Typescript validation for redundant property checks

Why am I encountering an error under the 'name' interface with an excess property when using an object literal? There is no error in the case of a class, why is this happening? export interface Analyzer { run(matches: MatchData[]): string; } ...

Retrieving live comments from YouTube streams for a customized React application

Currently working on developing a React Webapp to organize and showcase superchats during a live stream. My initial attempt involved utilizing the YouTube LiveChat API, but I hit a roadblock as it requires authentication from the live stream owner, which ...

Utilize viewport activation to determine browser width

Is there a way to dynamically add the viewport-meta tag only for devices with screen widths larger than 680px? If the screen is smaller than 680px, then the responsive style file should be enabled instead. I attempted to achieve this by placing the follow ...

Understanding the mechanics of async/await and Promise in TypeScript

Trying to wrap my head around how async, await, and promises work with this simple function. function delay(ms: number) { return new Promise<void>(function(resolve) { setTimeout(resolve, ms); }); } async function asyncAwait() { c ...

Seeking assistance in creating custom tabs for integration with a jQuery tabs plugin

Attempting to navigate the world of CSS as a newbie, I find myself struggling with creating tabs. Our current tab setup can be viewed here, but unfortunately, these tabs are created using an unattractive <table> tag. Below is the code responsible fo ...

Guide to finding the parent component of a particular element?

When the add button is clicked, I am dynamically adding lists and a new button labeled as "New Button" to a web page. My goal is to have a variable printed inside the parent list when this "New Button" is clicked. How can I achieve this functionality? Bel ...

Leveraging Next.js for credential validation along with secured paths using next-auth

Currently in the process of developing a web application using NextJs (13.1.1), I have been provided with an external backend that requires a connection via username/password to obtain an access token, refresh token, and its expiration time in the response ...

Ensure that the website content maintains a full 100% height even while resizing

Is there a way to make my website resize its height instead of width when zooming out? I want the red box at the bottom to stay fixed while the other content adjusts. Any suggestions? .menu { cursor: pointer; } .mario { display: block; margin-left ...

Implementing an interface with a variable key and defining the key simultaneously

I am trying to design an interface with a fixed key, as well as a variable key, like this : interface Data { api?: { isReady: boolean; }; [key: string]: string; } This setup gives me the following error message : Property 'api' of typ ...

Which HTML tag should I choose to apply color to text in Twitter Bootstrap?

I'm looking to enhance the appearance of a specific word in my text. For example: This is my text, <span class="red">this</span> should be red. Would using the span tag be the appropriate method for achieving this effect? Or are there ot ...

Retrieving Information from an Angular 2 Component

Struggling to figure this out, I am attempting to dynamically add user video data that includes a video URL. My goal is to access the data from the component so I can use it in my HTML. I've attempted the following approach. app.component.ts import ...

What is the significance of `(<typeof className>this.constructor)` in TypeScript?

After inspecting the source code of jQTree, written in Typescript, available at https://github.com/mbraak/jqTree, I came across the following snippet: export default class SimpleWidget{ protected static defaults = {}; ...

Sketch a variety of numerical values in a circular formation

I was working on a number circle using the below fiddle, but I need it to always start from 0 at the top. How can I achieve this? Additionally, I would like to connect the numbers from the inner circle border to the number with a dotted line. How can I dr ...

Is there a method or alternative solution for deconstructing TypeScript types/interfaces?

Imagine a scenario where a class has multiple type parameters: class BaseClass<T extends T1, U extends U1, V extends V1, /* etc. */ > Is there a method to consolidate these type arguments in a way that allows for "spreading" or "destructuring," sim ...

Is it considered best practice to include try/catch blocks within the subscribe function in RxJs?

Imagine we have an Angular 2 application. There is a service method that returns data using post(), with a catch() statement to handle any errors. In the component, we are subscribing to the Observable's data: .subscribe( ()=> { ...

Calculating the dimensions of a CSS element based on its content

Is there a way to achieve this using only CSS, without needing JavaScript? I am working on a project with a lot of relative and absolute positions, where elements must be centered dynamically without specifying static widths. While I have managed to minimi ...