Tailwind CSS v3——核心思想(二)状态变量与暗夜模式
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
系列文章可以查看《Tailwind》专栏
参考:
状态变量
通过在基础类前添加相应的状态变量,如类似于伪类选择器的字符串,悬停 hover
、聚焦 focus
等,并用冒号 :
分隔,即可设置相应状态下元素的样式。
Tailwind 提供了多种常见的状态变量:
- 和伪类选择器相对应的状态变量,如
hover
、focus
、first-child
、required
- 和伪元素选择器相对应的状态变量,如
before
、after
、selection
、placeholder
- 媒体查询相关的状态变量,如
sm
(尺寸)、dark
(暗夜模式)、prefers-reduced-motion
(动画模式) - 特定元素的专属特性相关的状态变量,如
<details>
或<dialog>
元素在 open state 展开状态的样式设置可以使用状态变量open
、字体排列顺序 RTL 或 LTR 可以使用状态属性rtl
和ltr
表示
💡 Tailwind 默认提供的所有状态变量,可以查看的官方文档
💡 这些的样式设置方式都是 inline-style 无法实现的。而且这些状态属性可以「叠加」使用,来为元素设置在特定的几个状态同时触发时的样式
<!-- 鼠标在按钮上悬停时,颜色变深 -->
<!-- 在暗夜模式开启且鼠标在按钮上悬停时,颜色变浅 -->
<button class="bg-teal-500 hover:bg-teal-600 dark:hover:bg-teal-300">Sign Up</button>
根据它们的先后「叠加」次序,会生成嵌套的选择器,类似于嵌套函数。一般情况下「叠加」的状态变量的次序并无关紧要,但是有一些特殊例外?
// These modifiers:
'dark:group-hover:focus:opacity-100'
// ...are applied like this:
dark(groupHover(focus('opacity-100')))
💡 所有基础类,包括自定义的基础类,都支持和状态变量配合使用
/* 📄 main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer utilities {
.content-auto {
content-visibility: auto;
}
}
<div class="lg:content-auto">
<!-- ... -->
</div>
伪类状态变量
-
hover
、focus
、active
、visited
、focus-within
、focus-visible
等状态变量,一般用于设定按钮、表单等元素的相应状态的样式<!-- 当鼠标悬停在按钮时,背景色变浅 --> <!-- 当点击按钮时,背景色变深 --> <!-- 当按钮被聚焦时,没有默认的聚焦样式,换为自定义的样式 --> <button class="bg-violet-500 hover:bg-violet-400 active:bg-violet-600 focus:outline-none focus:ring focus:ring-violet-300 ..."> Save changes </button>
-
first
、last
状态变量一般用于父元素,用以设置第一或最后一个子元素的样式;odd
、even
状态变量一般用于表格元素,用以设置奇数行或偶数行的样式。<table> <!-- ... --> <tbody> {#each people as person} <!-- Use a white background for odd rows, and gray-100 for even rows --> <tr class="odd:bg-white even:bg-gray-100"> <td>{person.name}</td> <td>{person.title}</td> <td>{person.email}</td> </tr> {/each} </tbody> </table>
💡 此外还有其他的一些不常用的表示 DOM 元素结构的状态变量:
only
用以设置当该元素内只有一个子元素的状态下的样式
<ul> {#each people as person} <li class="py-4 only:py-0 ..."> <!-- ... --> </li> {/each} </ul>
first-of-type
用以设置当该元素是同类型的标签中,作为其父元素的第一个子元素的状态下的样式。另一个先对的状态变量是last-of-type
;还有作为其父元素的同类型标签唯一一个子元素的状态变量only-of-type
。
<div> <p class>first paragraph</p> <p>second paragraph</p> </div>
empty
用以设置当元素中没有内容时的样式(不仅没有子元素,也没有文本内容)
<ul> {#each people as person} <li class="empty:hidden ...">{person.hobby}</li> {/each} </ul>
-
required
、valid
、invalid
、disabled
、checked
等状态变量一般用于设置表单元素在特定情况下的样式。💡 还包括一些不常用的状态变量:
default
用以设置下拉菜单的选项元素、复选框、单选按钮的默认值被加载时的表单元素的样式read-only
用以设置只读表单元素的样式autofill
用以设置具有自动填充属性的表单元素(它具有autocomplete
特性)的样式placeholder-shown
用以设置当占位符 placeholder 存在时表单元素的样式in-range
和out-of-range
用以分别设置输入值在范围内或在范围外时表单元素的样式<input min="1" max="5" class="in-range:border-green-500 ..." />
indeterminate
用以设置单选按钮或复选框在不确定时的表单元素的样式<input type="checkbox" class="appearance-none indeterminate:bg-gray-300 ..." />
除了基于元素自身的不同状态设置样式,还可以基于该元素的父元素的不同状态、或兄弟元素的不同状态设置样式
-
group-{modifier}
状态变量用以设置子元素在父元素处于特定状态时样式,例如group-hover
状态变量是设置当鼠标悬停在父元素(含有类名group
)时,该子元素的样式<!-- 父元素具有类名 group --> <a href="#" class="group ..."> <!-- 子元素/目标元素具有状态变量 group-hover --> <p class="group-hover:text-white text-sm ...">sub element</p> </a>
💡
group-{modifier}
其中modifier
是一种伪类状态变量,表示父元素所处的状态,例如group-focus
、group-active
、group-odd
-
peer-{modifier}
状态变量用以设置该元素在兄弟元素(含有类名peer
)处于特定状态时样式,<form> <label class="block"> <!-- 兄弟元素具有类名 peer --> <input type="email" class="peer ..."/> <!-- 目标元素具有状态变量 peer-invalid --> <!-- 当以上的表单输入非法值时,该提示信息才会显示 --> <p class="invisible peer-invalid:visible ..."> Please provide a valid email address. </p> </label> </form>
🎬 这个视频教程就是使用该状态变量实现 floating labels 浮动标签的效果。
伪元素状态变量
-
before
和after
状态变量用于设置伪元素:before
和:after
的样式 💡 其中采用content: ''
空字符串作为伪元素内容的默认值,如果希望设置内容可以采用before:content-[*]
的形式,这是在元素前添加*
字符串作为伪元素。<label class="block"> <span class="after:content-['*'] after:ml-0.5 after:text-red-500 ..."> Email </span> <input type="email" name="email" class="..." /> </label>
-
placeholder
状态变量为<input type="text"/>
和<textarea></textarea>
元素的占位符设置样式<label class="relative block"> <input class="placeholder:italic placeholder:text-gray-400 ... placeholder="Search for anything..." type="text" name="search"/> </label>
-
file
状态变量为<input type="file">
文件选择表单元素设置样式<form class="flex items-center space-x-6"> <label class="block"> <span class="sr-only">Choose profile photo</span> <input type="file" class="... file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-violet-50 file:text-violet-700 hover:file:bg-violet-100 "/> </label> </form>
💡 由于 Tailwind 的样式重置 base reset 并不会应用到
<input type="file">
元素的按钮的边框属性上,所以一般需要显式地来设置border
相关的样式,以保持设计的统一性<input type="file" class="file:border file:border-solid ..." />
-
marker
状态变量用以设置列表的各项前的标识样式<ul role="list" class="marker:text-sky-400 ..."> <li>5 cups chopped mushrooms</li> <li>1/2 cup of olive oil</li> <li>3lb of celery</li> </ul>
💡 该状态变量可以用在
<ul>
或<ol>
列表元素上来统一设置列表项的样式;也可以单独应用在<li>
元素上,分别设置该列表项的样式 -
selection
状态变量用以设置选中的文本的样式<div class="selection:bg-fuchsia-300 selection:text-fuchsia-900"> <p> So I started to walk into the water. </p> </div>
💡 一般将该状态变量设置的基础类用于
<body>
元素以设置全局的选中文本的样式 -
first-line
和first-letter
状态变量分别用于设置文本的首行或首个字母的样式<p class="first-line:uppercase first-line:tracking-widest first-letter:text-7xl first-letter:font-bold first-letter:text-gray-900 first-letter:mr-3 first-letter:float-left "> Well, let me tell you something, funny boy. Y'know that little stamp, the one that says "New York Public Library"? Well that may not mean anything to you, but that means a lot to me. One whole hell of a lot. </p>
媒体相关的状态变量
-
Tailwind 提供了五个默认的断点
sm
、md
、lg
、xl
、2xl
这些状态变量用以设置在页面满足一定宽度时才应用的样式 -
dark
用以设置当媒体特性 prefers-color-scheme 为 dark 时(即系统的主题色设置为暗色)元素的样式 -
motion-reduce
用以设置当媒体特性 prefers-reduced-motion 为 reduce 时(即系统将动画效果最小化,以获得更好的性能)元素的样式,一般该状态变量用来覆盖/取消 undo那些「性能耗费高」的动效相关的样式;还有一个相对的状态变量motion-safe
用于设置样式,一般是「性能耗费高」的动效相关的样式,它们在媒体特性 prefers-reduced-motion 不为 reduce 时才会被应用<!-- Using `motion-reduce` can mean lots of "undoing" styles --> <button class="hover:-translate-y-0.5 transition motion-reduce:hover:translate-y-0 motion-reduce:transition-none ..."> Save changes </button> <!-- Using `motion-safe` is less code in these situations --> <button class="motion-safe:hover:-translate-x-0.5 motion-safe:transition ..."> Save changes </button>
-
portrait
和landscape
状态变量分别用于设置当屏幕方向为纵向或横向时元素的样式 -
print
状态变量用于设置元素在打印时的样式,可以用print:hidden
基础类来实现在打印时隐藏某些元素的功能
特性相关的状态变量
-
rtl
和ltr
状态变量分别用于设置当页面的文本显示模式为从右到左 RTL(默认情况)或从左到右 LTR 时元素的样式💡 如果希望
ltr
状态变量所设置的样式生效,需要指定元素的属性dir
为ltr
(可以在页面的根元素<html>
中进行设置) -
open
状态变量用于设置<details>
或<dialog>
元素为展开状态时(具有open
特定)的样式<div class="max-w-lg mx-auto p-8"> <details class="open:bg-white ... open"> <summary class="..."> Why do they call it Ovaltine? </summary> <div class="..."> <p>The mug is round. The jar is round. They should call it Roundtine.</p> </div> </details> </div>
自定义状态变量
除了内置的状态变量,Tailwind 还支持自定义状态变量 state variants。
使用 plugins
模块在 Tailwind 的配置文件 tailwind.config.js
中定制 modifier
// 📄 tailwind.config.js
// 导入插件模块
const plugin = require('tailwindcss/plugin');
module.exports = {
// ...
plugins: [
// 创建一个名为 third 状态变量
// 用以匹配第三个子元素设置其样式
plugin(function ({ addVariant }) {
// Add a `third` variant, ie. `third:pb-0`
addVariant('third', '&:nth-child(3)')
})
]
}
暗夜模式
Tailwind 提供了 dark
状态变量,用以设置暗夜模式下元素的样式。
可以有两种方式来开启暗夜模式
-
默认是基于媒体查询
prefers-color-scheme
的结果为dark
时(即系统开启了暗夜模式时),来决定是否采用暗夜模式下的样式。 -
如果希望给用户主动权,可以在页面手动切换日间或暗夜模式,可以在 Tailwind CSS 的配置文件
tailwind.config.js
中将属性darkMode
设置为使用class
策略,而不是默认的基于媒体查询 prefers-color-scheme(即系统设置)的media
模式module.exports = { darkMode: 'class', // ... }
页面还需要添加相应的 JS 脚本,一般是监听按钮点击事件,控制页面根元素 <html>
的类名 dark
的增删,以实现切换 toggle 日间模式与暗夜模式
// 以下代码兼容了随系统切换和让用户主动切换日间、暗夜模式的功能
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
// Whenever the user explicitly chooses light mode
localStorage.theme = 'light'
// Whenever the user explicitly chooses dark mode
localStorage.theme = 'dark'
// Whenever the user explicitly chooses to respect the OS preference
localStorage.removeItem('theme')
然后会根据页面的根元素 <html>
中是否具有类名 dark
而决定是否将暗夜模式的样式应用于元素。
<!-- Dark mode not enabled -->
<html>
<body>
<!-- Will be white -->
<div class="bg-white dark:bg-black">
<!-- ... -->
</div>
</body>
</html>
<!-- Dark mode enabled -->
<html class="dark">
<body>
<!-- Will be black -->
<div class="bg-white dark:bg-black">
<!-- ... -->
</div>
</body>
</html>
转载自:https://juejin.cn/post/7072173545874260005