属性选择器
概述
属性选择器(Attribute Selectors)用于选择具有特定属性的元素,或者属性值满足特定条件的元素。
语法
[属性名] {
/* 选择具有该属性的元素 */
}
[属性名="值"] {
/* 选择属性值完全匹配的元素 */
}
[属性名~="值"] {
/* 选择属性值包含该词的元素(词列表) */
}
[属性名|="值"] {
/* 选择属性值以该值开头的元素(或该值后连字符) */
}
[属性名^="值"] {
/* 选择属性值以该字符串开头的元素 */
}
[属性名$="值"] {
/* 选择属性值以该字符串结尾的元素 */
}
[属性名*="值"] {
/* 选择属性值包含该字符串的元素 */
}基本用法
1. 存在属性选择器
选择具有指定属性的元素,不考虑属性值。
/* 选择具有 title 属性的元素 */
[title] {
border: 1px solid red;
}
/* 选择具有 disabled 属性的输入框 */
input[disabled] {
background-color: #f5f5f5;
cursor: not-allowed;
}
/* 选择具有 required 属性的表单元素 */
input[required] {
border-color: #e74c3c;
}<div title="提示信息">有 title</div>
<div>无 title</div>
<input type="text" disabled>
<input type="text" required>2. 精确匹配
选择属性值完全等于指定值的元素。
/* 选择 type 为 text 的输入框 */
input[type="text"] {
width: 100%;
padding: 10px;
}
/* 选择 href 精确匹配的链接 */
a[href="https://example.com"] {
color: red;
}
/* 选择 target 为 _blank 的链接 */
a[target="_blank"]::after {
content: " ↗";
}3. 部分匹配
[属性名~="值"] - 词列表匹配
选择属性值包含指定词的元素(词之间用空格分隔)。
/* 选择 class 包含 "box" 的元素 */
[class~="box"] {
border: 1px solid #3498db;
}<div class="box">匹配</div>
<div class="box active">匹配</div>
<div class="box-red">不匹配</div>
<div class="box2">不匹配</div>[属性名|="值"] - 连字符分隔的前缀匹配
选择属性值以指定值开头,或以该值加连字符开头的元素。
/* 选择 lang 以 "en" 开头的元素 */
[lang|="en"] {
font-family: Arial, sans-serif;
}<p lang="en">匹配</p>
<p lang="en-US">匹配</p>
<p lang="en-GB">匹配</p>
<p lang="zh">不匹配</p>[属性名^="值"] - 开头匹配
选择属性值以指定字符串开头的元素。
/* 选择 class 以 "icon-" 开头的元素 */
[class^="icon-"] {
display: inline-block;
width: 20px;
height: 20px;
background-repeat: no-repeat;
}
/* 选择 href 以 "https://" 开头的链接 */
a[href^="https://"] {
color: #27ae60;
}
/* 选择 src 以 "http://" 开头的图片 */
img[src^="http://"] {
display: none; /* 不显示非 HTTPS 图片 */
}<i class="icon-user"></i>
<i class="icon-home"></i>
<i class="icon-home-active"></i>
<i class="my-icon"></i> <!-- 不匹配 -->[属性名$="值"] - 结尾匹配
选择属性值以指定字符串结尾的元素。
/* 选择 href 以 ".pdf" 结尾的链接 */
a[href$=".pdf"]::after {
content: " (PDF)";
color: #e74c3c;
}
/* 选择 src 以 ".jpg" 结尾的图片 */
img[src$=".jpg"] {
border: 2px solid #3498db;
}
/* 选择 class 以 "-active" 结尾的元素 */
[class$="-active"] {
color: #3498db;
font-weight: bold;
}<a href="document.pdf">下载文档</a>
<a href="page.html">普通链接</a>
<div class="box-active">激活状态</div>
<div class="active-box">不匹配</div>[属性名*="值"] - 包含匹配
选择属性值包含指定字符串的元素。
/* 选择 href 包含 "example" 的链接 */
a[href*="example"] {
color: #3498db;
}
/* 选择 src 包含 "logo" 的图片 */
img[src*="logo"] {
border: 2px solid gold;
}
/* 选择 class 包含 "box" 的元素 */
[class*="box"] {
padding: 10px;
}<a href="https://example.com">匹配</a>
<a href="https://test.com">不匹配</a>
<img src="logo.png">
<img src="header.png">权重计算
属性选择器的权重为 10:
[type="text"] {
/* 权重 = 10 */
}
input[type="text"] {
/* 权重 = 1 + 10 = 11 */
}
.box[class~="active"] {
/* 权重 = 10 + 10 = 20 */
}常见应用场景
1. 表单样式
/* 文本输入框 */
input[type="text"],
input[type="email"],
input[type="password"],
textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
/* 单选框和复选框 */
input[type="radio"],
input[type="checkbox"] {
width: 16px;
height: 16px;
cursor: pointer;
}
/* 按钮 */
input[type="submit"],
input[type="button"],
button {
padding: 10px 20px;
background: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}2. 链接样式
/* 外部链接 */
a[href^="http"]::after {
content: " ↗";
font-size: 0.8em;
}
/* 邮箱链接 */
a[href^="mailto:"]::before {
content: "✉ ";
}
/* 电话链接 */
a[href^="tel:"]::before {
content: "📞 ";
}
/* PDF 链接 */
a[href$=".pdf"]::after {
content: " (PDF)";
color: #e74c3c;
font-size: 0.8em;
}
/* 压缩文件链接 */
a[href$=".zip"],
a[href$=".rar"]::after {
content: " (下载)";
color: #f39c12;
font-size: 0.8em;
}3. 图标样式
/* 所有图标 */
[class^="icon-"],
[class*=" icon-"] {
display: inline-block;
width: 16px;
height: 16px;
background-image: url(icons.png);
background-repeat: no-repeat;
}
/* 特定图标 */
.icon-home {
background-position: 0 0;
}
.icon-user {
background-position: -16px 0;
}
.icon-settings {
background-position: -32px 0;
}4. 社交媒体链接
/* Twitter 链接 */
a[href*="twitter.com"] {
color: #1da1f2;
}
/* Facebook 链接 */
a[href*="facebook.com"] {
color: #1877f2;
}
/* LinkedIn 链接 */
a[href*="linkedin.com"] {
color: #0077b5;
}
/* GitHub 链接 */
a[href*="github.com"] {
color: #333;
}5. 图片样式
/* SVG 图片 */
img[src$=".svg"] {
width: 100%;
height: auto;
}
/* PNG 图片 */
img[src$=".png"] {
background: white;
padding: 10px;
}
/* JPG 图片 */
img[src$=".jpg"],
img[src$=".jpeg"] {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}6. 数据属性
/* 基于 data 属性的样式 */
[data-color="red"] {
background-color: #e74c3c;
color: white;
}
[data-color="blue"] {
background-color: #3498db;
color: white;
}
[data-color="green"] {
background-color: #27ae60;
color: white;
}
/* 悬停提示 */
[data-tooltip]:hover::after {
content: attr(data-tooltip);
position: absolute;
background: #333;
color: white;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
}<div data-color="red">红色背景</div>
<div data-color="blue">蓝色背景</div>
<span data-tooltip="这是提示信息">悬停查看</span>7. 必填和禁用状态
/* 必填字段 */
input[required],
textarea[required],
select[required] {
border-left: 3px solid #e74c3c;
}
input[required]::after,
textarea[required]::after {
content: " *";
color: #e74c3c;
}
/* 禁用字段 */
input[disabled],
textarea[disabled],
select[disabled] {
background-color: #f5f5f5;
color: #999;
cursor: not-allowed;
opacity: 0.7;
}8. 自定义属性
/* 基于 data 属性的组件样式 */
.card[data-size="small"] {
padding: 10px;
font-size: 14px;
}
.card[data-size="medium"] {
padding: 15px;
font-size: 16px;
}
.card[data-size="large"] {
padding: 20px;
font-size: 18px;
}
/* 主题颜色 */
.button[data-theme="primary"] {
background: #3498db;
}
.button[data-theme="success"] {
background: #27ae60;
}
.button[data-theme="danger"] {
background: #e74c3c;
}
.button[data-theme="warning"] {
background: #f39c12;
}<div class="card" data-size="small">小卡片</div>
<div class="card" data-size="medium">中卡片</div>
<div class="card" data-size="large">大卡片</div>
<button class="button" data-theme="primary">主要按钮</button>
<button class="button" data-theme="success">成功按钮</button>9. 多条件组合
/* 同时满足多个条件 */
input[type="text"][placeholder*="用户"] {
background-color: #f0f8ff;
}
a[href^="http"][href*="example"] {
color: #e74c3c;
font-weight: bold;
}
/* 组合选择器 */
.box[data-size="large"].active {
transform: scale(1.1);
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}10. 图片优化
/* 懒加载图片 */
img[loading="lazy"] {
opacity: 0;
transition: opacity 0.3s ease;
}
img[loading="lazy"].loaded {
opacity: 1;
}
/* 响应式图片 */
img[srcset] {
width: 100%;
height: auto;
}
/* 视频封面 */
video[poster] {
width: 100%;
height: auto;
}实战案例
案例1: 文件下载列表
.download-list a {
display: block;
padding: 10px 15px;
background: #f9f9f9;
border-radius: 4px;
margin-bottom: 5px;
}
.download-list a[href$=".pdf"] {
border-left: 4px solid #e74c3c;
}
.download-list a[href$=".pdf"]::before {
content: "📄";
margin-right: 10px;
}
.download-list a[href$=".zip"],
.download-list a[href$=".rar"] {
border-left: 4px solid #f39c12;
}
.download-list a[href$=".zip"]::before,
.download-list a[href$=".rar"]::before {
content: "📦";
margin-right: 10px;
}<div class="download-list">
<a href="document.pdf">产品手册</a>
<a href="files.zip">资源包</a>
<a href="data.rar">数据文件</a>
</div>案例2: 表单验证样式
.form-group {
margin-bottom: 20px;
}
/* 必填字段 */
.form-group input:required,
.form-group textarea:required {
border-left: 3px solid #e74c3c;
}
.form-group input:required::placeholder,
.form-group textarea:required::placeholder {
color: #e74c3c;
}
/* 验证通过 */
.form-group input:valid,
.form-group textarea:valid {
border-color: #27ae60;
}
/* 验证失败 */
.form-group input:invalid:not(:placeholder-shown),
.form-group textarea:invalid:not(:placeholder-shown) {
border-color: #e74c3c;
}
.form-group input:invalid:not(:placeholder-shown) + .error-msg,
.form-group textarea:invalid:not(:placeholder-shown) + .error-msg {
display: block;
}
.error-msg {
display: none;
color: #e74c3c;
font-size: 12px;
margin-top: 5px;
}案例3: 社交媒体图标
.social-links a {
display: inline-flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 50%;
color: white;
text-decoration: none;
transition: transform 0.3s ease;
}
.social-links a[href*="twitter.com"] {
background: #1da1f2;
}
.social-links a[href*="facebook.com"] {
background: #1877f2;
}
.social-links a[href*="linkedin.com"] {
background: #0077b5;
}
.social-links a[href*="github.com"] {
background: #333;
}
.social-links a:hover {
transform: scale(1.1);
}<div class="social-links">
<a href="https://twitter.com" title="Twitter">T</a>
<a href="https://facebook.com" title="Facebook">F</a>
<a href="https://linkedin.com" title="LinkedIn">L</a>
<a href="https://github.com" title="GitHub">G</a>
</div>案例4: 响应式图片
/* 懒加载 */
img[loading="lazy"] {
opacity: 0;
transition: opacity 0.5s ease;
}
img[loading="lazy"].loaded {
opacity: 1;
}
/* 响应式图片 */
picture img {
width: 100%;
height: auto;
}
/* 不同格式支持 */
picture source[type="image/avif"] {
/* AVIF 格式 */
}
picture source[type="image/webp"] {
/* WebP 格式 */
}案例5: 主题切换
/* 主题容器 */
[data-theme="light"] {
--bg-color: #ffffff;
--text-color: #333333;
}
[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #ffffff;
}
/* 应用主题变量 */
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background-color 0.3s ease, color 0.3s ease;
}
/* 主题特定样式 */
[data-theme="light"] .card {
background: white;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
[data-theme="dark"] .card {
background: #2a2a2a;
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
}<div data-theme="light">
<div class="card">内容</div>
</div>
<div data-theme="dark">
<div class="card">内容</div>
</div>注意事项
- 属性区分大小写: HTML 属性名不区分大小写,但属性值可能区分
- 引号使用: 属性值可以用单引号、双引号或不加引号
- 性能考虑: 复杂的属性选择器可能影响性能
- 浏览器兼容: 大部分属性选择器在现代浏览器中都支持
- data 属性: 自定义 data 属性是很好的做法
最佳实践
- 语义化: 使用 data-* 属性传递语义信息
- 渐进增强: 为不支持的浏览器提供回退
- 性能优化: 避免过于复杂的属性选择器
- 代码可读: 添加注释说明复杂选择器
- 组合使用: 与其他选择器配合使用
- 规范命名: data-* 属性命名要规范
- 测试兼容: 测试浏览器兼容性
- 避免过度: 不要过度依赖属性选择器
总结
属性选择器是 CSS 中非常强大的选择器,能够基于元素的属性进行精确选择。掌握各种属性选择器的使用方法,可以帮助我们创建更灵活、更可维护的样式代码。在实际开发中,要合理使用属性选择器,确保代码的可读性和性能。