项目中会经常使用css样式来修饰页面效果
也可以结合css预编译器进行使用
css预编译器(变量、嵌套、混入、函数) 最终要编译为css
常用css预编译器:
sass、scss是一种 scss是sass的第三个版本 编译器发生了改变 node-sass dart-sass
less
stylus
1、行内样式
使用标签的style属性,JSX语法中style属性的值的为对象结构,css属性的名称为大驼峰,如果值为非数字则使用引号包裹
import React, { Component } from 'react'
export default class App extends Component {
render() {
return (
// style行内样式
<div
style={{
border: '1px solid #ccc',
width: '25%',
marginTop: 10,
marginLeft: 10,
display: 'flex',
flexDirection:'column',
alignItems:'center'
}}
>
<div>名称:皮卡丘</div>
<div>技能:十万伏特</div>
<div>体态:黄色</div>
</div>
)
}
}
2、使用className属性
可以将样式进行抽离出来,并且可以进行复用。但是会存在样式污染的情况,也就是选择器名称不能够重名。
.card {
border: 1px solid #ccc;
width: 25%;
margin-top: 10px;
margin-left: 10px;
display: flex;
flex-direction: column;
align-items: center;
}
import React, { Component } from 'react'
import './index.css'
export default class App extends Component {
render() {
return (
<div>
<div className="card">
<div>名称:皮卡丘</div>
<div>技能:十万伏特</div>
<div>体态:黄色</div>
</div>
<Child></Child>
</div>
)
}
}
3、css module模块化
当然,在 vue 里可以选择 scoped css 或者 css modules,而在 react 里就只能用 css modules 了。
css modules 是通过 postcss-modules 这个包实现的,vite 也对它做了集成。
底层脚手架(webpack)在加载样式文件时,通过module模块化,编译后,把css选择器相同的生成一个唯一的名称,这样就可以避免由于选择名称相同,导致样式的覆盖和污染了。
src\Child.module.css
.card {
border: 1px solid red;
width: 25%;
margin-top: 10px;
margin-left: 10px;
display: flex;
flex-direction: column;
align-items: center;
}
src\Child.jsx
import React, { Component } from 'react'
//module模块化css后 实际文件会当做一个对象加载进来
import styles from './index.module.css'
export default class Child extends Component {
render() {
return <div className={styles.card}>Child</div>
}
}
不管是index.module.css还是index.module.scss,他们导入的时候,都需要又一个东西接受才能生效,这样导入(import 'index.module.css')是无效的。
正确使用方式:
import styles from './index.module.css'
同一个文件,不同组件使用,生成的hash值是一样的
测试如下
打包的时候,和其他样式打在一起
4、styled-components
在react中为了能够使样式进行动态变化,需要在js中完成css的设置。css-in-js技术,在react社区中有多种样式编写的方案。
styled-components是其中优秀方案之一,将样式同时编写在组件的jsx文件中,以达到编写和管理方便的情况。
继承、变量等写法
安装
npm i styled-components
src\App.js
import React, { Component } from 'react'
import Child from './Child'
// 1、引入styled-components 样式库
import styled from 'styled-components'
// 2、创建一个组件容器 并编写样式
const Card = styled.div`
border: 1px solid #ccc;
width: 25%;
margin-top: 10px;
margin-left: 10px;
display: flex;
flex-direction: column;
align-items: center;
`
export default class App extends Component {
render() {
return (
<div>
{/* 3、将编写好的组件样式 进行套用 和组件标签的使用方式基本一致 */}
<Card>
<div>名称:皮卡丘</div>
<div>技能:十万伏特</div>
<div>体态:黄色</div>
</Card>
<Child></Child>
</div>
)
}
}
样式继承和属性传递
import React, { Component } from 'react'
import styled from 'styled-components'
const Title = styled.div`
width: 200px;
height: 100px;
border: 1px solid black;
`
// 样式继承 将原有的样式进行复用 没有设置的复用 有设置的的以自身为准
const Title1 = styled(Title)`
height: 50px;
color: red;
`
// 属性传递 变量使用
const Color = styled.div`
color: ${(props) => props.color || 'red'};
`
export default class App extends Component {
render() {
return (
<div>
App
<Title>标题内容一</Title>
<Title1>标题内容二</Title1>
<Color>红色文字</Color>
<Color color="green">绿色文字</Color>
</div>
)
}
}
5、scss的使用
scss是成熟、稳定的流行的css预编译处理器
在react使用create-react-app脚手架中,内部已经将scss的样式编译配置完成,但是编译器的依赖需要自行安装。
安装sass编译器
npm i -D sass
src\App.scss
$pramiry-color: red;
.item {
display: flex;
justify-content: space-between;
padding: 5px;
// scss嵌套写法
> div:first-child {
width: 30%;
}
> div:nth-child(2) {
width: 60%;
margin-left: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
> div:first-child {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
> div:nth-child(2) {
// 变量使用
color: $pramiry-color;
}
}
}
src\App.js
import React, { Component } from 'react'
import './App.scss'
export default class App extends Component {
render() {
return (
<div className="item">
<div>
<img
src="http://dingyue.ws.126.net/2021/0201/b63f2e50j00qntwfh0020c000hs00npg.jpg?imageView&thumbnail=140y88&quality=85"
alt=""
/>
</div>
<div>
<div>被指偷拿半卷卫生纸 63岁女洗碗工服药自杀 酒店回应</div>
<div>2021-02-02 10:00:51</div>
</div>
</div>
)
}
}
6、less的使用
less支持浏览器和开发者服务器编译两种方式。
默认react脚手架create-react-app默认只支持scss,如果使用less需要解构配置文件,并安装编译器和加载器进行使用
npm i less -D
src\App.less
// 变量声明定义
@pramiry-color: red;
.item {
display: flex;
justify-content: space-between;
padding: 5px;
> div:first-child {
width: 30%;
}
> div:nth-child(2) {
width: 60%;
margin-left: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
> div:first-child {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
> div:nth-child(2) {
// 变量使用
color:@pramiry-color;
}
}
}
src/App.jsx
import React, { Component } from 'react'
import './App.less'
export default class App extends Component {
render() {
return (
<div className="item">
<div>
<img
src="http://dingyue.ws.126.net/2021/0201/b63f2e50j00qntwfh0020c000hs00npg.jpg?imageView&thumbnail=140y88&quality=85"
alt=""
/>
</div>
<div>
<div>被指偷拿半卷卫生纸 63岁女洗碗工服药自杀 酒店回应</div>
<div>2021-02-02 10:00:51</div>
</div>
</div>
)
}
}
sass和less在webpack里面都需要具体的加载器:sass-loader和less-loader,配置下就好了
7、tailwind的使用
tailwind它依赖postcss存在。
按照 tailwind 文档里的步骤安装 tailwind:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
会生成 tailwind 和 postcss 配置文件:
在tailwind.config.js
这个文件里,修改下 content
配置,也就是从哪里提取 className
:
javascript
复制代码
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
tailwind
会提取className
之后按需生成最终的 css。
改下index.css
引入 tailwind
基础样式:
@tailwind base;
@tailwind components;
@tailwind utilities;
在 main.tsx 里引入:
如果你没安装 tailwind 插件,需要安装一下:
这样在写代码的时候就会提示 className 和对应的样式值:
不知道 className 叫啥的样式,还可以在 tailwind 文档里搜:
注意: 安装 tailwind
以后请重启项目,才会生效,不然不会生效
8.Unocss
从官网我们可以看出,Unocss 将自己定位为一款原子化引擎,而不是像 TailwindCSS 那样只是一款 PostCSS 的插件,这说明 UnoCSS 不会依靠别的工具或者平台去执行,自己就可以完成像 TailwindCSS 那样的功能。
相比 TailwindCSS 来说,UnoCSS 扩展性和灵活性也更加强大,我们几乎不需要任何的配置就是可以完成原子化样式的生成。
npm install unocss @unocss/cli -D
创建文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="./dist/output.css" />
</head>
<body>
<div class="flex justify-center text-red p-100 m-0 text-lg">
hello, UnoCSS
</div>
</body>
</html>
编译
npx unocss ./index.html --out-file ./dist/output.css
在命令执行完成之后,就可在根目录下面生成一个 dist
文件夹,里面有一个 output.css
文件。
/* layer: preflights */
*,
::before,
::after {
--un-rotate: 0;
--un-rotate-x: 0;
--un-rotate-y: 0;
--un-rotate-z: 0;
--un-scale-x: 1;
--un-scale-y: 1;
--un-scale-z: 1;
--un-skew-x: 0;
--un-skew-y: 0;
--un-translate-x: 0;
--un-translate-y: 0;
--un-translate-z: 0;
--un-pan-x: ;
--un-pan-y: ;
--un-pinch-zoom: ;
--un-scroll-snap-strictness: proximity;
--un-ordinal: ;
--un-slashed-zero: ;
--un-numeric-figure: ;
--un-numeric-spacing: ;
--un-numeric-fraction: ;
--un-border-spacing-x: 0;
--un-border-spacing-y: 0;
--un-ring-offset-shadow: 0 0 rgb(0 0 0 / 0);
--un-ring-shadow: 0 0 rgb(0 0 0 / 0);
--un-shadow-inset: ;
--un-shadow: 0 0 rgb(0 0 0 / 0);
--un-ring-inset: ;
--un-ring-offset-width: 0px;
--un-ring-offset-color: #fff;
--un-ring-width: 0px;
--un-ring-color: rgb(147 197 253 / 0.5);
--un-blur: ;
--un-brightness: ;
--un-contrast: ;
--un-drop-shadow: ;
--un-grayscale: ;
--un-hue-rotate: ;
--un-invert: ;
--un-saturate: ;
--un-sepia: ;
--un-backdrop-blur: ;
--un-backdrop-brightness: ;
--un-backdrop-contrast: ;
--un-backdrop-grayscale: ;
--un-backdrop-hue-rotate: ;
--un-backdrop-invert: ;
--un-backdrop-opacity: ;
--un-backdrop-saturate: ;
--un-backdrop-sepia: ;
}
::backdrop {
--un-rotate: 0;
--un-rotate-x: 0;
--un-rotate-y: 0;
--un-rotate-z: 0;
--un-scale-x: 1;
--un-scale-y: 1;
--un-scale-z: 1;
--un-skew-x: 0;
--un-skew-y: 0;
--un-translate-x: 0;
--un-translate-y: 0;
--un-translate-z: 0;
--un-pan-x: ;
--un-pan-y: ;
--un-pinch-zoom: ;
--un-scroll-snap-strictness: proximity;
--un-ordinal: ;
--un-slashed-zero: ;
--un-numeric-figure: ;
--un-numeric-spacing: ;
--un-numeric-fraction: ;
--un-border-spacing-x: 0;
--un-border-spacing-y: 0;
--un-ring-offset-shadow: 0 0 rgb(0 0 0 / 0);
--un-ring-shadow: 0 0 rgb(0 0 0 / 0);
--un-shadow-inset: ;
--un-shadow: 0 0 rgb(0 0 0 / 0);
--un-ring-inset: ;
--un-ring-offset-width: 0px;
--un-ring-offset-color: #fff;
--un-ring-width: 0px;
--un-ring-color: rgb(147 197 253 / 0.5);
--un-blur: ;
--un-brightness: ;
--un-contrast: ;
--un-drop-shadow: ;
--un-grayscale: ;
--un-hue-rotate: ;
--un-invert: ;
--un-saturate: ;
--un-sepia: ;
--un-backdrop-blur: ;
--un-backdrop-brightness: ;
--un-backdrop-contrast: ;
--un-backdrop-grayscale: ;
--un-backdrop-hue-rotate: ;
--un-backdrop-invert: ;
--un-backdrop-opacity: ;
--un-backdrop-saturate: ;
--un-backdrop-sepia: ;
}
/* layer: default */
.m-0 {
margin: 0;
}
.flex {
display: flex;
}
.justify-center {
justify-content: center;
}
.p-100 {
padding: 25rem;
}
.text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
}
.text-red {
--un-text-opacity: 1;
color: rgb(248 113 113 / var(--un-text-opacity));
}
预览页面
相比 TailwindCSS,UnoCSS 使用起来确实更加的方便,它不需要我们再单独提供一个样式文件,也不需要创建任何的配置文件(当然,官方更建议我们作用配置文件)就可以生成我们想要的样式,而且只生成我们入口文件中所需要的样式,尽量减少包体积。
和 TailwindCSS 相比,我们通过上面的叙述也可以看出来几点不同。
- TailwindCSS 本质上是一款 PostCSS 插件,它运行需依赖 PostCSS ,而 UnoCSS 是一款引擎,无需借助任何其它工具或者平台即可执行构建。
presetUno
预设提供了一个包含 TailwindCS、WindiCSS、Boostrap 和 Tachyons
等框架的超集。我们通过配置文件可以配置预设。默认本来就有,你可以配置关闭也可以配置启用。
import { defineConfig, presetUno } from 'unocss'
export default defineConfig({
presets: [
presetUno()
]
})
如果我们想在 UnoCSS 中使用了一个预设中没有提供的样式该怎么办?比如说我起一个样式名为:aa-bb-cc
,这很明显在预设中没有,我们可以在配置文件中添加自定义 Rules
:
import { defineConfig } from 'unocss'
export default defineConfig({
// 配置自定义 rule
rules: [
['aa-bb-cc', {
'display': 'fixed',
'top': '10px',
'left': '10px'
}]
]
})
集成webpack
npm install -D @unocss/webpack @unocss/preset-uno
配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 引入 UnoCSS 依赖
const UnoCSS = require('@unocss/webpack').default
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
module: {
rules: [
{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
]
},
{
test: /.(scss|sass)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
},
{
test: /.(less)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'less-loader',
],
},
{
test: /.(styl)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'stylus-loader',
],
},
]
},
plugins: [
new MiniCssExtractPlugin(),
new HtmlWebpackPlugin({
template: 'index.html'
}),
// 配置 UnoCSS 插件
UnoCSS(),
],
};
然后我们再创建一个 uno.config.js
配置文件:
const { defineConfig } = require('@unocss/webpack')
const presetUno = require('@unocss/preset-uno')
module.exports = defineConfig({
content: {
pipeline: {
include: [
'src/**/*.{js,ts}',
],
},
},
presets: [
presetUno()
]
})
// 引入 uno.css
import 'uno.css'
import { sassComponent, lessComponent, stylusComponent } from "./component";
function component() {
const element = document.createElement('div');
element.id = 'app'
// 创建一个 div 用于显示,在添加上相关的样式
const unoElement = document.createElement('div')
unoElement.innerText = 'hello, Weback + UnoCSS'
unoElement.classList = ['text-red']
element.appendChild(unoElement)
return element;
}
document.body.appendChild(component());
vite集成
npm install -D unocss
vite配置文件
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 引入 UnoCSS 依赖
import unoCSS from 'unocss/vite'
// https://vitejs.dev/config/
export default defineConfig({
// 配置插件
plugins: [vue(), unoCSS()]
})
main。tsx
import { createApp } from 'vue'
import './style.css'
import './test.scss'
//引
import 'virtual:uno.css'
import App from './App.vue'
createApp(App).mount('#app')
9.提取共用样式
/* styles.css */
.text-blue {
color: blue;
}
.text-bold {
font-weight: bold;
}
export const sharedStyles = {
textBlue: 'text-blue',
textBold: 'text-bold',
};
在app.tsx文件里面使用
// MyComponent.js
import React from 'react';
import styles, { sharedStyles } from './styles.css';
const MyComponent = () => {
return (
<div className={styles[sharedStyles.textBlue]}>
This text is blue.
</div>
<div className={styles[sharedStyles.textBold]}>
This text is bold.
</div>
);
};
export default MyComponent;
10 提取样式变量
参考文章:www.jianshu.com/p/0099fd124…
创建一个CSS文件(例如styles.css
),并定义变量,:root是body的意思。
/* styles.css */
:root {
--primary-color: #3498db;
--font-size-large: 18px;
}
使用
// MyComponent.js
import React from 'react';
// 导入CSS变量文件
import './styles.css';
const MyComponent = () => {
return (
<div
style={{
color: 'var(--primary-color)',
fontSize: 'var(--font-size-large)',
}}
>
这是一个使用共用样式变量的组件。
</div>
);
};
export default MyComponent;
10.样式切换 利用classnames
import React, { useState } from 'react';
import classNames from 'classnames';
const ToggleButton = () => {
const [isToggled, setIsToggled] = useState(false);
const handleToggle = () => {
setIsToggled(!isToggled);
};
const buttonClass = classNames({
'btn': true,
'btn-active': isActive,
'btn-inactive': !isActive,
});
return (
<button className={buttonClass} onClick={handleToggle}>
{isToggled ? 'ON' : 'OFF'}
</button>
);
};
export default ToggleButton;