源本科技 | 码上会

Tailwind CSS 交互设计

2026/03/12
8
0

学习目标

  • 掌握 Hover (悬停) 状态的设计原则,利用颜色和变换提供即时视觉反馈。

  • 深入理解 Focus (焦点) 管理,构建符合无障碍标准(Accessibility)的表单和导航体验。

  • 熟练运用 Active (激活) 状态模拟物理按压感,提升按钮的触觉反馈。

  • 正确处理 Disabled (禁用) 状态,通过样式和光标明确告知用户元素不可用。

  • 学会自定义 Cursor (光标)User Select (文本选择),优化特定场景下的用户操作体验。

  • 能够组合多种交互状态,制作出专业、流畅且易于访问的 UI 组件。


悬停状态

悬停是桌面端交互的核心,用于提示用户“此元素可点击”或展示更多细节。

核心用法

  • 颜色变化: hover:bg-blue-700, hover:text-white, hover:border-red-500

  • 组合变换: 常与 transitiontransform 配合,如 hover:scale-105

  • 伪类链式调用: Tailwind 允许链式使用,如 group-hover: (父元素悬停时触发子元素变化)。

代码示例

按钮与卡片悬停效果

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Tailwind Auto Cols 对比演示</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>
    <div class="p-8 bg-gray-50 space-y-8">

        <!-- 场景 1: 基础按钮悬停 -->
        <div class="flex flex-wrap gap-4">
            <button
                class="px-6 py-2 bg-blue-600 text-white font-medium rounded-lg transition-colors duration-200 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
                标准悬停 (Hover Color)
            </button>

            <button
                class="px-6 py-2 bg-white text-gray-700 border border-gray-300 font-medium rounded-lg shadow-sm transition-all duration-200 hover:bg-gray-50 hover:shadow-md hover:-translate-y-0.5">
                立体悬停 (Hover Lift)
            </button>
        </div>

        <!-- 场景 2: 卡片悬停 (Group Hover) -->
        <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
            <div
                class="group bg-white rounded-xl shadow-md overflow-hidden cursor-pointer transition-shadow duration-300 hover:shadow-xl">
                <div class="h-40 bg-gray-200 relative overflow-hidden">
                    <img src="https://zhanweifu.com/600x400/cccccc/ffffff" alt="Card Image"
                        class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110">
                    <!-- 悬停时显示的遮罩 -->
                    <div
                        class="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
                        <span
                            class="text-white font-bold px-4 py-2 border border-white rounded-full transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300">查看详情</span>
                    </div>
                </div>
                <div class="p-4">
                    <h3 class="font-bold text-gray-900 group-hover:text-blue-600 transition-colors">项目标题</h3>
                    <p class="text-sm text-gray-500 mt-1">鼠标悬停时,图片放大,遮罩浮现,标题变色。</p>
                </div>
            </div>
        </div>

    </div>
</body>

</html>

焦点管理

焦点状态对于键盘导航用户至关重要。忽略焦点样式会导致键盘用户无法知道当前选中了哪个元素。

核心用法

  • 移除默认轮廓: focus:outline-none (慎用,必须替换为自定义样式)。

  • 自定义光环: focus:ring-2, focus:ring-blue-500, focus:ring-offset-2

  • 环的位置: focus:ring 默认在元素内部,focus:ring-offset 可以在元素和外环之间创造间隙。

代码示例

表单输入框的焦点优化

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Tailwind Auto Cols 对比演示</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>
    <div class="p-8 bg-white rounded-xl shadow max-w-md space-y-6">

        <h3 class="text-lg font-bold text-gray-800">表单焦点演示</h3>

        <!-- 场景 1: 错误的做法 (移除了 outline 但没有替代) -->
        <div class="space-y-2">
            <label class="block text-sm font-medium text-gray-700">错误示范 (无焦点样式)</label>
            <input type="text" class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none"
                placeholder="按 Tab 键试试...">
            <p class="text-xs text-red-500">警告:键盘用户无法看到此输入框是否被选中!</p>
        </div>

        <!-- 场景 2: 标准做法 (自定义 Ring) -->
        <div class="space-y-2">
            <label class="block text-sm font-medium text-gray-700">标准示范 (Ring + Offset)</label>
            <input type="text"
                class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:border-transparent transition-shadow"
                placeholder="按 Tab 键试试...">
            <p class="text-xs text-green-600">清晰可见的蓝色光环,且与原边框有间隙。</p>
        </div>

        <!-- 场景 3: 不同颜色的焦点 -->
        <div class="space-y-2">
            <label class="block text-sm font-medium text-gray-700">成功状态焦点</label>
            <input type="text" value="验证通过"
                class="w-full border border-green-300 bg-green-50 text-green-900 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2">
        </div>

    </div>
</body>

</html>

激活状态

active 状态仅在鼠标按下(未松开)或触摸屏触摸时生效,用于提供“被按下”的即时反馈。

核心用法

  • 颜色加深: active:bg-blue-800 (比 hover 更深)。

  • 尺寸缩小: active:scale-95 (模拟按钮被压下去的物理形变)。

  • 阴影消失: active:shadow-inneractive:shadow-none

代码示例

具有触感的按钮

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Tailwind Auto Cols 对比演示</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>
    <div class="p-8 bg-gray-100 flex flex-wrap gap-6 justify-center">

        <!-- 场景 1: 颜色反馈 -->
        <button
            class="px-6 py-3 bg-indigo-600 text-white font-bold rounded-lg shadow-md transition-colors duration-100 hover:bg-indigo-700 active:bg-indigo-900">
            颜色加深 (Active Darker)
        </button>

        <!-- 场景 2: 物理按压感 (推荐组合) -->
        <button
            class="px-6 py-3 bg-emerald-600 text-white font-bold rounded-lg shadow-md transition-all duration-100 hover:shadow-lg hover:-translate-y-0.5 active:shadow-none active:translate-y-0 active:scale-95">
            物理按压 (Scale Down)
        </button>

        <!-- 场景 3: 内部凹陷感 -->
        <button
            class="px-6 py-3 bg-amber-500 text-white font-bold rounded-lg border-b-4 border-amber-700 active:border-b-0 active:translate-y-1 transition-all duration-75">
            复古凹陷 (Border Trick)
        </button>

    </div>
</body>

</html>

禁用与光标

明确告知用户某些操作当前不可用,避免无效点击。

禁用状态

  • 样式: disabled:opacity-50, disabled:grayscale

  • 交互: disabled:cursor-not-allowed, disabled:pointer-events-none (彻底禁止点击事件穿透)。

  • 注意: HTML 原生 disabled 属性会使表单元素无法提交,但普通 <div><a> 标签没有 disabled 属性,需靠 JS 控制类名或使用 aria-disabled

光标类型

  • cursor-pointer: 手型,表示可点击。

  • cursor-wait: 沙漏 / 旋转圈,表示加载中。

  • cursor-not-allowed: 禁止符号,表示不可操作。

  • cursor-default: 默认箭头。

  • cursor-text: 工字型,表示可选中文本。

代码示例

表单禁用与加载状态

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Tailwind Auto Cols 对比演示</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>
    <div class="p-8 bg-white rounded-xl shadow space-y-8">

        <!-- 场景 1: 禁用按钮 -->
        <div class="flex gap-4 items-center">
            <button disabled
                class="px-6 py-2 bg-blue-600 text-white font-medium rounded-lg disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none">
                提交表单 (Disabled)
            </button>
            <span class="text-sm text-gray-500">无法点击,光标显示为禁止符号。</span>
        </div>

        <!-- 场景 2: 加载状态光标 -->
        <div class="flex gap-4 items-center">
            <button class="px-6 py-2 bg-gray-800 text-white font-medium rounded-lg cursor-wait flex items-center gap-2">
                <svg class="animate-spin h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none"
                    viewBox="0 0 24 24">
                    <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                    <path class="opacity-75" fill="currentColor"
                        d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
                    </path>
                </svg>
                处理中...
            </button>
            <span class="text-sm text-gray-500">光标变为等待状态 (cursor-wait)。</span>
        </div>

        <!-- 场景 3: 文本选择控制 -->
        <div class="border p-4 rounded bg-gray-50">
            <p class="mb-2 font-bold text-gray-700">文本选择控制:</p>
            <p class="select-text mb-2">这段文字可以被正常选中 (select-text)。</p>
            <p class="select-none mb-2 user-select-none bg-yellow-100 p-2 rounded">这段文字无法被选中
                (select-none),常用于防止用户误选图标或按钮文字。</p>
            <p class="select-all bg-blue-50 p-2 rounded">点击这里会全选整段文字 (select-all)。</p>
        </div>

    </div>
</body>

</html>