CSS伪类介绍

CSS伪类详解
本文介绍了CSS伪类的各种状态,如link、visited、hover、active、autofill、checked等,以及它们在不同元素上的应用,如表单元素、链接、视频元素等。同时提到了LVHA顺序、全屏、焦点状态和画中画模式等概念。

CSS伪类

css伪类就是元素的一种特殊状态,下面的伪类是相关的,可以尝试其中的示例代码看看实际效果。

link, visited, hover, active, any-link, local-link

需要按照 LVHA 的顺序定义样式,否则 active 的样式可能会被覆盖。

link 是链接的初始状态,visited 是链接访问过(点击)之后的状态,hover 是鼠标悬停的状态,active 是激活状态(鼠标主键按下及松开之间的状态)。

any-link 就是 link 和 visited 状态的集合, local-link(实验性的)一般表示锚点链接,指向当前文档。

autofill

设置了 autocomplete 属性的表单元素会在获取焦点后有浏览器提示,当选中浏览器提示时触发 autofill 状态。

blank

这是实验性的,表示 input 或 textarea 元素非必填且为空的状态。

checked

表示 checkbox, radio, select 下的 option 选中时的状态。

current, past, future

这是实验性的,目前基本没用。在 video 元素内部使用 track 元素,该元素引入的文件就是 WEBVTT 字幕轨道。

default

表示设置了 checked 属性的 checkbox 和 radio 元素,设置了 selected 属性的 option 元素,表单的默认提交按钮(type=submit)。

defined

表示浏览器内置标准元素以及customElements.define()定义的自定义元素。

dir, lang()

dir 伪类会继承父级的文本方向,:dir(ltr | rtl)的选择器元素即使没有设置 dir 属性也会生效。

在元素设置lang="<language value>"属性后,可以使用:lang(<language value>)选中元素。

disabled, enabled

表单元素 input,select,textarea,button 可以设置 disabled 属性实现disabled状态。没有 disabled 属性或者 disabled=false 就是enabled状态。

empty

元素内部不存在元素节点和文本节点就认为是empty状态。注释节点不包括。

<style>
    div:empty {
        outline: 2px solid deeppink;
        height: 1em;
    }
</style>
<!-- empty -->
<p>Element with no content:</p>
<div></div>
<!-- empty -->
<p>Element with comment:</p>
<div><!-- Simple Comment --></div>

<p>Element with whitespace:</p>
<div>&nbsp;</div>

first, left, right

伪类的样式只会生效的属性有margin, padding, border, background

:first@page一起使用,选中被打印文档的第一页。:left:right@page一起使用,选中被打印文档的左手边页面或右手边页面。一般双面打印的正面是右手边页面,背面是左手边页面。

/* Selects the first page when printing */
@page :first {
    margin-left: 50%;
    margin-top: 50%;
}

first-child, first-of-type, last-child, last-of-type

first-childlast-child分别选中同级兄弟元素的第一个和最后一个元素,并且元素必须与选择器匹配。

<style>
    p:first-child {
        color: lime;
        background-color: black;
        padding: 5px;
    }
</style>
<div>
    <p>This text is selected!</p>
    <p>This text isn't selected.</p>
</div>

<div>
    <h2>This text isn't selected: it's not a `p`.</h2>
    <p>This text isn't selected.</p>
</div>

first-of-typelast-of-type选中同级兄弟元素的第一种类的元素,后一个从末尾倒数,如果选择器不存在则默认是通用选择器(*)。

<style>
    /* article下的所有同级兄弟元素的第一个被选中 */
    article :first-of-type {
        background-color: pink;
    }
</style>
<article>
    <div>This `div` is first!</div>
    <div>This <span>nested `span` is first</span>!</div>
    <div>This <em>nested `em` is first</em>, but this <em>nested `em` is last</em>!</div>
    <div>This <span>nested `span` gets styled</span>!</div>
    <p>This `p` qualifies!</p>
    <div>This is the final `div`.</div>
</article>

fullscreen

当浏览器开启全屏之后,document.fullscreenElement的值就是:fullscreen选中的元素。

focus, focus-visible, focus-within

表单元素以及其它可以通过 Tab 键选中的元素在用户点击时会进入 focus 状态。

focus-visible状态包含focus状态,只不过focus-visible状态存在由用户代理启发式设置的默认样式对焦环

/* user agent stylesheet */
:focus-visible {
    outline: -webkit-focus-ring-color auto 1px;
}

focus-within状态表示选择器自身符合focus状态或者选择器元素的后代元素符合focus状态。

<style>
    form {
        border: 1px solid;
        color: gray;
        padding: 4px;
    }
    form:focus-within {
        background: #ff8;
        color: black;
    }
</style>
<form>
    <label for="given_name">Given Name:</label>
    <input id="given_name" type="text" />
    <br />
    <label for="family_name">Family Name:</label>
    <input id="family_name" type="text" />
</form>

has()

这是实验性的,如果 has 之前的选择器和 has 参数传递的相对选择器至少匹配一个元素,则:has()选中该元素。

host, host(), host-context()

:host选中阴影 DOM 的宿主元素,不要在阴影 DOM 外使用。:host()选择器参数与阴影 DOM 宿主元素匹配则选中该阴影 DOM 的宿主元素。:host-context()选择器参数与阴影 DOM 宿主元素的祖先元素匹配则选中该阴影 DOM 的宿主元素。

const style = document.createElement("style");
const span = document.createElement("span");
span.textContent = this.textContent;

const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(style);
shadowRoot.appendChild(span);

style.textContent =
    "span:hover { text-decoration: underline; }" +
    // h1元素下的自定义元素
    ":host-context(h1) { font-style: italic; }" +
    ':host-context(h1):after { content: " - no links in headers!" }' +
    // 不生效,不要用逗号群组选择器
    ":host-context(article, aside) { color: gray; }" +
    // 宿主元素包含 .footer class生效
    ":host(.footer) { color : red; }" +
    // 所有宿主元素都生效
    ":host { background: rgba(0,0,0,0.1); padding: 2px 5px; }";

indeterminate

indeterminate状态包含以下情况:

  • checkbox 元素设置实例 indeterminate 属性(是 property 不是 attribute)为 true(需要通过 javascript 设置)
  • 相同 name 值的同组 radio,没有一个 radio 被选中
  • 没有 value 的 progress 元素

实际效果

<style>
    input:indeterminate + label {
        background: lime;
    }
</style>
<fieldset>
    <legend>Checkbox</legend>
    <div>
        <input type="checkbox" id="checkbox" />
        <label for="checkbox">This checkbox label starts out lime.</label>
    </div>
</fieldset>

<fieldset>
    <legend>Radio</legend>
    <div>
        <input type="radio" id="radio1" name="radioButton" />
        <label for="radio1">First radio label starts out lime.</label>
    </div>
    <div>
        <input type="radio" id="radio2" name="radioButton" />
        <label for="radio2">Second radio label also starts out lime.</label>
    </div>
</fieldset>
<script>
    const inputs = document.getElementsByTagName("input");

    for (let i = 0; i < inputs.length; i++) {
        inputs[i].indeterminate = true;
    }
</script>
<style>
    progress {
        margin: 4px;
    }

    progress:indeterminate {
        width: 80vw;
        height: 20px;
    }
</style>
<progress></progress>

in-range, out-of-range

适用于有范围限制的表单元素。值在范围区间内则是 in-range 状态,否则就是 out-of-range 状态。

<style>
    label {
        display: block;
        margin-top: 1em;
    }
    input:in-range {
        background-color: palegreen;
    }
    input:out-of-range {
        background-color: orangered;
    }
</style>
<form>
    <label for="amount">How many tickets? (You can buy 2-6 tickets)</label>
    <input name="amount" type="number" min="2" max="6" value="4" />

    <label for="dep">Departure Date: (Whole year 2022 is acceptable)</label>
    <input name="dep" type="date" min="2022-01-01" max="2022-12-31" value="2025-05-05" />

    <label for="ret">Return Date: (Whole year 2022 is acceptable)</label>
    <input name="ret" type="date" min="2022-01-01" max="2022-12-31" />
</form>

invalid, valid, optional, required

表示 form,fieldset,input 或其它表单元素校验结果状态,通过就是 valid,不通过就是 invalid。

<style>
    label {
        display: block;
        margin-top: 1em;
    }
    input:invalid {
        background-color: ivory;
        border: none;
        outline: 2px solid red;
        border-radius: 5px;
    }
    input:valid {
        background-color: ivory;
        border: none;
        outline: 2px solid deepskyblue;
        border-radius: 5px;
        accent-color: gold;
    }
</style>
<form>
    <label for="email">Email Address:</label>
    <input name="email" type="email" value="na@me@example.com" />
    <label for="secret">Secret Code: (lower case letters)</label>
    <input name="secret" type="text" value="test" pattern="[a-z]+" />
    <label for="age">Your age: (18+)</label>
    <input name="age" type="number" value="5" min="18" />
    <label><input name="tos" type="checkbox" required checked /> - Do you agree to ToS?</label>
</form>

required 或 optional 状态表示 input,select,textarea 等表单元素是否设置了 required 属性。

<style>
    label {
        display: block;
        margin-top: 1em;
    }

    .req {
        color: red;
    }

    *:required {
        background-color: gold;
    }

    *:optional {
        background-color: palegreen;
    }
</style>
<form>
    <label for="name">Name: <span class="req">*</span></label>
    <input name="name" type="text" required />

    <label for="birth">Date of Birth:</label>
    <input name="birth" type="date" />

    <label for="origin">How did you find out about us? <span class="req">*</span></label>
    <select name="origin" required>
        <option>Google</option>
        <option>Facebook</option>
        <option>Advertisement</option>
    </select>
    <p><span class="req">*</span> - Required field</p>
</form>

is(), where()

:match()被重命名为:is()is()接受选择器列表作为参数,并且选中选择器列表中任意一个匹配的元素。

选择器列表中不支持的参数会被忽略,而逗号群组选择器会导致整个被忽略。选择器列表中不要出现伪元素。

<style>
    ol {
        list-style-type: upper-alpha;
        color: darkblue;
    }

    :is(ol, ul, menu:unsupported) :is(ol, ul) {
        color: green;
    }

    :is(ol, ul) :is(ol, ul) ol {
        list-style-type: lower-greek;
        color: chocolate;
    }
</style>
<ol>
    <li>Saturn</li>
    <li>
        <ul>
            <li>Mimas</li>
            <li>Enceladus</li>
            <li>
                <ol>
                    <li>Voyager</li>
                    <li>Cassini</li>
                </ol>
            </li>
            <li>Tethys</li>
        </ul>
    </li>
    <li>Uranus</li>
    <li>
        <ol>
            <li>Titania</li>
            <li>Oberon</li>
        </ol>
    </li>
</ol>

where()is()功能一样,但是is()会计算所有参数选择器列表作为优先级,where()优先级是 0。:where(ol) :where(ol)优先级不如ol,所以ol的样式覆盖:where(ol, ul, menu:unsupported) :where(ol, ul)的样式。

<style>
    ol {
        list-style-type: upper-alpha;
        color: darkblue;
    }

    /* Not applied to ol, because of lower specificity */
    :where(ol, ul, menu:unsupported) :where(ol, ul) {
        color: green;
    }

    :where(ol, ul) :where(ol, ul) ol {
        list-style-type: lower-greek;
        color: chocolate;
    }
</style>
<ol>
    <li>Saturn</li>
    <li>
        <ul>
            <li>Mimas</li>
            <li>Enceladus</li>
            <li>
                <ol>
                    <li>Voyager</li>
                    <li>Cassini</li>
                </ol>
            </li>
            <li>Tethys</li>
        </ul>
    </li>
    <li>Uranus</li>
    <li>
        <ol>
            <li>Titania</li>
            <li>Oberon</li>
        </ol>
    </li>
</ol>

modal

modal 适用于与外部元素停止交互的元素:

  • 使用showModal()打开的<dialog>元素
  • 使用requestFullscreen()请求全屏的元素

not

表示不匹配选择器列表的元素,和is()是相反的,且not()的参数列表不能包含另一个否定选择器或者伪元素。

使用建议:

  • :not(*)匹配所有不是元素的元素,所以是无意义的。
  • not()会计算参数优先级,所以#foo:not(#bar)#foo多一个#bar的优先级
  • not()优先级会使用参数中最具体选择器的优先级
  • :not(.foo)会匹配所有类不是foo的元素,包括<html><body>
  • :not()与后代选择器联合使用可能不是你想要的效果,:not(table) a表示选择非 table 下的 a,但是 table 内的 tr,th,td,tbody,caption 都匹配:not(table)
  • :not(.foo, .bar)等于:not(.foo):not(.bar)
  • :not()参数如果有一个选择器不支持,则整体都不会生效。:not(.foo, :invalid-pseudo-class)无效,:is(:not(.foo), :not(:invalid-pseudo-class))会匹配非.foo的元素。

nth-child(), nth-last-child(), nth-of-type(), nth-last-of-type()

参数可以是关键字odd(2n+1), even(2n); 也可以是An+B的公式(取值 n >= 0, An + B > 0)。匹配索引从 1 开始。

因为索引是从 1 开始,所以同级兄弟元素的第一个元素就是奇数 1。同样由于索引是从 1 开始,所以An + B >= 1。例如li:nth-child(-n + 3)匹配第一到第三个 li(n = 0, 1, 2),
n >= 3时,-n + 3 <= 0所以不会匹配任何元素。

  • nth-child() - 从同级兄弟元素中根据公式An+B匹配元素,假如元素与伪类前面的选择器匹配则选中
  • nth-of-type()- 从同级兄弟元素中根据伪类前面的选择器匹配元素(如果没有选择器则计算所有特定类型的元素在同类型兄弟元素中的次序),然后根据公式An+B匹配特定类型的元素
  • nth-last-child() - 等同于nth-child(),从后往前匹配
  • nth-last-of-type() - 等同于nth-of-type(),从后往前匹配
<style>
    dl :nth-child(-2n + 4) {
        color: red;
    }
    dl :nth-of-type(2) {
        color: green;
    }
    dd:nth-of-type(n + 4):nth-of-type(-n + 6) {
        color: blue;
    }
    dd.fancy:nth-of-type(2n) {
        font-weight: bold;
    }
</style>
<dl>
    <dt>列表1</dt>
    <dd class="fancy">Item 1</dd>
    <dd>Item 2</dd>
    <dd>Item 3</dd>
    <dt>列表2</dt>
    <dd class="fancy">Item 4</dd>
    <dd>Item 5</dd>
    <dd>Item 6</dd>
</dl>

only-child, only-of-type

  • :only-child - 先保证该元素是父级元素的唯一元素,然后匹配伪类前面选择器的元素
  • :only-of-type - 先保证该类型元素在同级的兄弟元素中唯一,然后匹配伪类前面选择器的元素
<style>
    li:only-child {
        color: pink;
    }
    span:only-of-type {
        color: chocolate;
    }
</style>
<div>
    <div>
        <span>This is only child</span>
        <ul>
            <li>only child</li>
        </ul>
    </div>
    <div>
        <span>This has two child</span>
        <ul>
            <li>one child</li>
            <li>two child</li>
        </ul>
    </div>
</div>

picture-in-picture

匹配当前处于画中画模式的元素(通常是 video 元素)

placeholder-shown

匹配<input>, <textarea>元素当前正在显示 placeholder 文本的元素

paused, playing

匹配video, audio处于播放或暂停状态的元素(兼容性不太好)。

read-only, read-write

匹配可以编辑或只读的元素。<input>, <textarea>元素通过read-only属性不允许更改输入。其它不可编辑的元素可以通过contenteditable属性控制是否可编辑。

root

在 HTML 中:root就是选择器html

scope

在样式表中,:scope等于:root,在一些 DOM API 中,比如querySelector(), querySelectorAll(), matches()等方法中,:scope等于调用这些方法的元素。

target, target-within!

:target表示 URL 中的锚点指向的特定 ID 的元素。:target-within是一个实验性功能,表示当前元素是:target或者后代元素是:target的元素,不建议使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值