如何在 React 应用程序中使用 CSS 模块应用全局样式?

Posted

技术标签:

【中文标题】如何在 React 应用程序中使用 CSS 模块应用全局样式?【英文标题】:How to apply global styles with CSS modules in a react app? 【发布时间】:2017-02-09 20:37:27 【问题描述】:

我目前正在使用带有 React 的 CSS 模块来进行样式设置。所以我的每个组件都在其组件特定的 css 文件中导入,如下所示:

import React from 'react';
import styles from './App.css';

const example = () => (
  <div className=styles.content>
    Hello World!
  </div>
);

export default example;

这在对单个组件进行样式设置时效果很好,但是如何应用非组件特定的全局样式(html、正文、标题标签、div 等)?

【问题讨论】:

为什么不在你的根组件中require('./App.css'); 【参考方案1】:

我可以说的最佳实践应该是有一个 CSS 文件夹,您可以在其中保存整个应用程序所需的所有 CSS,就像我需要的所有组件中的字体大小为 20 一样,因此需要按照以下步骤操作:

创建一个名为 css/scss 的单独文件夹(首选 scss)。 创建文件name _font.scss。 创建一个文件name index.scssimport _font.scssindex.scss (@import './fonts';)。 将此导入您的 index.js 起始文件 (import "../scss/index.scss")。 现在您可以在整个应用程序中使用您的 CSS。

在这种情况下,您可能会发现重复。例如 - 您在全局范围内创建了一个文件的容器 CSS,但您希望为您的文件之一创建一个单独的容器

这种情况为此应用程序创建一个单独的 css/scss 文件,名称应该类似于 (cssname.module.scss) 必须包含 .module 以便更好地处理。

使用这个 css 你可以导入你的 jsx 文件 (import Style from './cssname.module.scss')

你可以使用className= Style.container 但是如果你想同时使用一些全局和本地 css 从 npm (npm install classNames) 安装类名

使用方法:

import cn from 'Classnames'
className = cn(Style.container,"fs-20 text-center")

这里 fs-20 和 text-center 是您的某些文件中存在的全局 CSS

【讨论】:

感谢您分享原始发帖者问题的答案。请注意正确格式化答案。如需进一步帮助,请参阅以下降价指南:***.com/editing-help【参考方案2】:

如果你想使用 css 模块,另一种简单的方法是:

<style jsx global>`
     .slick-prev:before,
     .slick-next:before 
         color: somecolor;
      
`</style>

【讨论】:

【参考方案3】:

解决方案 1:

reactapp的起点导入全局样式。 整个 react 应用程序在 root 组件中是 wrapped。 可以是index.jsapp.jsindex.html

解决方案 2:

使用scss 并创建main.scss 文件并导入 main.scss 中所有其他特别需要的custom scss 文件

【讨论】:

【参考方案4】:

我也遇到了同样的问题,找到了以下方法来解决这个问题,你可以选择最适合你的方法

    在你的 webpack 配置中定义两组规则来解析 css/less 文件。 第一条规则应该是包含所有全局样式, 假设它保存在 /styles/ 或类似目录中。 第二条规则是处理所有本地范围的 css 样式,理想情况下,这些样式应位于其组件旁边。 您可以通过在定义规则时使用包含和排除选项来做到这一点 或通过强制执行命名约定并相应地编写规则,例如所有 css 模块将是 [name].module.css 并且您的测试将检查 /.module.(less |css)$/ 并解析它。

下面给出一个示例:

      // exclude all global styles for css modules
      
        test: /\.(less|css)$/,
        exclude: path.resolve(__dirname, './src/styles'),
        use: [
          
            loader: CssExtractPlugin.loader,
            options:  hot: is_dev, reloadAll: is_dev 
          ,
          
            loader: "css-loader",
            options:  
                modules:  
                    localIdentName: '[local]___[hash:base64:5]'
                
            
          ,
          "postcss-loader",
          "less-loader"
        ]
      ,
      // process global styles without css modules
     
        test: /\.(less|css)$/,
        include: path.resolve(__dirname, './src/styles'),
        use: [
          
            loader: CssExtractPlugin.loader,
            options:  hot: is_dev, reloadAll: is_dev 
          ,
          "css-loader",
          "postcss-loader",
          "less-loader"
        ]
      
    在编写 css/less 时使用 :local 和 :global。如果启用 css 模块,它将默认为本地模式,您可以在选项中指定模式,如下所示:
          
            loader: "css-loader",
            options:  
                modules:  
                    localIdentName: '[local]___[hash:base64:5]', 
                    mode: 'global',
                
            
          ,

如果您将模式定义为全局,那么所有包含的 css 类都不会被散列名称替换,而是只有您指定为 :local 的类将被赋予唯一名称。例如:

/* this will remain as is */
.header 
   color: blue;


:local 
  /* this will become something like item_xSH2sa */
  .item 
   color: yellow;
  


    定义一个函数来检查您的文件以确定它是 css 模块还是全局,使用 getLocalIdent 选项完成。这是我目前在我的设置中使用的方法。这也要求你的文件有一些命名约定,[name].module.less 用于 css 模块,[name].less 用于常规文件。 请参见下面的示例:
// regex to test for modules, loaderUtils is part of webpack dependencies
const cssModuleRegex = new RegExp(/\.module\.(less|css)$/);
const loaderUtils = require("loader-utils");

// inside webpack rules
      
        test: /\.(less|css)$/,
        use: [
          
            loader: CssExtractPlugin.loader,
            options:  hot: is_dev, reloadAll: is_dev 
          ,
          
            loader: "css-loader",
            options:  
                modules:  
                    localIdentName: '[local]___[hash:base64:5]', 
                    getLocalIdent: getLocalIdent
                
            
          ,
          "postcss-loader",
          "less-loader"
        ]
      

// this is a copy of the default function, modified slightly to achieve our goal
function getLocalIdent(loaderContext, localIdentName, localName, options) 

    // return local name if it's a global css file
    if (!cssModuleRegex.test(loaderContext.resourcePath)) 
        return localName;
    

    if (!options.context) 
      // eslint-disable-next-line no-param-reassign
      options.context = loaderContext.rootContext;
    

    const request = path
      .relative(options.context, loaderContext.resourcePath)
      .replace(/\\/g, '/');

    // eslint-disable-next-line no-param-reassign
    options.content = `$options.hashPrefix + request+$localName`;

    // eslint-disable-next-line no-param-reassign
    localIdentName = localIdentName.replace(/\[local\]/gi, localName);

    const hash = loaderUtils.interpolateName(
      loaderContext,
      localIdentName,
      options
    );

    return hash
      .replace(new RegExp('[^a-zA-Z0-9\\-_\u00A0-\uFFFF]', 'g'), '-')
      .replace(/^((-?[0-9])|--)/, '_$1');
  

【讨论】:

最后的解决方案是魅力,感谢分享!【参考方案5】:

我发现全局导入样式但仅适用于特定路线的唯一方法是添加:

<style dangerouslySetInnerHTML=__html: `
  body  max-width: 100% 
` />

render方法的返回内。

否则,style 标记将添加到 &lt;head&gt;,并且样式将应用于所有后续路由。

来自https://medium.learnreact.com/the-style-tag-and-react-24d6dd3ca974

也许可以将样式作为字符串从文件中导入,以使代码更有条理。

【讨论】:

【参考方案6】:

由于您使用的是 ES6 导入语法,因此您可以使用相同的语法来导入样式表

import './App.css'

另外,你可以用 :global 包裹你的类来切换到全局范围(这意味着 CSS 模块不会修改它,例如:在它旁边添加一个随机 id)

:global(.myclass) 
  background-color: red;

【讨论】:

对我来说,像import './App.css' 这样导入的文件中的类名根本没有任何作用。它仅适用于您的第二段代码。这是我第一次遇到这种“css 模块”的东西,我已经讨厌它破坏了几千年来有用的东西。 @MikhailBatcer 我也发生了同样的事情。事实上,我必须使用命名导入然后应用类。 import classes from './App.css' 然后申请classes.Myclass @FaizanMubasher 是的,命名导入也对我有用。 @felixyadomi 非常感谢!这绝对是我想要的!【参考方案7】:

这可以通过简单地添加:

require('./App.css');

(感谢@elmeister 正确回答了这个问题。)

【讨论】:

或者为了避免es模块和commonjs混在一起,import './App.css' @riscarrott 是的,但是您需要按照***.com/questions/39805537/…命名导入

以上是关于如何在 React 应用程序中使用 CSS 模块应用全局样式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 中组合多个类名?

在 React 中如何只导入需要的 Bootstrap 样式。引导 css 模块?

如何使用 CSS 模块在 React 中设置子组件的样式

在 React 应用程序中使用启用 CSS 模块的 PrimeReact 主题

如何在 React 16.13.1 中启用 CSS 模块?

如何使用 Typescript、React 和 Webpack 导入 SCSS 或 CSS 模块