关于伪元素选择器

253 阅读4分钟

这是我参与更文挑战的第7天,活动详情查看: 更文挑战

关于伪元素选择器的一些小发现

主要参考文章:www.zhangxinxu.com/wordpress/2…

什么是伪元素选择器

简单来讲就是用css定义了一个不存在的元素。

image-20210627185329041.png

如图,html代码里只有p元素,但是当用css定义了一个伪元素::first-line,就只会对p元素中的第一行起样式作用。

当前存在的伪元素选择器主要有以下几种:

  1. ::after:在元素之前创建伪元素
  2. ::before:在元素之后创建伪元素
  3. ::first-letter:选择元素的首字母
  4. ::first-line: 选择元素的首行
  5. ::selection: 选择用户选择的元素部分

生效的前提

  1. 元素的display计算值必须是 block, inline-block, table-cell, list-item或者table-caption

    对span使用伪元素选择器是不生效的。

    猜想:是不是因为伪元素其实就是生成了一个inline元素?

  2. 一些特殊字符被认为是辅助字符,如下:

    image-20210627191222571.png

    空格也会被认为是辅助字符,他们的表现如下:当设置::first-letter为红色时

    辅助字符:

    image-20210627191318028.png

    非辅助字符:

    image-20210627191336265.png

    也就是说,辅助字符会和第一个字一起变为红色。

  3. 作用的字符不能display:inline-系列的属性,如inline-block,inline-flex,inline-table,inline-grid。

    image-20210627193210623.png

    如果作用的字符属性是display:flex、grid、none。和float等属性,不会直接放弃,会为下一个符合规定的元素应用字符。

    image-20210627193142818.png

  4. 只对某些css属性生效

    1. 所有字体相关属性:font, font-style, font-variant, font-weight, font-size, line-height以及font-family.
    2. 所有背景相关属性:background-color, background-image, background-position, background-repeat, background-size, 以及background-attachment.
    3. 所有margin相关属性:margin, margin-top, margin-right, margin-bottom, margin-left.
    4. 所有padding相关属性:padding, padding-top, padding-right, padding-bottom, padding-left.
    5. 所有border相关属性:缩写的border, border-style, border-color, border-width及普通书写的属性。
    6. color属性。
    7. text-decoration, text-transform, letter-spacing, word-spacing(合适情境下), line-height, float, vertical-align(只有当floatnone的时候)这些CSS属性们.

优先级问题

前面的那些东西其实也不会刻意去记哈哈哈,写在那里只是方便要用的时候来看看。下面才是我想说的,我想说如果用了first-letter或first-line而且样式生效的情况下,几乎没有什么能够覆盖它的样式。

如下:

我们给p设置important:

<head>
    <style>
        /*伪元素*/
        p::first-letter {
            color: pink;
        }
        p{
            color: #abcdef !important; 
        }
    </style>
</head>
<body>
    <p>一行代码</p>
</body>

最后生成的样式是:一行代码

可以看到p上设置的important没生效,是不是不太符合逻辑?按照css2规范,伪元素选择器应该和标签选择器一样优先级属于1,而import是最高优先级。

为啥会这样呢,我们打开控制台,发现伪元素其实是被分离出来的:

image-20210627195757546.png

所以我们暂时推测:伪元素其实是一个不存在于dom中的元素,是选择器作用的元素的子元素。

子元素是吧,好,我再弄个子元素。我们给p>span元素的color设置important:

<head>
    <style>
        /*伪元素*/
        p::first-letter {
            color: pink;
        }
    
        p>span{
            color: #abcdef !important; 
        }
    </style>
</head>
<body>
    <p><span></span>行代码</p>
</body>

最后生成的样式是:一为粉红色,其余字体不变色

既然伪元素是p的子元素,span也是p的子元素,那么为什么不会被span的样式覆盖呢

如果在span上设置其他样式,效果会怎么样?

span{
    font-weight: bolder;
    color: #abcdef !important; 
}

效果如下:

image-20210627200305112.png

我们看到字体确实被加粗了(好像不太显眼但是确实起作用了~~),所以伪元素其实继承了span的font属性。可以推测,伪元素其实是作为span的子元素存在的

再继续嵌套子元素其实也是一样的,他永远都是作为最底层的那个子元素存在,继承所有可继承的属性,所以不管span里面怎么设置important,他都只是优先于在span上设置的属性,而span的子元素会继承span上的所有可继承属性,在此基础上再添加自己的样式。

结论:伪元素选择器之所以覆盖important,不是因为伪元素选择器优先级高,而是因为伪元素是最底层的子元素