CSS基本功从头练之Selector

CSS基本功从头练之Selector


CSS一直是我的短板,从来没有系统学过,一直都是使用第三方的样式库,或者在网上找点资料copy。最近感觉应该系统的梳理一下,否则很多概念还是不太清晰。还是属于边学边写的资料,难免各种漏洞,希望大家多指正。

Selector(选择器)

为什么会有选择器这个概念?因为样式最终是要应用到HTML的元素上的,那么哪一类样式应该应用到什么元素这个问题就催生了选择器的诞生。总体来说,Selector分标签选择器、类选择器、ID选择器和属性选择器

标签选择器

顾名思义是以HTML标签作为筛选依据的,比如下面的代码中,我们的可见标签一共有:<html><body><div><label><input><output>

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div>
    <label for="weight">体重</label>
    <input id="weight" type="number">
  </div>
  <div>
    <label for="height">身高</label>
    <input id="height" type="number">
  </div>
  <div>
    <label for="bmi">BMI</label>
    <output id="bmi"></output>
  </div>
  
</body>
</html>

如果我们在css中有下面的定义,那么我们其实是对所有 <body> 标签(虽然事实上只有一个)应用样式背景色 #DCEDC8,而对所有 <input> 标签应用样式背景色 #8BC34A

body {
  background-color: #DCEDC8;
}

input {
  background-color: #8BC34A;
}
应用body和input标签样式的效果
应用body和input标签样式的效果

类选择器

类选择器的筛选标准是用类来确定的,就是在html标签中,我们一般可以用 class="blablabla" 来完成样式的类指定。现在我们改写HTML,把所有label指定一个 class="label"

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div>
    <label class="label" for="weight">体重</label>
    <input id="weight" type="number">
  </div>
  <div>
    <label class="label" for="height">身高</label>
    <input id="height" type="number">
  </div>
  <div>
    <label class="label" for="bmi">BMI</label>
    <output id="bmi"></output>
  </div>
  
</body>
</html>

然后在css中加上一个类样式定义,在css中我们在类名的前面加上一个 . 来表示这是个类样式定义。

.label {
  color: #fff;
}

使用label类样式定义后的效果
使用label类样式定义后的效果

ID选择器

我们看到上面的HTML代码中,有一些元素是有 id 这个属性的,那么这个选择器当然就是用来选择 id="blablabla" 的元素的。如果我们在css中给BMI结果加入一个ID选择器,放大结果的字体。

#bmi {
  font-size: xx-large;
}
应用了ID选择器的效果
应用了ID选择器的效果

属性选择器

属性选择器就是对HTML标签中含有的属性进行筛选,比如上例中我们如果想对标签中 for 属性、值为weight的进行特殊处理,那么我们可以看到下图的效果。

label[for="weight"] {
  color: #FF4081;
}
应用属性选择器的效果
应用属性选择器的效果

其实我感觉前面的ID选择器、类选择器甚至标签选择器都应该是属性选择器的一种特殊形式,比如我们其实把 #bmi 那段代码注释掉,换成属性选择器:选择 id="bmi" 的形式效果是一样的。

/* #bmi {
  font-size: xx-large;
} */

output[id="bmi"] {
  font-size: xx-large;
}

属性选择器的花样最多,下面我们来看看,如果不用 =,而使用 ~= 是什么效果。我们把bmi的label中的for改成 for="weight height"

  <div>
    <label class="label" for="weight height">BMI</label>
    <output id="bmi"></output>
  </div>

然后在css中用 ~= 替代 = 看看会发生什么?我们看到体重和BMI都应用了 #FF4081 这个颜色。也就说 ~= 表示选择所有含有等号后面的值的元素。

label[for~="weight"] {
  color: #FF4081;
}
使用 `~=` 代表选择含有该值的所有元素
使用 `~=` 代表选择含有该值的所有元素

但是注意一点,~= 后面的一定是一个完整的属性值,而不是含有这个字符串就行,比如上面HTML中如果我们写成 for="weight1 height" 那么这个选择器就无法生效了。

css1中还支持一种符号 |=,它会选择所有以等号后的值开头的元素,同样的,这里的开头指的是完整属性值而不是字符串意义上的开头。那么问题来了,有没有办法选择字符串呢?css3中增加了 ^=$=*= 这几个符号,是专门处理字符串这种需求的。题外话感觉这几个操作符很像正则表达式中的。

还是上面的例子,我们的html如下,注意bmi的label的for中是 weight1,而体重label的for中是 weight

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <script src="https://unpkg.com/@reactivex/rxjs@5.0.0-beta.7/dist/global/Rx.umd.js"></script>
  <title>JS Bin</title>
</head>
<body>
  <div>
    <label class="label" for="weight">体重</label>
    <input id="weight" type="number">
  </div>
  <div>
    <label class="label" for="height">身高</label>
    <input id="height" type="number">
  </div>
  <div>
    <label class="label" for="weight1 height">BMI</label>
    <output id="bmi"></output>
  </div>
  
</body>
</html>

css中我们使用 ^= 来试验一下,你会发现选择器又生效了。

label[for^="weight"] {
  color: #FF4081;
}

使用 `^=` 选择以字符串xxx开头的元素
使用 `^=` 选择以字符串xxx开头的元素

同样的如果我们换成下面的css,你会发现所有的label都变色了,因为都是 eight这个字符串结尾的

label[for$="eight"] {
  color: #FF4081;
}
 `$=`选择以字符串xxx结尾的所有元素
`$=`选择以字符串xxx结尾的所有元素

这时你会问,不对啊,bmi的label是 weight1 啊,但是请看仔细 for="weight1 height",这个字符串的最后是 height

*= 是选择字符串中包含某个值的元素,遇到它的话我比较好奇的是它能不能选择空格,因为 for="weight1 height"中含有一个空格。于是我做了个实验,用如下的css证明了是可以选择空格的。

label[for*=" "] {
  color: #FF4081;
}
 `*=`选择包含xxx字符串的元素
`*=`选择包含xxx字符串的元素

上下文选择器

如果仅有上面这些也还不错,css的强大或者说复杂在于还特么能组合。这个上下文选择器可以看作组合的一种,它利用多种符号连接标签选择器来实现根据上下文选择元素的目的。

还是用实例说话,首先最简单的组合符号 ,,为了看的更清楚一些,我们重新定义HTML:在最外面包了一层 div,并且给每一层 div 都指定了一个样式类。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <script src="https://unpkg.com/@reactivex/rxjs@5.0.0-beta.7/dist/global/Rx.umd.js"></script>
  <title>JS Bin</title>
</head>
<body>
  <div class="content">
    <div class="weight">
      <label class="label" for="weight">体重</label>
      <input id="weight" type="number">
    </div>
    <div class="height">
      <label class="label" for="height">身高</label>
      <input id="height" type="number">
    </div>
    <div class="bmi">
      <label class="label" for="weight1 height">BMI</label>
      <output id="bmi"></output>
    </div>
  </div>
</body>
</html>

css 中为几个 div 定义背景色,以便看的更清楚些。然后利用 , 定义了 div,label 的padding是 20px

...
.weight {
  background-color: gray;
}

.height {
  background-color: silver;
}

.bmi {
  background-color: darkgray;
}

.content{
  background-color: brown;
}

div,label {
  padding: 20px;
}

, 这种就比较简单,就是多个标签都使用这个样式,我们来看看效果:

采用了`,`表示“和”
采用了`,`表示“和”
只有div时的效果,仔细看会发现文字靠左边缘近了一些
只有div时的效果,仔细看会发现文字靠左边缘近了一些
只有label时的效果
只有label时的效果

这个操作符我认为只起到节省代码的作用;-)

后代选择器 (空格)

下面我们看看 (空格)这个操作符,还是为了更明显,我们在HTML中的最外层div之外加一行

<label for="something">我不在div中,所以没有变大</label>

我们在css中加上下面的定义,我们会看到,div内部的所有label的文字都变大了,但外部的没有。所以 x y表示选择在x元素内部的所有y

div label {
  font-size: x-large;
}

 ` `空格表示在div内部的所有label
` `空格表示在div内部的所有label

子选择器 >

那么下面我们看看 >,同样需要改造一下HTML,在 <div class="content"> 下加入下面的代码。

<p>
  <label for="something">我的父节点不是div,所以没有变大</label>
</p>

将css改成

div>label {
  font-size: x-large;
  padding:20px;
}

下面看看效果,刚刚加入的那个label文字没有变大的原因在于它的父节点是 <p>

`div>label` 符号筛选父节点为div的label元素
`div>label` 符号筛选父节点为div的label元素

“亲兄弟”选择器 +

接下来的这位就有意思了 +,你如果把 div+label 直接套用到上面的HTML中,会发现没什么作用,哪个字体也没变大。原因是这个符号是选择div 之后紧挨着 div的label元素。

那么我们的实验之前,请把下面的代码插入到最外层div之后

<label for="something">我不在div中但紧挨着div,所以变大了</label>
<label for="something">我虽然在div后但没有紧挨着div,所以没有变大了</label>
 `+` 指的是紧挨着前面的元素的所有元素
`+` 指的是紧挨着前面的元素的所有元素

"兄弟连"选择器 ~

有看后面的就有看前面的,接下来就是 ~ 闪亮登场了,div~label 是个什么效果捏? 事实证明 x~y 是用于选择前面有 x 的所有 y

div~label {
  font-size: x-large;
  padding:20px;
}
`div~label` 用于选择之前有div的所有label
`div~label` 用于选择之前有div的所有label

伪类

为什么叫这个名字?我也不知道,感觉有点怪,听说一个说法是它们很像类,但我真没看出哪儿像。伪类一般都是以 : 开头,也不光是伪类的,伪元素也是 : 开头。

链接伪类

首先看链接伪类,这个其实没什么好讲,就是因为链接有几个状态,普通的选择器无法筛选出来导致硬生生的造出来这几个东东。需要注意的是,这些货必须按着下面的顺序给出才可以生效。其实我实验了一下,link和visited调换位置没影响,其他按顺序是因为这几个状态有时有重叠,写错顺序会导致样式被覆盖。比如鼠标按下未抬起其实同时也满足hover的条件,如果我们把hover放在最后,active放在前面,那么这时就会以最后的样式(hover)覆盖前面的样式(active)

  • link: 没有访问过也没有鼠标悬停或点击的状态。
  • visited:用户点击过这个链接之后的状态。
  • hover:鼠标指针正悬停在连接上。
  • active:链接正在被点击(鼠标在元素上按下,还没有释放)。

“选中状态”伪类

再来看 :focus 伪类,这个也是由于输入框处于聚焦状态时无法通过其他选择器选取而特别定制的,我们看一下效果

input:focus {
  background-color: #C5CAE9;
}
体重输入框聚焦的状态
体重输入框聚焦的状态

同理,还有类似的对于复选框、单选框等选中状态的选择所设计的 :checked;为元素禁用和激活状态所设计的 :enabled:disabled。这些就不举例了,比较简单,如果有坑,请指教。

“排头兵”伪类

:first-letter:first-line:first-child 这几个跟在某个元素后面的作用是选取该元素的第一个文字(英文的话是字母)、第一行和父元素的第一个子元素中的所有该元素。还是看图说话吧。
我们把体重的selector加了一个首字母伪类放大字体200%,效果如下图,另两个的效果类似,只不过是第一行或者第一个子元素,自己可以实验一下。

.weight:first-letter {
 font-size:200%;
}
首字大写的效果
首字大写的效果

“前缀”和“后缀”伪类

为什么叫它们“前缀”和“后缀”呢?因为它们是作用于选择内容之前或之后的,为什么要设计这个选择器呢?我们的BMI计算器目前的两个输入值都是没有单位的。如果我们希望增加一个单位的话,当然可以在HTML页面增加,但是如果对于某一类值它们的单位就是某些文字的话,这么做就有点累。我们给css加上下面的样式看看效果。

.weight::after {
  content: "公斤";
}

.height::after {
  content: "厘米";
}

另外一个比较常见的技巧是利用这个伪类去改造默认的控件样式,比如复选框默认是方块型,如何改造成圆形呢?我们就可以先把复选框中的原有表现形式(方块)隐藏起来,然后利用“后缀”伪类画出一个圆来。

//html
<input type="checkbox" class="check">
//css
.check {
  background-color: #8BC34A;
  width: 40px;
  -webkit-appearance: none;
  appearance: none;
}
.check::after {
  content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#fff" stroke-width="3"/></svg>');
}
圆形复选框
圆形复选框

“正着数和倒着数”伪类

css增加一堆很类似数组或集合中常用的选择器,这一类的大部分都是成对的,可以记成正着数和倒着数。为了方便记忆,我就起名叫“正着数和倒着数”伪类了。这一类有好多,包括选择首尾的: :first-of-type:last-of-type:first-child(这个不是css3引入的),:last-child;第n个子元素的 :nth-child(n):nth-last-child(n);第n个某类型子元素:nth-of-type(n):nth-last-of-type(n);当然对于特殊情况,比如只有一个的会有专门的处理::only-child:only-of-type

应用这种选择器可以非常方便的打造一些效果,比如交替颜色的表格。

table {
    width: 100%;
}

tr:nth-child(even){background-color: #f2f2f2}
交错颜色的表格
交错颜色的表格

这里有问题了,这个 even 是怎么回事?这一类Selector是可以接受表达式作为参数的,而 evenodd 作为两个特别常用的东东被认定成关键字,其实 nth-child(even) 可以改写成 nth-child(2n)nth-child(odd)可以改写成 nth-child(2n+1)。是的,如果你愿意可以写出3的倍数,5的倍数等等序列等等。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,737评论 1 92
  • 本文转载自:众成翻译译者:为之漫笔链接:http://www.zcfy.cc/article/239原文:http...
    极乐君阅读 7,369评论 1 62
  • 其实平时用得多的选择器无非也就是那么几个,时间久了,许多不常用的选择器就慢慢忘记了。为了不让自己忘记这些选择器,今...
    盛夏晚清风阅读 1,820评论 0 5
  • 一:在制作一个Web应用或Web站点的过程中,你是如何考虑他的UI、安全性、高性能、SEO、可维护性以及技术因素的...
    Arno_z阅读 1,141评论 0 1
  • 他说: “不敢想象明年我会分配到哪!边疆?海防?总而言之,我愿放弃家中舒适的生活!献身国防。” 我想,你大概也是一...
    小八_阅读 190评论 0 0