likes
comments
collection
share

Tailwind CSS v3——核心思想(二)状态变量与暗夜模式

作者站长头像
站长
· 阅读数 74

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情


系列文章可以查看《Tailwind》专栏


参考:

状态变量

通过在基础类前添加相应的状态变量,如类似于伪类选择器的字符串,悬停 hover、聚焦 focus 等,并用冒号 : 分隔,即可设置相应状态下元素的样式

Tailwind 提供了多种常见的状态变量:

💡 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>

伪类状态变量

  • hoverfocusactivevisitedfocus-withinfocus-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>
    
  • firstlast 状态变量一般用于父元素,用以设置第一或最后一个子元素的样式;oddeven 状态变量一般用于表格元素,用以设置奇数行或偶数行的样式。

    <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>
    
  • requiredvalidinvaliddisabledchecked 等状态变量一般用于设置表单元素在特定情况下的样式。

    💡 还包括一些不常用的状态变量:

    • default 用以设置下拉菜单的选项元素、复选框、单选按钮的默认值被加载时的表单元素的样式
    • read-only 用以设置只读表单元素的样式
    • autofill 用以设置具有自动填充属性的表单元素(它具有 autocomplete 特性)的样式
    • placeholder-shown 用以设置当占位符 placeholder 存在时表单元素的样式
    • in-rangeout-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-focusgroup-activegroup-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 浮动标签的效果。

    Tailwind CSS v3——核心思想(二)状态变量与暗夜模式

伪元素状态变量

  • beforeafter 状态变量用于设置伪元素 :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-linefirst-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 提供了五个默认的断点 smmdlgxl2xl 这些状态变量用以设置在页面满足一定宽度时才应用的样式

  • 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>
    
  • portraitlandscape 状态变量分别用于设置当屏幕方向为纵向或横向时元素的样式

  • print 状态变量用于设置元素在打印时的样式,可以用 print:hidden 基础类来实现在打印时隐藏某些元素的功能

特性相关的状态变量

  • rtlltr 状态变量分别用于设置当页面的文本显示模式为从右到左 RTL(默认情况)或从左到右 LTR 时元素的样式

    💡 如果希望 ltr 状态变量所设置的样式生效,需要指定元素的属性 dirltr(可以在页面的根元素 <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
评论
请登录