样式被Material-UI样式覆盖 [英] Styles being overwritten by Material-UI style

查看:132
本文介绍了样式被Material-UI样式覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

序言

我问了类似的问题追溯到这几天,尽管本质上是相关的,但我认为解决方案最终将有所不同,因此我在不同的话题中再次提出疑问.

I asked a similar question to this several days back and while related in nature I believe the solution will ultimately be different, so I am asking again in a different thread.

CodeSanbox 示例(已更新以反映已接受的答案)

CodeSanbox Example (Has Been updated to reflect the accepted answer)

问题:

我希望通过className道具传递的任何外部样式都比我的自定义组件内部样式具有更高的特异性.这样,使用它的人就可以调整边距和填充.但是,我组件的默认内部样式会覆盖我的外部样式,我希望反之亦然.

I'd like any external styles passed in with the className prop to have higher specificity than my custom components internal style. That way someone using it can adjust margins and padding. However, my components default internal style is overwriting my external style and I would like it to be the other way around.

详细信息:

我正在创建一个基于material-ui的自定义组件库.我想使自定义组件api与@material-ui类似,以便我们的开发人员可以更轻松地使用它们.我正在构建的每个组件都具有其自己的内部样式,该样式将覆盖默认的material-ui样式,在这种情况下,它定义为类button.另外,像@material-ui一样,我接受颜色道具<TestButton color={'default'}/>.最后,如果需要,我希望可以使用外部样式覆盖自定义按钮.我正在使用clsx库来构建className字符串.

I am creating a custom component library built on top of material-ui. I'd like to make the custom components api similar to @material-ui so that our devs will find them easier to use. Each component I am building has it's own internal style overwriting the default material-ui styles in this case it is defined as class button. Additionally, like @material-ui I am accepting a color prop <TestButton color={'default'}/>. Finally, I'd like my custom button to be allowed to be overwritten with external styles if the need ever arises. I am using the clsx library to build the className strings.

代码:

import React, { useState } from "react";
import { makeStyles } from "@material-ui/styles";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import { Button } from "@material-ui/core";
import clsx from "clsx";

const useAppStyles = makeStyles({
  gButton: { margin: "150px" }
});

export default function App() {
  const classes = useAppStyles();

  return (
    <div className={classes.example}>
      <div className={classes.separator}>
        <div>Buttons:</div>
        <TestButton
          className={classes.gButton}
          color={"default"}
        >
          Default
        </TestButton>
        <TestButton
          className={classes.gButton}
          color={"primary"}
        >
          Primary
        </TestButton>
    </div>
  );
}

function TestButton(props) {

  const classes = GrangeButtonStyles();
  let color = props.color === 'default' ? classes.default : classes.primary 

  const GrangeButtonStyles = makeStyles({
    button: {
     height: "45px",
     padding: "13px 30px 13px 30px",
     borderRadius: "5px",
     border: "none",
     margin: "15px",
    },
    default: {
     backgroundColor: "black",
     border: 'solid #2e7d32 1px',
     color: "white",
    },
    primary: {
     backgroundColor: 'white',
     color: 'black',
     fontFamily: 'Montserrat, sans-serif',
     border: 'solid black 1px',
    }
  });

  return (
    <Button
      className={clsx(classes.button, color, props.className)}
      variant="contained"
      disabled={props.disabled}
      disableElevation
    >
      {props.children}
    </Button>
  );
}

注意:

在这个问题和代码沙箱示例中,我大大简化了空间代码.请不要发表评论,因为这个例子,您认为我在做什么并没有意义.

I have simplified the code greatly for space in this question and in the code sandbox example. Please don't comment that you think what I'm doing doesn't make sense because of the example.

推荐答案

来自

当多个声明具有相同的特异性时,将在CSS中找到的最后一个声明应用于该元素.

When multiple declarations have equal specificity, the last declaration found in the CSS is applied to the element.

因此,在您要在自定义组件(例如TestButton)和使用该组件的代码中定义CSS类的情况下,其特异性取决于这些CSS类在<head>中出现的顺序.元素.此顺序由

So in your case where you are defining CSS classes in your custom component (e.g. TestButton) and in the code that uses that component, the specificity is determined by the order in which those CSS classes appear within the <head> element. This order is determined by an index that is set when makeStyles is called, so classes defined by later calls to makeStyles will appear later in the <head> element and thus have greater specificity.

在您的示例中有两个问题:

There are two issues then in your example:

  1. TestButton是在使用它的代码之后定义的,因此在makeStyles调用之后定义了旨在覆盖TestButton中的样式的样式.由于对gButtonmakeStyles调用首先发生,因此相应的CSS类将首先在<head>元素中.但是,在实际使用中,TestButton(您的自定义组件)将在单独的文件中定义并导入.由于导入必须位于最顶层,因此在使用导入的组件对文件中的任何makeStyles调用之前,将执行导入文件的所有makeStyles顶级调用.

  1. TestButton is defined after the code that uses it and therefore after the makeStyles call that is defining styles intended to override styles in TestButton. Since the makeStyles call for gButton occurs first, the corresponding CSS class will be first in the <head> element. In real-world usage though, TestButton (your custom component) would be defined in a separate file and be imported. Since imports have to be at the top, any makeStyles calls at the top level of the imported file will be executed before any makeStyles calls in the file using the imported component.

TestButtonmakeStyles调用不是在最顶层完成的.相反,它是在TestButton函数内部完成的,这意味着它将在呈现TestButton时而不是在导入TestButton时执行.对makeStyles的调用应始终位于顶层,而不是嵌套在组件函数中.另一个较小的问题是从makeStyles返回的变量的名称(在您的示例中为GrangeButtonStyles).由于makeStyles返回自定义钩子,因此您应始终以"use"开头的名称(例如useGrangeButtonStyles).这样可以确保挂钩的限制规则将其识别为挂钩并警告您任何钩子滥用.

The makeStyles call for TestButton is not being done at the top level. Instead it is being done inside the TestButton function which means it will be executed when TestButton is rendered instead of when TestButton is imported. Calls to makeStyles should always be at the top level rather than nested within a component function. One other minor issue is the name of the variable returned from makeStyles (i.e. GrangeButtonStyles in your example). Since makeStyles returns a custom hook, you should always have a name that starts with "use" (e.g. useGrangeButtonStyles). This will ensure that the eslint rules for hooks recognize it as a hook and warn you of any hook misuse.

相关答案和参考文献:

  • Material UI v4 makeStyles exported from a single file doesn't retain the styles on refresh
  • Internal implementation of "makeStyles" in React Material-UI?
  • https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity

这篇关于样式被Material-UI样式覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆