首页 > 解决方案 > 样式化的组件,两层 className - 如何在组件声明中应用样式?

问题描述

我在 next.js 中创建了一个带有组件样式的 Container 组件。当我在整个站点中声明使用此容器组件时,我想为其添加一个 className 并根据其使用的上下文对其进行主观样式设置。

这是我的 Container 组件的示例:

    const Container = (props) => (
    <>
        <div className="container">
            {props.children}
        </div>

        <style jsx>{`
            .container{
                width: 100%;
                max-width: 1200px;
                margin: 0 auto;
            }
        `}</style>
    </>
)

export default Container;

所以,我想给它1200px的最大宽度,并用自动边距居中。没问题,我已经做到了。

现在,我打算在我的网站标题中使用这个组件。但在标题的情况下,我希望 Container 组件是一个 flexbox:

import Container from './Container'

const Header = (props) => (
    <>
        <header>
            <Container className="header-col">
                <div>
                    <h1>{props.title}</h1>
                </div>
                <nav>
                    <ul>
                        {/* Navigation items */}
                    </ul>
                </nav>
            </Container>
        </header>

        <style jsx>{`
            .header-col{
                display: flex;
                justify-content: space-between;
            }
        `}</style>
    </>
)

export default Header;

当我查看该站点时,我注意到我在标题中为 Container 组件指定的 flexbox 样式不存在。

我期待 className 生效,并允许我添加其他样式。

我相信这与认为 className 不是类名,而是道具有关。但是,我想通过在组件上创建样式继承来保持我的代码干燥。

我怎么能这样做?

谢谢您的帮助!

标签: cssreactjsnext.jsstyles

解决方案


这是样式化组件的工作:

import React from "react";
import styled from "styled-components";

export default function App() {
  return (
    <>
      <Container custom={"header"}>
        <h1>Very fancy h1 with flex display</h1>
      </Container>
      <Container custom={"regular"}>
        <h1>Non-fancy h1 with no flex display</h1>
      </Container>
    </>
  );
}

const Container = styled.div`
  display: ${(props) => (props.custom === "header" ? "flex" : "block")};
  /* you can call your prop ^^^^^^ whatever you want, 
  just change it on the container element too*/

  & h1 {
    /* you can apply css to children like so */

    font-family: ${(props) =>
      props.custom === "header"
        ? '"Courier New", Courier, monospace'
        : '"Arial Black", Gadget, sans-serif'};
  }
`;

在上面,我创建了一个自定义样式组件,它接收custom道具,然后有条件地更改您要调整的值。为了使更改更直观,我还设置了字体样式,以便您可以看到两个<Container>元素之间的直接区别。


对于更具可扩展性的解决方案(例如,对于不同的主题),请使用ThemeProvider

import React from "react";
import styled, { ThemeProvider } from "styled-components";

export default function App() {
  return (
    <>
      <ThemeProvider theme={ContainerHeader}>
        <Container>
          <h1>Very fancy h1 with flex display</h1>
        </Container>
      </ThemeProvider>
      <Container theme={"regular"}>
        <h1>Non-fancy h1 with no flex display</h1>
      </Container>
    </>
  );
}

const Container = styled.div`
  display: ${(props) => props.theme.display};
  & h1 {
    font-family: ${(props) => props.theme.h1Font};
  }
`;

Container.defaultProps = {
  theme: {
    display: "block",
    h1Font: '"Arial Black", Gadget, sans-serif'
  }
};

const ContainerHeader = {
  display: "flex",
  h1Font: '"Courier New", Courier, monospace'
};

CodeSandbox:https ://codesandbox.io/s/stack-conditional-styled-components-vmnpn?file=/src/App.js:0-773


推荐阅读