[Day 23] 阿嬷都看得懂的进阶 CSS 选择器与伪类选择器

阿嬷都看得懂的进阶 CSS 选择器与伪类选择器

前天我们在写绿色贴纸的时候,各位阿嬷会不会觉得,我们也没遵守到 DRY 原则呢?明明绿色贴纸和粉红贴纸都是盖版横幅,只是颜色不同,我们却整个都要重写,也太麻烦了吧!

你可能会说:我没这麽笨,我让绿色贴纸沿用粉红贴纸的样式,然後用行内样式的方式,另外把绿色贴纸改成绿色就好啦!那如果绿色贴纸中的文字需要是粉红色,而粉红色贴纸中的文字需要是绿色呢?把 color 也在行内样式写一次?这太麻烦了!

等等,我们是否可能把颜色的类别抽取出来,并且和横幅盖版的类别分开写,然後让粉红贴纸和绿色贴纸都属於两个类呢?可以喔,我们只要把标签中的 class 的 2 个类用半行空白隔开就可以了。所以写起来会像这样:

.banner{
  height: 20vh;
  width: 100vw;
}
.pink{
	background-color: pink;
	color: green;
}
.green{
	background-color: pink;
	color: green;
}
<div class="banner pink"><div>
.
.
.
<div class="banner green"><div>

看起来是很理想,不过如果我有很多其他粉红和绿色的贴纸,也都共享 pink 和 green 这两个类别,但是我只希望盖版横幅中的文字才是这样的颜色配置,其他贴纸维持黑色,那我们又应该怎麽办呢?有没有可能我不要选择所有 pink 类别中的标签,而只选择同时属於 pink 和 banner 这 2 个类的标签,才改变字体颜色呢?可以喔!我们需要的是更多种选择器。

当我们想选择那些同时具备某些类别的标签时,我们必须在 .css 中,将这些类别全都写在一起。注意,这些同时都需要具备的类别中间,不能有空格喔!也就是说,我们应该这样写:

.banner.pink{
	background-color: pink;
	color: green;
}
.banner.green{
	background-color: pink;
	color: green;
}

注意,.banner.pink 中间是没有空格的!

另外,也要注意,这种组合几个类别而做出选择的进阶选择器,通常都需要放在原本类别的下方,因为 .css 档案中,较下方出才写的样式,通常都会覆盖掉较上方写过的样式。

那如果我们希望只有盖版横幅中的文字段落才置中放大,其它维持原样,又应该怎麽写呢?换句话说,我们只想选择到那些属於 .banner 类别的标签中包含的文字段落。这时候,我们会在类别间放入空格,表示类别的从属关系。举例会比较好懂:

<div class="banner">
	<p>粉红贴纸</p>
</div>
.banner p{
	text-align: center;
	line-height: 20vh;
	font-size: 5vmin;
	margin: 0;
}

这样就可以将只有在属於 .banner 类别的标签中的 p 标签加上这些样式。(那个 margin 是为了清掉 p 标签在某些浏览器预设的 1em 外距。) 在空格分隔类别的选择器中,无论後面的类别在第几层,都会被选择到。换句话说,就算我的 HTML 标签是

<div class="banner">
	<div>
	.
	.
	.
		<p>粉红贴纸</p>
	.
	.
	.
	</div>
</div>

这个 p 标签还是会被加上样式。

由於在类别间加上空格以後,类别间会变成从属关系,而非并列关系,所以是否加上空格就变得非常关键!这是新学习 CSS 选择器的夥伴很容易混淆的地方,要仔细注意喔!

你可能会问,那如果我只想选择 .banner 底下那层的 p 标签,但不想选择再更底层的 p 标签,该怎麽办呢?我们可以使用半形右角号 ">" 来表示这个关系。换句话说,如果上面的样式改成这样写:

.banner>p{
	text-align: center;
	line-height: 20vh;
	font-size: 5vmin;
	margin: 0;
}

那麽

<div class="banner">
	<p>我会吃到样式。</p>
	<div>
	.
	.
	.
		<p>我不会吃到样式</p>
	.
	.
	.
	</div>
</div>

其中只有第一个 p 会吃到样式喔!

但是,你会说,这样我还是只能选择到同层的所有同样元素,没办法再选择得更精确些吗?例如,我就只想选择那 8 张黄色贴纸中的第一张,该怎麽办呢?我们总不会有个类,可以选择出所有第一个元素吧!? 毕竟,「第一个元素」这种选择法,是要看我们把哪些元素放在一起。

呃嗯,是也不是。我们确实有方法可以选到第一个元素,但也确实如同上述讨论,我们必须先选择出某群元素,才能选择到这群元素中的第一个元素。这样的选择法,并不完全从类别出发,而是选择到类别底下的,某个好像是类别的一堆(!?)元素。也因此,我们把这种选择器,称为「伪类选择器」(psuedo-class selector)。换句话说,伪类选择器会先选出

  1. 某个类别;然後再从中选择出
  2. 某个子类。
    这个类别与子类中间,我们会用半形冒号 ":" 连接。例如,如果我们想选择出黄色贴纸中的第一张贴纸,并且让这个贴纸加上阴影 (box-shadow),我们就会这样写:
.yellow:first-child{
	box-shadow: 5px 5px 2px 1px gray;
}

其中 box-shadow 这个属性的值分别是水平右移的长度、垂直下移的长度、阴影模糊的长度、阴影扩散的长度、以及阴影颜色。

那麽,我们可以选泽出所有编号为奇数的贴纸,并且加上蓝色边框吗?没问题。我们有第 n 个子元素 :nth-child() 这个伪类选择器。这个选择器的圆括弧里可以填上某个数字,也可以填某个公式,就可以选择到某个或某些子元素了。例如,:nth-child(1) 其实就是 :first-child;而我们想选泽出所有编号为奇数的贴纸,圆括弧中就可以填 2n+1:

.yellow:nth-child(2n+1){
	border: 1px solid blue;
}

当我们的元素个数不定,我们又想选择最後一个子元素时, :last-child 这个伪类选择器就派上用场了。让我们把最後一张贴纸加上大圆角吧!

.yellow:last-child{
	border-radius: 5vmin;
}

今天介绍了许多进阶的 CSS 选择器,各位阿嬷可以自己 fork 底下这个 CodePen 回家练习喔!
https://codepen.io/LogosChen/pen/jOwzgpz


<<:  Backtrader - 自订 datafeeds

>>:  Day24:今天我们来聊一下SQL Injection

用visual studio写动物图监网页

先下载visual studio打开之後建档 接着写第一页进入页面 home是指我们的主页面 下面的...

Day24 CSS Animation 动画

昨天介绍完了transition动画,今天要介绍Animation动画,两者有甚麽区别呢? Anim...

Recursion

接下来我们要来学习很重要的递回,接下来让我们了解吧 函式呼叫自己 使用到Stack Fibonacc...

[鼠年全马] W38 - 使用Vuex管理资料状态(上)

这周要来介绍一个很好用的套件 - Vuex 看到名称应该马上可以理解他就是Vue专案在使用的套件吧...

[第23天]理财达人Mx. Ada-KDJ指标

前言 本文说明KDJ技术指标。 KDJ指标 KDJ指标运用一段期间内的收盘价、最高价和最低价三个元素...