What is the best way to leverage environment variables in my CSS within the context of Next.js for defining the primary color scheme?

Is there a way to use an environment variable to specify the base color in my CSS?

I am working with NEXTJS.

All of my colors are defined as variables in my globals.css:

@layer base {
   :root {
      ...
      --primary: #0096d0;
      --primary-bright: hsl(from var(--primary) h s calc(l*1.5));
      ...

I attempted to do the following:

--primary: env(NEXT_PUBLIC_PRIMARY_COLOR, #0096d0);

However, the env variable is not being recognized.

Does anyone have any suggestions on how to solve this issue?

Answer №1

Although the env() function can work with custom properties, it currently reads from UA-defined environment variables, not from the published NEXT_PUBLIC_ variables on the client-side or server-side environment variables. While there may be a possibility in the future to add custom environment variables via JS or CSS, creating client-side Custom CSS Environment Variables is not feasible at this moment.

Until such functionality becomes available, options include using CSS preprocessors, inline-styles in JSX, or PostCSS plugins, each with its own limitations.

Inline Styles

The primary drawback of inline styles is that they cannot be used in global.css as previously done. However, an advantage is the flexibility to create and update the style object dynamically during runtime. Please note that all NEXT_PUBLIC_ variables are immutable once the application starts running.

Example usage in index.js:

//Dynamic creation by iterating over keys in .env.local
const style = {"--primary": process.env.NEXT_PUBLIC_PRIMARY_COLOR ?? '#0096d0'}
<div style={style}>
    <MyRoot></MyRoot>
</div>

CSS Preprocessors

One approach involves importing specific environment variables into SCSS variables using the SASS additional-data loader option.

To integrate SASS with Next.js, follow the documentation for Styling with SCSS:

npm install --save-dev sass

In the next.config.js file, prepend the SASS variables:

const nextConfig = {
  sassOptions: {
    additionalData: Object.keys(process.env).reduce((accumulator, currentValue) => {
      if (currentValue.startsWith('NEXT_THEME_')) {
        return `${accumulator}$${currentValue}: ${process.env[currentValue]};`
      }
      else {
        return accumulator
      }
    }, ''),
    includePaths: [path.join(__dirname, 'styles')],
  }
}

Add the necessary environment variables in .env.local:

NEXT_THEME_PRIMARY_COLOR=red
NEXT_THEME_SECONDARY_COLOR='#fff'

Now you can utilize these variables in globals.scss as demonstrated below:

@layer base {
  :root {
    --primary: #{$NEXT_THEME_PRIMARY_COLOR};
  }
}

The downside is that SCSS variables are preprocessed and cannot be updated during JS runtime. Additionally, all referenced environment variables must be defined or handled explicitly using variable-exists() or !default.

PostCSS Plugins

Next.js comes with built-in support for PostCSS and various plugins, although none directly cater to your requirements. You may need to explore external plugins or create a custom solution to address your needs.

An example plugin like postcss-functions allows you to define a custom env function accessing environment variables.

In the postcss.config.js file:

const theme = Object.keys(process.env).reduce((accumulator, currentValue) => {
  if (currentValue.startsWith('NEXT_THEME_')) {
    accumulator[currentValue] = process.env[currentValue];
    return accumulator;
  }
  else {
    return accumulator
  }
}, {})

function getEnv(variable, fallback = null) {
  return theme[variable] ?? fallback;
}

module.exports = {
  "plugins": {
    "postcss-functions": {
      "functions": {
        getEnv
      }
    },
  }
}

You can now utilize this custom function within global.css as shown below:

@layer base {
  :root {
    --primary: getEnv(NEXT_THEME_PRIMARY_COLOR, #0096d0);
  }
}

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

Is there a way to resolve the issue with sequelize not running 'npx sequelize-cli db:migrate' command through docker-compose.yml?

Currently encountering the following issue: Sequelize CLI [Node: 21.7.1, CLI: 6.6.2, ORM: 6.37.1] | | Loaded configuration file "database/config/config.json". | Using environment "production". | ERROR: Access denied for user 'root ...

Need jQuery solution for changing CSS in numerous locations upon hover

Currently, I am working on a WordPress website and I am trying to figure out how to change the CSS color of a side navigation element when a remote image is hovered over. In a typical scenario, I would accomplish this using CSS by assigning a hover class ...

The scroll animation feature was not functioning properly in Next.js, however, it was working flawlessly in create react app

I recently transitioned a small project from Create React App (CRA) to Next.js. Everything is working as expected except for the scroll animations in Next.js, which are not functioning properly. There are no errors thrown; the animations simply do not occ ...

How can I modify the value of a CSS animation rule in AngularJS?

I am looking to dynamically change the value assigned to stroke-dashoffset based on a custom input. @-webkit-keyframes donut-chart-1 { to { stroke-dashoffset: 100; } } @keyframes donut-chart-1 { to { stroke-d ...

Next.JS Hydration Issue when using Trpc and React-Query (even when data is not being rendered)

const HomePage: NextPage = () => { const [showPublishedPosts, setShowPublishedPosts] = useState(false) const { data, isLoading } = trpc.item.getAllPosts.useQuery({ text: "from tRPC", filters: { showPublishedPosts: showPublishedP ...

Guide to dividing a URL in reactjs/nextjs

Here is the complete URL: /search-results?query=home+floor&categories=All+Categories. I am looking to separate it into two sections - /search-results and query=home+floor&categories=All+Categories. My objective is to extract the second part of t ...

Ensure that radio buttons are positioned next to their respective labels on separate lines

My HTML form is structured with sections as described below: I prefer having the labels inline to prevent the section from being excessively tall, but I'm facing an issue where the radio buttons are not staying aligned with their respective labels. ...

Incorporating descriptions below the images within this JavaScript carousel

I'm struggling to add text under the images in this slider. The functionality is simple, but I can't figure it out. I might have to rewrite it. Here's the HTML and JS: <div id="look-book-scroll"> <a href="javascript:;" id="lookbo ...

Elevate a div over another div

I have a situation where I need to nest two divs inside another div with the ID "video-wrapper". Here is the HTML code: <div class="row"> <div class="video-wrapper col-lg-2"> <div class="video-thumbnail"> <img ...

Tips for Creating a Responsive Homepage

I'm new to CSS and trying to create a responsive design for mobile IE. Currently, the page appears blank on IE but works fine on Google Chrome and other browsers :-) Here are the code snippets I have used: HTML: <div class="main"> <div ...

Vercel encountered issues with "validating code quality and type correctness" during deployment but was successful when performed locally

Running "next build" locally and "vercel build" both work smoothly. However, once deployed to vercel, the "Linting and checking validity of types" fails during the build process. It seems like TypeScript is stricter when building on vercel even with the sa ...

Pointer-enhanced Material UI Popup

Is there a way to implement a Popup that looks like the image provided using @Material-ui? https://material-ui.com/ I attempted to use Popover, however Popper does not include a pointer like in the image. https://i.stack.imgur.com/atz0G.png ...

Customizing font sizes for individual fonts within the same font family

I am designing a website in a language other than English. This means that the text on the webpage will be a mixture of English and other languages. In order to make sure the text displays correctly, I have set the font-family like this: p{ font-family: ...

Issue with FullPageJS: scrollOverflow feature not functioning upon click event

I am currently working on a Fullpage.js instance that needs to be initialized with a click event and then destroyed when switching to another page, and vice versa. The scrollOverflow feature works perfectly as long as the #fullpage element is not hidden up ...

Leveraging the "ActiveLink" feature within NextJS

I am currently browsing through this webpage: https://nextjs.org/docs/pages/api-reference/functions/use-router and I stumbled upon this block of code. import { useRouter } from 'next/router' function ActiveLink({ children, href }) { const rout ...

When deploying a Next.js app to a server, dynamic pages may not be accessible due to build configurations

I recently developed a webpage using Next.js (version 13.4.19) with dynamic routing functionality. While everything works perfectly on my local machine, I encountered an issue when trying to build the app as it failed to create dynamic pages. For reference ...

Struggle between Angular and fundamental CSS principles

Upon following the steps below, I aim to achieve my desired grids: How to set auto-margin boxes in flexible-width design using CSS? The solution provided is effective when implemented outside of Angular. However, when inserted inside an Angular component ...

Discovering the steps to showcase _app.tsx within next.js 13 through module federation

I am faced with a situation where I have two Next.js 13 projects: Homepage and Admin Panel. My goal is to showcase the entire Admin Panel (specifically _app.tsx) and embed it within Homepage. To achieve this, I have set up both projects utilizing @module-f ...

Switching image sources depending on CSS prefers-color-scheme: A guide

In my endeavor to incorporate the latest CSS prefers-color-scheme media query into my website, I encountered a challenge. I have an img (image) element featuring a very dark blue image, which clashes poorly with the new dark mode setting. Is there a simpl ...

Using GSAP to merge texts from left to right

I'm curious about the animation technique used by the developer to make his name come together from right to left. I'd love to try implementing it myself to improve my CSS skills. It looks like GSAP ScrollTrigger was involved in this animation, ...