如何在 React 中优雅的写 CSS?CSS作用域隔离

24 篇文章 4 订阅
20 篇文章 0 订阅

目录

方案一: namespaces

方案二:CSS in JS

1. styled-jsx

2. styled-components

安装

全局样式

局部(组件)样式

方案三:CSS Modules


用了 React 很久了,关于 react 中 css 作用域隔离一直不爽,这里总结一下在 React 中 优雅的写css。

  • 方案一:namespaces
  • 方案二:CSS in JS
  • 方案三:CSS Modules

方案一: namespaces

利用约定好的命名来隔离 CSS 的作用域。这种方式不多加描述,大家都懂。

方案二:CSS in JS

目前的 CSS in JS 的第三方库有60余种,介绍两款我在使用的库

  • styled-jsx
  • styled-components

1. styled-jsx

 我在之前的文章中有写过它,你可以参阅

在 create-react-app 中使用 styled-jsx_五虎战画戟-CSDN博客yarn add react-app-rewired customize-cra在 package.json 中替换/* package.json */ "scripts": {- "start": "react-scripts start",+ "start": "react-app-rewired start",- "build": "react-scripts build",+ "build": "react-app-rewired build",- ".https://blog.csdn.net/qq_41887214/article/details/120523661语法:

import React from "react";
 
export default () => {
  return (
    <div className='container'>
      <section className='main'>
        <h1>111111</h1>
      </section>
 
      <style jsx>{`
        .container {
          height: 100vh;
          background: royalblue;
        }
        .main {
          height: 300px;
          background: #61dafb;
        }
      `}</style>
    </div>
  );
}

缺点:但是 styled-jsx 的缺点在于,它无法修改第三方UI组件的样式,这让我很痛心。当我要修改第三方UI组件时只能用 css namespaces 使用

优点:但是优点也很明显,语法和 css 一致,没有学习成本

2. styled-components

安装

npm install --save styled-components

全局样式

// style.js
import { createGlobalStyle } from 'styled-components'

export const GlobalStyle = createGlobalStyle`
  html, body, div, span, applet, object, iframe,
  h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  a, abbr, acronym, address, big, cite, code,
  del, dfn, em, img, ins, kbd, q, s, samp,
  small, strike, strong, sub, sup, tt, var,
  b, u, i, center,
  dl, dt, dd, ol, ul, li,
  fieldset, form, label, legend,
  table, caption, tbody, tfoot, thead, tr, th, td,
  article, aside, canvas, details, embed, 
  figure, figcaption, footer, header, hgroup, 
  menu, nav, output, ruby, section, summary,
  time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
  }
  /* HTML5 display-role reset for older browsers */
  article, aside, details, figcaption, figure, 
  footer, header, hgroup, menu, nav, section {
    display: block;
  }
  body {
    line-height: 1;
  }
  ol, ul {
    list-style: none;
  }
  blockquote, q {
    quotes: none;
  }
  blockquote:before, blockquote:after,
  q:before, q:after {
    content: '';
    content: none;
  }
  table {
    border-collapse: collapse;
    border-spacing: 0;
  }
`;

项目入口文件index.js中加载全局样式 style.js

import React from 'react';
import ReactDOM from 'react-dom';
import { GlobalStyle} from './style.js';
import App from './App';

ReactDOM.render(
  <>
    <GlobalStyle/>
    <App/>
  </>,
  document.getElementById('root')
);

局部(组件)样式

对于一个特定的组件,我们可以事先在render函数中,用组件的命名方式替换原本的div等标签

import React, {Component} from 'react'
import {
  HeaderWrapper,
  Nav,
  NavItem
} from './style'

class Header extends Component {
  render() {
    return (
      <HeaderWrapper>
        <Nav>
          <NavItem className='left active'>首页</NavItem>
          <NavItem className='left'>下载App</NavItem>
          <NavItem className='right'>登陆</NavItem>
          <NavItem className='right'>
            <span className='icon'>😄😄</span>
          </NavItem>
        </Nav>       
      </HeaderWrapper>
    )
  }
}

export default Header

然后在同目录下的style.js中编写具体的CSS样式,以组件名的形式导出

import styled from 'styled-components'

export const HeaderWrapper = styled.div`
  position: relative;
  margin: 0;
  padding: 0;
  height: 58px;
  border-bottom: 1px solid #f0f0f0
`;

export const Nav = styled.div`
  width: 945px;
  height: 100%;
  padding-right: 70px;
  box-sizing: border-box;
  margin: 0 auto;
  display: flex;
  justify-content: space-around;

`

export const NavItem = styled.div`
  line-height: 56px;
  padding: 0 15px;
  font-size: 17px;
  color: #333;

`

缺点:

1. jsx 中的原生标签不能一眼看出来,额外增加了标签变量

2. 使用不方便,与平时html + css 开发习惯相差较大

3. 也不能用来修改第三方组件样式

优点:

1. 样式写在 js 文件里,降低 js 对 css 文件的依赖。

2. 样式可以使用变量,更加灵活。

3. 使用方便,不需要配置 webpack、开箱即用。

4. SSR 类框架处理 CSS Modules 变量相当棘手,所以使用 styled-components 作方案

方案三:CSS Modules

利用 webpack 等构建工具使 class 作用域为局部。CSS 依然是还是 CSS

npm i -D style-loader css-loader

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
        ],
      },
    ],
  },
};

modules 更具体的配置项参考:css-loader | webpack 中文文档

loader 会用唯一的标识符 (identifier) 来替换局部选择器。所选择的唯一标识符以模块形式暴露出去。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: {
                mode: 'local',
                // 样式名规则配置
                localIdentName: '[name]__[local]--[hash:base64:5]',
              },
            },
          },
        ],
      },
    ],
  },
};

App.js

...
import styles from "./App.css";
...
<div>
  <header className={styles["header__wrapper"]}>
    <h1 className={styles["title"]}>标题</h1>
    <div className={styles["sub-title"]}>描述</div>
  </header>
</div>

App.css

.header__wrapper {
  text-align: center;
}

.title {
  color: gray;
  font-size: 34px;
  font-weight: bold;
}

.sub-title {
  color: green;
  font-size: 16px;
}

编译后的 CSS,class 增加了 hash 值。

.App__header__wrapper--2_jgY {
  text-align: center;
}

.App__title--GpMto {
  color: gray;
  font-size: 34px;
  font-weight: bold;
}

.App__sub-title--1cIFi {
  color: green;
  font-size: 16px;
}

优点:解决了css局部作用域和模块依赖, 没有改造CSS,上手成本小,简单易用

缺点:对于不会webpack配置的同学有一定起步成本,但你可以参考我的webapck专栏教程https://blog.csdn.net/qq_41887214/category_10668880.html

参阅:

CSS Modules 用法教程 - 阮一峰的网络日志

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__畫戟__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值