理解CSS之选择器 | 青训营笔记

116 阅读12分钟

这是我参与「第四届青训营 」笔记创作活动的第1天

CSS 是什么?

CSS (Cascading Style Sheets) 又称层叠样式表,主要与HTML一同使用,被用来定义页面元素的样式,是用来控制网页外观的一门技术。它可以为HTML页面设置字体和颜色、添加位置和大小、添加动画效果等。

CSS 的工作流程

工作原理

CSS 的使用

在页面中使用css的方式有三种。

外链式

<link rel="stylesheet" href="./css/style.css>

嵌入式

<style>
   div{
     width:100px;
     height:100px;
     border:3px soild red;
   }
</style>

内联式

<div style="width:100px; height:100px; border:3px soild red;"></div>

选择器与属性

选择器 (Selector) 会找到并选择页面中的元素,以便给它们设置样式。

选择器可以使用多种方式选择元素:

  • 按照标签名、类名或id
  • 按照属性
  • 按照 DOM 树中的位置

选择器有多种类型:

通配选择器

在 CSS 中,一个星号 (*) 就是一个通配选择器。它可以匹配任意类型的 HTML 元素。在配合其他简单选择器的时候,省略掉通配选择器会有同样的效果。比如,*.warning 和.warning 的效果完全相同。

*.warning {color:red;}
*#maincontent {border: 1px solid blue;}

标签选择器

标签选择器主要针对的是页面中某个标签中的样式设置,它的作用范围是这个页面内所有写在该标签内的内容,标签选择器可以定义多个标签的样式

p {color: red;}

类选择器

类选择器在定义的时候需要 "." 来做前缀,类名是自定义的,然后在括号内定义属性和属性值。它不是直接作用在该页面中,而是需要使用class方法去自定义要作用的标签

.MyClass {
	color: red;
}

定义完类选择器的样式之后,使用class方法去设置要调用改样式的标签。使用class方法调用类选择器中的样式的时候,直接接类名即可,不需要输入"."。

<p class="MyClass">Hello</p>

类选择器可以在页面中的多个标签内重复使用,也可以中定义多个类选择器。

id选择器

ID选择器使用"#"作前缀,标识名照样是自定义的。然后括号内输入要修改样式的属性和属性值。

#MyId {
	color: blue;
}

内定义好ID选择器之后,在需要使用该样式的标签内使用ID方法即可。

<p id="MyId">Hello</p>

ID="标识名" 需要注意的是ID选择器可以创建多个,但一个id选择器中的样式只能在页面中的一个标签内使用一次。

属性选择器

类选择器 和 ID 选择器都属于 属性选择器。 应为本质上 类选择器 是 匹配 HTML 中 class 的属性值, ID 选择器 是 匹配 HTML 中的 Id 属性值

但此处说的属性选择器则是可以根据元素的属性及属性值来选择元素,与类选择器、ID选择器略有不同。

属性值 直接匹配 选择器包括下面4 种:

简单属性选择

如果希望选择有某个属性的元素,而不论属性值是什么,可以使用简单属性选择器。

/*把包含标题(title)的所有元素变为红色*/
*[title] {color:red;}

/*对有 href 属性的锚(a 元素)应用样式*/
a[href] {color:red;}

/*将同时有 href 和 title 属性的 HTML 超链接的文本设置为红色*/
a[href][title] {color:red;}

根据具体属性值选择

除了选择拥有某些属性的元素,还可以进一步缩小选择范围,只选择有特定属性值的元素。

/*将指向 Web 服务器上某个指定文档的超链接变成红色*/
a[href="http://www.juejin.cn/about.html"] {color: red;}

/*与简单属性选择器类似,可以把多个属性-值选择器链接在一起来选择一个文档*/
a[href="http://www.juejin.cn/"][title="juejin"] {color: red;}

请注意,这种格式要求必须与属性值完全匹配。

如果属性值包含用空格分隔的值列表,匹配就可能出问题。

<p class="important warning">This paragraph is a very important warning.</p>

<style>
	p[class="important warning"] {color: red;}
</style>

根据部分属性值选择

如果需要根据属性值中的词列表的某个词进行选择,则需要使用波浪号(~),它能用于任何属性。

/*选择 class 属性中包含 important 的元素*/
p[class~="important"] {color: red;}

/*这个规则会选择 title 文本包含 "Figure" 的所有图像。没有 title 属性或者 title 属性中不包含 "Figure" 的图像都不会匹配。*/
img[title~="Figure"] {border: 1px solid gray;}

如果忽略了波浪号,则说明需要完成完全值匹配。

特定属性选择类型

该类型需要使用竖杠(|)。

/*这个规则会选择 lang 属性等于 en 或以 en- 开头的所有元素*/
*[lang|="en"] {color: red;}

根据以上规则,以下示例标记中的前三个元素将被选中,而不会选择后两个元素:

/*会被选中*/
<p lang="en">Hello!</p>
<p lang="en-us">Greetings!</p>
<p lang="en-au">G'day!</p>

/*不会被选中*/
<p lang="fr">Bonjour!</p>
<p lang="cy-en">Jrooana!</p>

组合选择器

组合选择器可以让多个选择器公用同一个CSS样式代码。

后代组合 ( )

后代选择器用于选取某元素的后代元素,使用空格分隔。

/*选取所有<div>元素中的<p>元素应用样式*/
div p { background-color:red; }

亲子组合 (>)

子元素选择器只能选择作为某元素直接或一级子元素的元素,使用(>)连接。

/*选择<div>元素中所有直接子元素<p>*/
div>p { background-color:red; }

兄弟选择器 (~)

找到指定的元素后面的所有满足条件的兄弟元素,使用(~)连接。

/*选择<p>元素后的所有<h3>元素*/
p ~ h3 { color:red; }

相邻选择器 (+)

该选择器使用(+)连接,选择紧接在另一个元素后的元素,而且二者有相同的父元素,兄弟只会影响下面的兄弟的样式,不影响上面兄弟的样式。

/*选择与<h1>元素相邻的<p>元素*/
h1 + p { margin-top:50px; color:red; }

分组选择器 (,)

分组选择器使用逗号把同组内不同对象分隔,其本质上不是一种选择器类型,而是一种选择器使用方法。当多个对象定义了相同的样式时,就可以把它们分成一组,这样能够简化代码。

/*定义所有级别的标题和段落行高为22px*/
h1,h2,h3,h4,h5,h6,p{
    line-height:22px;
}

伪类选择器

伪类通常用于标记一些特殊的样,用于控制一个元素在不同动作下有不同的样式。

伪类主要有两方面的用处,一方面是标记一些特殊的状态,另外还有一类伪类是有筛选的功能。

以下仅记录一些常用的伪类。

状态伪类

/*选取未访问过的超链接元素。如果我们注意过搜索引擎的结果的话,它里面的链接只要点过的就会变色,从而标记哪个链接是访问过的*/
:link{}

/*选取访问过的超链接元素。和第一条相反,:visited 是用来标记哪个链接是已经访问过的,防止重复点击*/
:visited{}

/*选取鼠标悬停的元素,当鼠标放在一个元素上时显示的样式*/
:hover{}

/*选取点中的元素。这个伪类的作用在刚才提到过了,当我们希望按钮有操作反馈的时候,可以用它来标记操作反馈的样式。当然这个伪类也是可以通用的,并不是只能用在按钮上*/
:active{}

/*选取获得焦点的元素。这个伪类用来标识获得焦点的元素,比如搜索框在聚焦的时候有个比较明显的边框,方便用户知道当前在可输入的状态*/
:focus{}

筛选伪类

/*选取没有子元素的元素。比如选择空的 span,就可以用 span:empty 选择器来选择。这里要注意元素内有空格的话也不能算空,不会被这个伪类选中*/
:empty{}

/*选取勾选状态的 input 元素, 只对 radio 和 checkbox 生效*/
:checked{}

/*选取禁用的表单元素*/
:disabled{}

/*选取当前选择器下第一个元素*/
:first-child{}

/*和 first-child 相反,选取当前选择器下最后一个元素*/
:last-child{}

/*选取指定位置的元素。这个伪类是有参数的,参数可以支持 an+b 的形式,这里 a 和 b 都是可变的,n 从0起。使用这个伪类可以做到选择第几个,或者选择序号符合 an+b 的所有元素。比如使用 li:nth-child(2n+1),就可以选中 li 元素中序号是2的整数倍加1的所有元素,也就是第1、3、5、7、9、2n+1个 li 元素*/
:nth-child(an+b){}

/*这个伪类和 nth-child 相似,只不过在计数的时候,这个伪类是从后往前计数*/
:nth-last-child(an+b){}

/*选取唯一子元素。如果一个元素的父元素只有它一个子元素,这个伪类就会生效。如果一个元素还有兄弟元素,这个伪类就不会对它生效*/
:only-child{}

/*选取唯一的某个类型的元素。如果一个元素的父元素里只有它一个当前类型的元素,这个伪类就会生效。这个伪类允许父元素里有其他元素,只要不和自己一样就可以*/
:only-of-type{}

伪元素选择器

伪元素选择器是用于向某些元素设置特殊效果。伪元素选择器选中的并不是真实的 DOM 元素,所以叫伪元素选择器。常用的伪元素选择器有5个。

/*为某个元素的第一行文字使用样式*/
::first-line{}

/*为某个元素中的文字的首字母或第一个字使用样式*/
::first-letter{}

/*在某个元素之前插入一些内容*/
::before{}

/*在某个元素之后插入一些内容*/
::after{}

/*对光标选中的元素添加样式*/
::selection{}
  1. 伪元素选择器构造的元素是虚拟的,所以不能用 JS 去操作它。
  2. 如果同时使用了 before 和 first-letter 两个伪类,第一个字是要从 before 里的内容开始算起的,如果 before里面的内容是一个非文本元素,那 first-letter 也会作用在这个非文本元素上,但是不一定能生效。
  3. first-line 和 first-letter 不适用于内联元素,在内联元素中这两个选择器都会失效。
  4. 在 CSS3 中,规定了伪类用一个冒号(:)表示,伪元素用两个冒号表示(::)。但除了 selection,其余四个伪元素选择器已经在 CSS2 中存在且和伪类用的是一样的单冒号表示的。为了向下兼容,现在的浏览器中伪元素选择器用单冒号和双冒号都可以。在没有兼容问题的情况下,还是建议大家按着新的 CSS3 标准来开发。

选择器的特异度

选择器的特异度由选择器本身的组件确定。

如果一个元素有两个或多个冲突的属性声明,那么有最特异度高的声明就会胜出。

特异度表述为4个部分,如:(0, 0, 0, 0),从左到右的权重由高到低。

权重排行(高到低):

  1. 行内样式
    (!important)
    
  2. ID选择器
    #id
    
  3. class、属性、伪类选择器
    .title
    input[type="text"]
    :hover
    
  4. 类型和伪元素选择器
    div
    ::before
    

权重向量

(0, 0, 0, 0) (行内样式,ID选择器,class/属性/伪类选择器/,类型/伪元素)

若权重相同,则定义靠后优先。

实例

<div id="container">
    <ul class="menu">
        <li id="item1" class="item1">item1</li>
        <li class="item2">item2</li>
        <li class="item3">item3</li>
    </ul>
</div>

<style>
    /* (0, 1, 3, 1) */
    #container .menu li.item2 {
        color: #ff4757;
    }

    /* (0, 1, 2, 1) */
    #container li:nth-child(2).item2 {
        color: #7bed9f;
    }
    
	/* (0, 1, 1, 1) */
    #container li.item2 {
        color: #ffa502;
    }


    /* (0, 0, 1, 1) */
    li.item2 {
        color: #5352ed;
    }

    /* (0, 0, 1, 0) */
    .item2 {
        color: #ff6b81
    }
</style>

继承

继承是css中最重要的概念之一,也是大多数人在学习css、调试css的过程中最容易感到迷惑的部分。比如我就经常迷惑为什么这些这些样式总是不能按照我的意愿来展现...

但继承存在的意义并不是为了迷惑我们,而是为了方便我们,换个方向想,如果我们要为每个元素再写一遍样式,太过于麻烦了吧!所以有些属性我们总是希望会被继承下去,不用重复的写。

但现实操作中,我们所面对的开发要求并非教科书的那么简单,为了更加实现多样化的场景,前者的样式不一定适用与后者。有些属性就是这么任性,它不会被继承,不仅仅是因为它不原意,更是因为它不适合被继承。

无继承性的属性

  1. display:元素布局类型
  2. 文本属性:
    • vertical-align:垂直文本对齐
    • text-decration:规定添加到文本的装饰
    • text-shadow:文本阴影效果
    • white-space:空白符的处理
    • unicode-bidi:设置文本的方向
  3. 盒子模型的属性:
    • width
    • height
    • margin
    • border
    • padding
  4. 背景属性:
    • background
    • background-color
    • background-image
    • background-repeat
    • background-position
    • background-attachment
  5. 定位属性:
    • float
    • clear
    • position
    • top
    • right
    • bottom
    • left
    • min-width
    • min-height
    • max-width
    • max-height
    • overflow
    • clip
    • z-index
  6. 生成内容属性:
    • content
    • counter-reset
    • counter-increment
  7. 轮廓样式属性:
    • outline-style
    • outline-width
    • outline-color
    • outline
  8. 页面样式属性:
    • size
    • page-break-before
    • page-break-after
  9. 声音样式属性:
    • pause-before
    • pause-after
    • pause
    • cue-before
    • cue-after
    • cue
    • play-during

有继承性的属性

  1. 字体系列属性:
    • font-family:字体系列
    • font-weight:字体的粗细
    • font-size:字体的大小
    • font-style:字体的风格
  2. 文本系列属性
    • text-indent:文本缩进
    • text-align:文本水平对齐
    • line-height:行高
    • word-spacing:单词之间的间距
    • letter-spacing:中文或者字母之间的间距
    • text-transform:控制文本大小写(就是uppercase、lowercase、capitalize这三个)
    • color:文本颜色
  3. 元素可见性:
    • visibility:控制元素显示隐藏
  4. 列表布局属性:
    • list-style:列表风格,包括list-style-type、list-style-image等
  5. 光标属性:
    • cursor:光标显示为何种形态

结尾

css的选择器类型繁多,应用场景多样且广泛,所以我认为很好的理解css的选择器能对之后深入学习css或在实际生产中提供很大的帮助。还有就是我初学MarkDown,用得还不是很好,而且平时也没有写笔记的习惯,这篇本就应该写好的笔记现在才完成,看来还是要多写笔记,提升自己。