Tailwind CSS 任意值语法和选择器详解
目录
基础概念
什么是任意值语法?
Tailwind CSS 的任意值语法允许你在类名中直接使用任意 CSS 值,而不需要修改配置文件。使用方括号 [] 来包裹任意值。
基本格式
tsx
<div className="[属性名:值]">...</div>
任意值语法
1. 自定义属性值
tsx
// 自定义宽度
<div className="[width:500px]">...</div>
// 自定义颜色
<div className="[color:rgb(255,0,0)]">...</div>
// 自定义背景色
<div className="[background:linear-gradient(to_right,#ff0000,#00ff00)]">...</div>
// 自定义字体大小
<div className="[font-size:18px]">...</div>
2. 使用 CSS 变量
tsx
<div className="[color:var(--primary-color)]">...</div>
<div className="[background:var(--bg-gradient)]">...</div>
3. 组合使用
tsx
<div className="[width:500px] [height:300px] [background:#f0f0f0]">...</div>
选择器语法
基础选择器语法
使用 & 代表当前元素,_ 代表空格(后代选择器)。
格式说明
[&选择器]:工具类
&→ 当前元素_→ 空格(后代选择器).class→ 类选择器#id→ ID 选择器tag→ 标签选择器
实际案例解析
案例 1: 我们的实际应用
tsx
<div className="[&_.react-json-view_span.string-value]:break-all">
拆解:
&→ 当前 div 元素_→ 空格(后代选择器).react-json-view→ 类名为react-json-view的元素_→ 空格(后代选择器)span.string-value→ 既是span标签又有string-value类的元素
等价于 CSS:
css
div .react-json-view span.string-value {
word-break: break-all;
}
HTML 结构:
html
<div class="[&_.react-json-view_span.string-value]:break-all">
<div class="react-json-view">
<span class="string-value">很长的字符串...</span>
</div>
</div>
更多选择器示例
1. 直接子元素选择器
tsx
// 使用 > 表示直接子元素
<div className="[&>button]:bg-red-500">
<button>按钮1</button> {/* 会应用样式 */}
<div>
<button>按钮2</button> {/* 不会应用样式 */}
</div>
</div>
等价于 CSS:
css
div > button {
background-color: rgb(239 68 68);
}
2. 伪类选择器
tsx
// hover 状态
<div className="[&_button:hover]:bg-blue-500">
<button>悬停我</button>
</div>
// focus 状态
<input className="[&:focus]:ring-2 [&:focus]:ring-blue-500" />
// active 状态
<button className="[&:active]:scale-95">点击我</button>
// disabled 状态
<button className="[&:disabled]:opacity-50" disabled>禁用按钮</button>
3. 伪元素选择器
tsx
// before 伪元素
<div className="[&::before]:content-[''] [&::before]:block [&::before]:w-4 [&::before]:h-4 [&::before]:bg-red-500">
内容
</div>
// after 伪元素
<div className="[&::after]:content-['→'] [&::after]:ml-2">
内容
</div>
4. 属性选择器
tsx
// 根据属性选择
<input className="[&[type='text']]:border-2" type="text" />
<input className="[&[type='email']]:border-blue-500" type="email" />
// 根据 data 属性选择
<div className="[&[data-active='true']]:bg-green-500" data-active="true">
激活状态
</div>
5. 组合选择器
tsx
// 多个类名组合
<div className="[&_.btn.primary]:bg-blue-500">
<button class="btn primary">按钮</button>
</div>
// 标签和类名组合
<div className="[&_span.text-red]:text-red-500">
<span class="text-red">红色文本</span>
</div>
// ID 选择器
<div className="[&_#my-button]:bg-yellow-500">
<button id="my-button">按钮</button>
</div>
6. 相邻兄弟选择器
tsx
// 使用 + 表示相邻兄弟
<div className="[&_h1+p]:mt-4">
<h1>标题</h1>
<p>这段文字会有上边距</p>
<p>这段文字不会有上边距</p>
</div>
等价于 CSS:
css
div h1 + p {
margin-top: 1rem;
}
7. 通用兄弟选择器
tsx
// 使用 ~ 表示通用兄弟
<div className="[&_h1~p]:text-gray-500">
<h1>标题</h1>
<p>这段文字是灰色</p>
<div>中间内容</div>
<p>这段文字也是灰色</p>
</div>
8. 第一个/最后一个子元素
tsx
// 第一个子元素
<div className="[&>:first-child]:pt-0">
<p>第一个,没有上边距</p>
<p>第二个,有默认边距</p>
</div>
// 最后一个子元素
<div className="[&>:last-child]:pb-0">
<p>第一个</p>
<p>最后一个,没有下边距</p>
</div>
// nth-child
<div className="[&>:nth-child(2)]:bg-yellow-500">
<p>第一个</p>
<p>第二个,黄色背景</p>
<p>第三个</p>
</div>
9. 条件选择器
tsx
// 当元素有特定类时
<div className="[&.active]:bg-blue-500">
内容
</div>
// 当父元素有特定类时
<div className="parent">
<div className="[.parent_&]:bg-red-500">
当父元素有 parent 类时,这个元素会有红色背景
</div>
</div>
10. 媒体查询
tsx
// 响应式设计
<div className="[&_button]:text-sm md:[&_button]:text-base lg:[&_button]:text-lg">
<button>响应式按钮</button>
</div>
实际应用示例
示例 1: 自定义组件样式覆盖
tsx
// 覆盖第三方组件样式
<div className="[&_.react-json-view_span.string-value]:break-all">
<ReactJson data={data} />
</div>
示例 2: 表单样式定制
tsx
<form className="[&_input:focus]:ring-2 [&_input:focus]:ring-blue-500 [&_input:invalid]:border-red-500">
<input type="email" required />
<input type="text" />
</form>
示例 3: 列表样式
tsx
<ul className="[&_li:not(:last-child)]:border-b [&_li:hover]:bg-gray-100">
<li>项目 1</li>
<li>项目 2</li>
<li>项目 3</li>
</ul>
示例 4: 卡片交互效果
tsx
<div className="[&_button:hover]:scale-105 [&_button:active]:scale-95 [&_button:disabled]:opacity-50">
<button>可交互按钮</button>
<button disabled>禁用按钮</button>
</div>
示例 5: 嵌套组件样式
tsx
<div className="[&_.card]:shadow-lg [&_.card:hover]:shadow-xl [&_.card_title]:text-xl">
<div className="card">
<h2 className="title">卡片标题</h2>
<p>卡片内容</p>
</div>
</div>
常见用法
1. 修改子元素样式
tsx
// 所有子按钮
<div className="[&_button]:px-4 [&_button]:py-2 [&_button]:bg-blue-500">
<button>按钮1</button>
<button>按钮2</button>
</div>
2. 响应式设计
tsx
<div className="[&_img]:w-full md:[&_img]:w-1/2 lg:[&_img]:w-1/3">
<img src="..." alt="..." />
</div>
3. 暗色模式支持
tsx
<div className="[&_p]:text-gray-800 dark:[&_p]:text-gray-200">
<p>这段文字在暗色模式下会变亮</p>
</div>
4. 打印样式
tsx
<div className="print:[&_button]:hidden print:[&_nav]:hidden">
<button>打印时隐藏</button>
<nav>打印时隐藏</nav>
</div>
5. 组合多个选择器
tsx
<div className="
[&_h1]:text-2xl
[&_h2]:text-xl
[&_p]:text-base
[&_a]:text-blue-500
[&_a:hover]:underline
">
<h1>标题1</h1>
<h2>标题2</h2>
<p>段落 <a href="#">链接</a></p>
</div>
注意事项
1. 选择器优先级
tsx
// 更具体的选择器优先级更高
<div className="[&_button.primary]:bg-blue-500 [&_button]:bg-red-500">
<button class="primary">蓝色背景(更具体)</button>
<button>红色背景</button>
</div>
2. 性能考虑
虽然任意值语法很方便,但过度使用可能会影响性能。建议:
- 优先使用 Tailwind 内置的工具类
- 只在必要时使用任意值语法
- 对于复杂的样式,考虑使用 CSS 模块或 styled-components
3. 可维护性
tsx
// ❌ 不推荐:过于复杂
<div className="[&_div>span:first-child+span:not(.disabled):hover]:bg-red-500">
...
</div>
// ✅ 推荐:清晰简洁
<div className="[&_span.active:hover]:bg-red-500">
...
</div>
总结
Tailwind CSS 的任意值语法提供了强大的灵活性,允许你:
- ✅ 使用任意 CSS 值
- ✅ 编写复杂的选择器
- ✅ 覆盖第三方组件样式
- ✅ 保持代码在同一个文件中
- ✅ 利用 Tailwind 的响应式和暗色模式功能
记住关键语法:
[]- 任意值语法&- 当前元素_- 空格(后代选择器)>- 直接子元素+- 相邻兄弟~- 通用兄弟