CSS :focus-within `:has,selection等伪类

发布于:2025-06-26 ⋅ 阅读:(20) ⋅ 点赞:(0)

CSS :focus-within 伪类详解

:focus-within 是一个CSS伪类,它表示一个元素自身或其后代元素获得焦点时的状态。这个选择器非常有用,可以在子元素获得焦点时对父元素或祖先元素应用样式。

基本语法

element:focus-within {
  /* 样式规则 */
}

工作原理

当以下情况发生时,元素会匹配 :focus-within

  1. 元素本身获得焦点
  2. 元素的任何后代元素获得焦点

这与 :focus 伪类不同,后者只在元素本身获得焦点时匹配。

使用示例

1. 表单输入时高亮整个容器

<div class="form-group">
  <label for="name">姓名:</label>
  <input type="text" id="name">
</div>

<style>
.form-group {
  padding: 10px;
  border: 1px solid #ccc;
  transition: all 0.3s;
}

.form-group:focus-within {
  border-color: #4a90e2;
  box-shadow: 0 0 5px rgba(74, 144, 226, 0.5);
}
</style>

2. 导航菜单下拉框

<nav>
  <ul>
    <li class="dropdown">
      <a href="#">菜单</a>
      <ul class="dropdown-menu">
        <li><a href="#">选项1</a></li>
        <li><a href="#">选项2</a></li>
      </ul>
    </li>
  </ul>
</nav>

<style>
.dropdown-menu {
  display: none;
}

.dropdown:focus-within .dropdown-menu {
  display: block;
}
</style>

3. 搜索框扩展效果

<div class="search-container">
  <input type="text" placeholder="搜索...">
  <button>搜索</button>
</div>

<style>
.search-container {
  width: 200px;
  transition: width 0.3s;
}

.search-container:focus-within {
  width: 300px;
}
</style>

浏览器支持

:focus-within 在现代浏览器中有很好的支持:

  • Chrome 60+
  • Firefox 52+
  • Safari 10.1+
  • Edge 79+
  • Opera 47+

对于不支持的浏览器,可以使用JavaScript polyfill或替代方案。

:focus 的区别

特性 :focus :focus-within
触发条件 仅元素本身获得焦点 元素本身或任何后代获得焦点
应用范围 单个元素 整个祖先链
冒泡效果
动态样式 有限 更灵活

实际应用场景

  1. 表单增强:当表单中的任何输入框获得焦点时,高亮整个表单区域
  2. 无障碍设计:更明显地显示当前焦点所在区域
  3. 交互反馈:为用户提供更直观的操作反馈
  4. 下拉菜单:替代传统的:hover实现,提高移动设备兼容性

注意事项

  1. 性能考虑:过度使用可能导致重绘和回流
  2. 特异性:focus-within的特异性与类选择器相同(0,1,0)
  3. 键盘导航:确保与键盘导航良好配合
  4. 视觉反馈:不要仅依赖颜色变化,要考虑色盲用户

兼容性解决方案

对于不支持 :focus-within 的浏览器,可以使用JavaScript实现类似效果:

// 简单的polyfill
document.addEventListener('focusin', function(event) {
  let target = event.target;
  while (target !== document.body) {
    target.classList.add('focus-within');
    target = target.parentNode;
  }
});

document.addEventListener('focusout', function(event) {
  let target = event.target;
  while (target !== document.body) {
    target.classList.remove('focus-within');
    target = target.parentNode;
  }
});

然后使用CSS:

.focus-within {
  /* 替代:focus-within的样式 */
}

:focus-within 是一个强大的CSS伪类,可以极大地增强用户界面的交互性和可访问性,特别是在表单和复杂交互组件中。

CSS :has() 伪类详解

:has() 是一个功能强大的CSS伪类,它允许开发者选择包含特定子元素或满足特定条件的父元素。这个选择器被称为"父选择器"或"反向选择器",因为它可以选择基于后代元素的祖先元素。

基本语法

parent:has(child) {
  /* 样式规则 */
}

/* 更复杂的例子 */
element:has(selector1, selector2, ...) {
  /* 样式规则 */
}

工作原理

:has() 伪类匹配满足以下条件的元素:

  • 包含与括号内选择器匹配的子元素
  • 包含与括号内选择器匹配的后代元素
  • 满足括号内指定的任何条件

使用示例

1. 选择包含特定子元素的父元素

/* 选择包含<img>子元素的<figure>元素 */
figure:has(img) {
  border: 1px solid #ccc;
  padding: 10px;
}

/* 选择包含.active类子元素的列表项 */
li:has(.active) {
  font-weight: bold;
}

2. 表单验证样式

/* 当包含无效输入时,给表单组添加红色边框 */
.form-group:has(:invalid) {
  border: 1px solid red;
}

/* 当复选框被选中时,改变标签样式 */
label:has(input:checked) {
  color: blue;
  font-weight: bold;
}

3. 复杂布局调整

/* 如果卡片包含图片,调整布局 */
.card:has(.card-image) {
  display: flex;
  flex-direction: column;
}

/* 当导航有下拉菜单时,添加指示箭头 */
nav:has(ul ul)::after {
  content: "▼";
  margin-left: 5px;
}

浏览器支持

:has() 伪类的浏览器支持情况:

  • Chrome 105+(2022年8月起)
  • Safari 15.4+(2022年3月起)
  • Edge 105+
  • Firefox 121+(2023年12月起)

对于不支持 :has() 的浏览器,需要使用JavaScript替代方案或渐进增强策略。

与其它选择器的比较

选择器 功能 方向性
A B 选择A元素内的所有B元素 向下
A > B 选择A元素的直接子元素B 向下
A + B 选择紧接在A元素后的B元素 同级
A ~ B 选择A元素之后的所有同级B元素 同级
A:has(B) 选择包含B元素的A元素 向上

实际应用场景

  1. 条件性布局:根据内容调整布局

    /* 如果文章有目录,调整布局 */
    article:has(.toc) {
      display: grid;
      grid-template-columns: 200px 1fr;
    }
    
  2. 状态指示:基于子元素状态改变父元素样式

    /* 当列表项包含已完成的任务时 */
    li:has(.task.completed) {
      opacity: 0.6;
    }
    
  3. 增强交互:响应用户操作

    /* 当鼠标悬停在子元素上时改变父元素 */
    .card:has(button:hover) {
      transform: scale(1.02);
    }
    

性能考虑

虽然 :has() 非常强大,但需要注意:

  1. 计算成本高:浏览器需要检查DOM的更多部分
  2. 避免过度使用:在大型DOM树上频繁使用可能影响性能
  3. 特异性:has() 的特异性等于其参数中最具体的选择器

兼容性解决方案

对于不支持 :has() 的浏览器:

JavaScript替代方案

// 为包含特定子元素的元素添加类
document.querySelectorAll('parent').forEach(parent => {
  if (parent.querySelector('child')) {
    parent.classList.add('has-child');
  }
});

然后使用CSS:

parent.has-child {
  /* 替代样式 */
}

使用Sass/Less预处理

// 预处理时生成可能的组合
parent {
  &.has-child {
    /* 样式 */
  }
}

高级用法

1. 组合多个条件

/* 选择包含标题和图片的文章 */
article:has(h2):has(img) {
  background: #f5f5f5;
}

/* 选择包含特定类或ID的元素 */
div:has(.special, #unique) {
  border: 2px dashed green;
}

2. 与其它伪类结合

/* 当悬停在子元素上时 */
section:has(a:hover) {
  background: #f0f0f0;
}

/* 当表单有必填字段时 */
form:has(input:required) {
  border-left: 3px solid orange;
}

3. 复杂选择器

/* 选择紧邻特定元素的父元素 */
div:has(+ .important) {
  margin-bottom: 20px;
}

/* 选择包含特定属性元素的父元素 */
ul:has(li[data-priority="high"]) {
  border-left: 3px solid red;
}

:has() 伪类极大地扩展了CSS的选择能力,使开发者能够基于内容或子元素状态更灵活地设计样式,减少了JavaScript处理样式的需求。

CSS ::selection 伪元素详解

::selection 是一个CSS伪元素,用于设置文档中被用户选中部分(高亮部分)的样式。这个选择器可以自定义文本选中时的外观,提升用户体验和视觉一致性。

基本语法

::selection {
  /* 可用的样式属性 */
  background-color: #ff0000;
  color: white;
  text-shadow: none;
}

可用属性

::selection 伪元素支持有限的CSS属性:

  • color (文字颜色)
  • background-color (背景色)
  • text-shadow (文字阴影)
  • text-decoration (文字装饰)
  • text-emphasis-color (强调标记颜色)
  • stroke-color (SVG描边颜色)
  • fill-color (SVG填充颜色)

使用示例

1. 基本文本选中样式

/* 全局选中样式 */
::selection {
  background-color: #3f51b5;
  color: white;
}

/* 特定元素的选中样式 */
p.highlight::selection {
  background-color: #ff9800;
  color: #000;
}

2. 移除文本选中阴影

::selection {
  text-shadow: none; /* 移除选中时的文字阴影 */
}

3. 特定元素的选中样式

/* 代码块选中样式 */
pre::selection {
  background-color: #333;
  color: #4CAF50;
}

/* 链接选中样式 */
a::selection {
  background-color: #2196F3;
  color: white;
  text-decoration: underline;
}

浏览器兼容性

::selection 在现代浏览器中有良好支持:

  • Chrome 1+
  • Firefox 1+ (使用 ::-moz-selection)
  • Safari 1.3+
  • Edge 12+
  • Opera 9.5+

注意事项

  1. 前缀需求:Firefox需要使用 ::-moz-selection 前缀
  2. 属性限制:只能应用有限的CSS属性
  3. 特异性::selection 伪元素不能组合其他选择器提高特异性
  4. 继承::selection 样式不会继承自父元素

最佳实践

1. 跨浏览器解决方案

/* 适用于所有浏览器 */
::-moz-selection { /* Firefox */
  background: #ff0000;
  color: white;
}

::selection {
  background: #ff0000;
  color: white;
}

2. 提高可读性

::selection {
  background-color: rgba(63, 81, 181, 0.8); /* 使用半透明色 */
  color: #fff;
  text-shadow: none; /* 移除可能干扰阅读的阴影 */
}

3. 品牌一致性

/* 使用品牌主色调 */
::selection {
  background-color: var(--brand-primary);
  color: var(--text-on-primary);
}

高级用法

1. 结合CSS变量

:root {
  --selection-bg: #3f51b5;
  --selection-color: white;
}

::selection {
  background-color: var(--selection-bg);
  color: var(--selection-color);
}

2. 禁用选中样式

/* 禁用选中高亮 */
.disable-selection::selection {
  background-color: transparent;
  color: inherit;
}

3. 打印样式

@media print {
  ::selection {
    background-color: #000;
    color: #fff;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
}

实际应用场景

  1. 品牌一致性:使选中状态与网站品牌色一致
  2. 可访问性:提高选中文本与背景的对比度
  3. 特殊内容:为代码块、引用等特殊内容设置不同的选中样式
  4. 交互反馈:增强用户选中操作的可视化反馈

限制与替代方案

由于 ::selection 的样式限制,如果需要更复杂的选择效果,可能需要使用JavaScript:

// 监听选中变化
document.addEventListener('selectionchange', function() {
  const selection = window.getSelection();
  if (selection.toString().length > 0) {
    // 对选中内容应用更复杂的样式
  }
});

::selection 伪元素为网页设计提供了一个简单而有效的方式来增强文本选中体验,使这一常见的用户交互行为更加美观和符合整体设计语言。


网站公告

今日签到

点亮在社区的每一天
去签到