Logo
Section 1 / 3

React 中的 CSS

简要介绍样式技术以及在 React 中使用层叠样式表(CSS)的基础知识。

检查点

React 中的 CSS

简要介绍样式技术以及在 React 中使用层叠样式表(CSS)的基础知识。

React 应用有多种样式实现方式,关于最佳的样式策略和样式方法也存在长期争论。我们会介绍其中几种方法,但不会过度强调某一种。每种方法都有其优缺点,关键在于哪种更适合开发者或团队的实际需求。

我们将从 React 中常见的 CSS 开始,然后探讨两种更高级的方案:CSS-in-CSS(即 CSS Modules)和 CSS-in-JS(即 Styled Components)。需要注意的是,CSS Modules 和 Styled Components 只是这两类策略中的代表之一,并非唯一选择。此外,我们还会学习如何在 React 应用中引入可缩放矢量图形(SVG),例如 logo 或图标。

如果你不想从零开始构建通用 UI 组件(如按钮、对话框、下拉菜单等),可以选择一个适合 React 的流行 UI 库,这类库通常已内置这些组件。但为了更好地学习 React,建议先尝试自己实现这些组件,再使用现成的解决方案。因此,本教程中不会引入任何 UI 组件库。

以下提到的样式方案和 SVG 支持在 create-react-app 中已经预配置好。如果你自行管理构建工具(例如 Webpack),则可能需要手动配置以支持导入 CSS 或 SVG 文件。由于我们使用的是 create-react-app,因此可以直接将这些文件作为资源使用。

层叠样式表(CSS)

React 中的普通 CSS 与你可能已经学过的标准 CSS 非常相似。每个 Web 应用都会为 HTML 元素添加 class 属性(在 React 中写作 className),然后在对应的 CSS 文件中定义该类的样式。

1const App = () => { 2 ... 3 4 return ( 5 6 <div className="container"> 7 <h1 className="headline-primary">My Hacker Stories</h1> 8 9 10 <SearchForm 11 searchTerm={searchTerm} 12 onSearchInput={handleSearchInput} 13 onSearchSubmit={handleSearchSubmit} 14 /> 15 16 {stories.isError && <p>Something went wrong ...</p>} 17 18 {stories.isLoading ? ( 19 <p>Loading ...</p> 20 ) : ( 21 <List list={stories.data} onRemoveItem={handleRemoveStory} /> 22 )} 23 </div> 24 ); 25};

我们移除了 <hr /> 标签,因为接下来会通过 CSS 来处理边框样式。现在导入 CSS 文件,借助 create-react-app 的配置可以轻松完成:

1import React from 'react'; 2import axios from 'axios'; 3 4import './App.css';

这个 CSS 文件将定义我们在 App 组件中使用的两个或更多 CSS 类。请在你的 src/App.css 文件中按如下方式定义它们:

No configuration found for ID: 7089d0695563981856b5fb2aca3c2420141c119336d42b7b698e5b75e5598071

重新启动应用后,你应该能看到页面上的样式已生效。接下来我们进入 Item 组件。它的部分元素也添加了 className 属性,同时我们还将使用一种新的样式技术:

1const Item = ({ item, onRemoveItem }) => ( 2 3 <div className="item"> 4 <span style={{ width: '40%' }}> 5 6 <a href={item.url}>{item.title}</a> 7 </span> 8 9 <span style={{ width: '30%' }}>{item.author}</span> 10 <span style={{ width: '10%' }}>{item.num_comments}</span> 11 <span style={{ width: '10%' }}>{item.points}</span> 12 <span style={{ width: '10%' }}> 13 14 <button 15 type="button" 16 onClick={() => onRemoveItem(item)} 17 18 className="button button_small" 19 20 > 21 Dismiss 22 </button> 23 </span> 24 </div> 25);

可以看到,我们也可以使用原生的 style 属性来设置 HTML 元素的样式。在 JSX 中,style 属性接收一个内联的 JavaScript 对象。这种方式让我们可以在 JavaScript 文件中定义动态样式,而不是局限于静态的 CSS 文件。这种方法被称为内联样式,适用于快速原型开发和动态样式的场景。不过应谨慎使用内联样式,因为将其分离出来有助于保持 JSX 结构更简洁。

在 src/App.css 文件中定义新的 CSS 类。这里仅使用基础的 CSS 特性,不包含 CSS 扩展语言(如 Sass)中的高级功能(例如嵌套),因为这些属于可选配置。

No configuration found for ID: abad7b9cd704a8988932fbafdaa1432e06c2d4db222408fc5314c2c79d4c316e

之前组件中的按钮样式尚未定义,现在我们来添加一个基础按钮样式以及两个更具体的变体(小号和大号)。其中一个变体已被使用,另一个将在后续步骤中使用。

No configuration found for ID: 08fab764a7c4bf41a68474b660ae5158abfa444ed78196abdc1fc27c925fa3a5

除了样式方法外,命名规范(参考 CSS 编码指南)也是一个重要话题。上述 CSS 代码片段遵循 BEM 规范,使用下划线(_)表示类的修饰状态。你可以根据团队习惯选择合适的命名方式。接下来,我们继续为下一个 React 组件添加样式:

1const SearchForm = ({ ... }) => ( 2 3 <form onSubmit={onSearchSubmit} className="search-form"> 4 5 <InputWithLabel ... > 6 <strong>Search:</strong> 7 </InputWithLabel> 8 9 <button 10 type="submit" 11 disabled={!searchTerm} 12 13 className="button button_large" 14 > 15 Submit 16 </button> 17 </form> 18);

我们还可以将 className 作为属性传递给 React 组件。例如,可以通过 className 属性,从预定义的 CSS 类中灵活地为 SearchForm 组件指定样式。最后,为 InputWithLabel 组件添加样式:

1const InputWithLabel = ({ ... }) => { 2 ... 3 4 return ( 5 <> 6 7 <label htmlFor={id} className="label"> 8 9 {children} 10 </label> 11 &nbsp; 12 <input 13 ref={inputRef} 14 id={id} 15 type={type} 16 value={value} 17 onChange={onInputChange} 18 19 className="input" 20 21 /> 22 </> 23 ); 24};

在 src/App.css 文件中补充剩余的类定义:

No configuration found for ID: 95940e2d015a4035298bca53c8696b4ec5f64d4190e63631cd960b42fd332279

为简化起见,我们在 src/App.css 文件中单独对 label 和 input 等元素进行了样式设置。

但在实际项目中,更好的做法是在 src/index.css 文件中全局定义这些基础元素的样式。随着 React 组件被拆分到多个文件中,共享样式变得必不可少。

以上就是大多数人都学过的基础 CSS,配合更具动态性的内联样式一起使用。如果没有 Sass(Syntactically Awesome Style Sheets)这类 CSS 扩展的支持,内联样式可能会变得繁琐,因为原生 CSS 不支持嵌套等高级特性。

No configuration found for ID: a7b28a09f24c9795c39ed3d268a4994ade6f076c045d19fb22e5961b8ef80231

练习:

  • 确认并查看上一节以来的所有变更。
  • 阅读更多关于 create-react-app 中的 CSS 样式表 的内容。
  • 了解如何在 create-react-app 中使用 Sass,以便利用嵌套等更高级的 CSS 功能。
  • 尝试从 App 组件向 SearchForm 组件传递 className 属性,值设为 button_small 或 button_large,并在按钮元素上应用该类名。

Quiz

单选题

使用内联样式属性为元素设置样式时,其值必须是一个 JavaScript 对象。

1 / 1

附录

React 中的 CSS 模块