选择器进阶 & padding对盒子的影响 & margin的三种特殊情况及解决方案--2019年9月3日20:00
0x01 相邻选择器与兄弟选择器的异同
相邻选择器:选择紧接在某个元素后的一个元素,且这两个元素之间有相同的父元素。它的使用方式是:某元素 + 相邻同父元素的某元素 {}。例如:div + p { }表示选择紧接着div元素出现的第一个段落p,且div元素与p元素应拥有相同的父元素。
兄弟选择器:选择在某个元素后的所有同父元素的同名元素(如果使用 * ,表示选择某元素后面所有同父元素的元素)。它的使用方式是:某元素 ~ 相邻同父元素的某元素名 {}。div ~ p { }表示选择在div元素后的所有与div元素拥有相同父元素的所有段落p。
以下是相关示例:
html文档:
实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="css/demo1.css"> <title>选择器</title> </head> <body> <ul> <li>1</li> <li id="bg-blue">2</li> <li class="bg-green">3</li> <li>4</li> <li class="bg-green">5</li> <li>6</li> <li>7</li> <li>8</li> </ul> </body> </html>
运行实例 »
点击 "运行实例" 按钮查看在线实例
对应的css样式表(demo1.css):
实例
/* 标签选择器 */ ul { /* 清除列表默认样式的方法: */ margin: 0; /* 1. 消除默认内边距 */ padding-left: 0; border: 1px solid red; } ul li { /* 2. 修改li的默认样式list-style-type */ list-style-type: none; width: 40px; height: 40px; background-color: wheat; /* border: 1px solid black; */ text-align: center; line-height: 40px; /* 当border-radius设置为50%时,角会变成圆角 */ border-radius: 50%; /* li本身是块元素,可以通过修改display样式为inline-block,将其转换成行内块元素,使其能在一行显示 即将一个块级元素转为内联元素 */ display: inline-block; /* 第一个2px表示水平偏移的程度;第二个2px表示垂直偏移的程度; 1px表示阴影的扩散程度;#888为阴影的颜色 */ box-shadow: 2px 2px 1px #888; } /* id选择器 */ #bg-blue { background-color: lightblue; } /* 类选择器 */ .bg-green { background: lightgreen; } /* 属性选择器 */ /* 选择拥有某属性的标签,可选中多个 */ /* li[class="bg-green"] { border: 1px solid red; } */ /* li[id] { border: 1px solid red; } */ li[id="bg-blue"] { border: 1px solid red; } /* 群组选择器 */ /* 相当于多选,同时选择多种元素 */ #bg-blue, .bg-green { border: 1px solid blue; } /* 相邻选择器 */ /* 选择紧接在某个元素后的一个元素,且这两个元素之间有相同的父元素 */ /* 只选择一个 */ #bg-blue+li { background-color: yellow; } /* 兄弟选择器 */ /* 选择在某个元素后的所有同父元素的同名元素 */ /* #bg-blue~li { background-color: lightcoral; } */ /* 选择在某个元素后的所有同父元素的元素 */ #bg-blue~* { background-color: lightcoral; }
运行实例 »
点击 "运行实例" 按钮查看在线实例
对于相邻选择器与兄弟选择器来说:他们都是选择某个元素后面的元素,且选择的元素与基准元素拥有相同的父元素。它们的不同之处在于:相邻选择器只选中基准元素后面第一个出现的拥有相同父元素的目标元素,用的连接符是 + ,只选中一个元素;兄弟选择器选中的是基准元素后面出现的所有拥有相同父元素的同名元素,用的连接符是 ~ ,可以一次选中多个。
值得注意的是,上方3号小球的底色是黄色的原因不是因为相邻选择器与兄弟选择器之间存在优先级关系,问题出在通配符*上。因为通配符*表示模糊搜索,而前面出现了一个更准确的选择,所以会默认选择更精确那个。这就是为什么3号球是黄色的原因。
0x02 伪类选择器相关
伪类选择器是指根据元素的位置或状态进行选择的选择器。下面将讨论两个:nth-child( )和nth-of-type( );
以下是相关示例:
html文档:
实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- <link rel="stylesheet" href="css/demo1.css"> --> <link rel="stylesheet" href="css/demo2.css"> <title>选择器</title> </head> <body> <ul> <li>1</li> <li id="bg-blue">2</li> <li class="bg-green">3</li> <li>4</li> <li class="bg-green">5</li> <li>6</li> <li>7</li> <li>8</li> </ul> </body> </html>
运行实例 »
点击 "运行实例" 按钮查看在线实例
对应的css样式表(demo2.css):
实例
/* 标签选择器 */ ul { /* 清除列表默认样式的方法: */ margin: 0; /* 1. 消除默认内边距 */ padding-left: 0; border: 1px solid red; } ul li { /* 2. 修改li的默认样式list-style-type */ list-style-type: none; width: 40px; height: 40px; background-color: wheat; /* border: 1px solid black; */ text-align: center; line-height: 40px; /* 当border-radius设置为50%时,角会变成圆角 */ border-radius: 50%; /* li本身是块元素,可以通过修改display样式为inline-block,将其转换成行内块元素,使其能在一行显示 即将一个块级元素转为内联元素 */ display: inline-block; /* 第一个2px表示水平偏移的程度;第二个2px表示垂直偏移的程度; 1px表示阴影的扩散程度;#888为阴影的颜色 */ box-shadow: 2px 2px 1px #888; } /* 伪类:子元素选择器 */ /* 选中ul标签后的第一个子元素 */ ul :first-child { background-color: lightblue; } /* 这样做的效果和上面的一样,但通常不会这样使用,因为直接指定元素类型有其他方法,在下面将进行演示 ul li:first-child { background-color: lightcoral; } */ /* 选中ul标签后的最后一个子元素 */ ul :last-child { background-color: lawngreen; } /* nth-child(n)表示选中从前往后数第n个子元素,n从1开始 */ ul :nth-child(6) { background-color: lightcoral; } /* nth-last-child(n)表示选中从后往前数第n个子元素,n从-1开始 */ ul :nth-last-child(4) { background-color: coral; } /* 伪类:类型选择器 */ /* 只要在伪类前有确定的元素类型,就使用带type的选择器,即类型选择器 */ /* 伪类:类型选择器的用法与伪类:子元素选择器的用法类似,只是多了个确定的类型 */ ul li:first-of-type { background-color: darkslategrey; color: #fff; } ul li:last-of-type { background-color: darkorange; color: #fff; } ul li:nth-of-type(4) { background-color: darkviolet; color: #fff; }
运行实例 »
点击 "运行实例" 按钮查看在线实例
对于两种伪类选择器来说:
1. 它们的关注点不同。如果关注点是位置,用nth-child( );如果既关注位置又关注类型,用nth-of-type( )。
2. 它们都有两个快捷方式:first和last;
3. 它们的下标开始都是 1。
以下是伪类选择器的小训练:
html文档:
实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="css/demo3.css"> <title>伪类选择器强化记忆</title> </head> <body> <div> <p>窝窝头</p> <li>一块钱四个</li> <p>嘿嘿</p> </div> <div> <p>今天星期几了</p> <li>今天又是充满希望的一天</li> </div> </body> </html>
运行实例 »
点击 "运行实例" 按钮查看在线实例
相应的css样式表(style3.css):
实例
/* 改变以div元素作为父元素的第二个子元素的背景色 */ div :nth-child(2) { background-color: lightblue; } /* 将第一个div元素的第二个p段落的背景与文字颜色进行改变 */ /* 第一种方法 */ /* div:first-child :nth-child(3) { background-color: coral; color: #fff; } */ /* 第二种方法 */ p:nth-of-type(2) { background-color: lawngreen; color: lightcoral; }
运行实例 »
点击 "运行实例" 按钮查看在线实例
0x03 padding对盒子大小的影响与解决方案
以下是padding相关示例:
html文档:
实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="css/demo4.css"> <title>padding</title> </head> <body> <!-- 1. 手动居中 --> <div id="box_outside1"> <div id="box_inside"> </div> </div> <!-- 2. 宽度分离 --> <div id="wrap"> <div id="box_outside2"> <div id="box_inside"> </div> </div> </div> <!-- 3. box-sizing --> <div id="box_outside3"> <div id="box_inside"> </div> </div> </body> </html>
运行实例 »
点击 "运行实例" 按钮查看在线实例
相应的css样式表(demo4.css):
实例
#box_inside { width: 200px; height: 200px; background-color: coral; } #box_outside1 { width: 300px; border: 1px solid black; background-color: lightblue; } /* 给盒子添加padding后会把盒子撑开,以下是各种解决方式 */ /* 1. 重新手动定义盒子宽度 */ #box_outside1 { /* 给外盒子添加内边距50px */ padding: 50px; /* 因为左右各加了50px的内边距,导致盒子被撑宽了100px,所以盒子原本的宽度应减少100px */ width: 200px; } /* 2. 宽度分离,给盒子添加一个中间层,好处是不用再改变本来外盒子的宽度 */ /* 本来的外层盒子 */ #wrap { width: 300px; /* background-color: #000; */ } /* 新增的中间层盒子(干爹) */ #box_outside2 { padding: 50px; background-color: lightgrey; border: 1px solid black; } /* 3. box-sizing,将内容区、内边距和边框一同作为一个盒子,这样盒子的内容就不能撑开盒子了 */ /* 注意:这里必须设置宽度作为基准参照物,否则默认是整个屏幕 */ #box_outside3 { width: 300px; box-sizing: border-box; padding: 50px; background-color: goldenrod; border: 1px solid black; }
运行实例 »
点击 "运行实例" 按钮查看在线实例
0x04 margin的三种特殊现象及解决方法
以下是margin相关示例:
html文档:
实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="css/demo5.css"> <title>margin</title> </head> <body> <!-- 1. 同级塌陷(垂直方向上的高度塌陷) --> <!-- <div id="box1"></div> <div id="box2"></div> --> <!-- 2. 嵌套传递(存在在嵌套关系上,子元素的外边距会自动传递到父元素上去) --> <!-- <div id="box3"> <div id="box4"></div> </div> --> <!-- 3. 自动挤压(这是好处;当一个元素设置了左外边距或右外边距时,会产生自动挤压,将尽可能多的空间留给其他元素);常常用于布局 --> <div id="box5"></div> </body> </html>
运行实例 »
点击 "运行实例" 按钮查看在线实例
相应的css样式表(demo5.css):
实例
/* 1. 同级塌陷 */ #box1 { width: 100px; height: 100px; background-color: lightblue; } #box2 { width: 100px; height: 100px; background-color: lightcoral; } #box1 { margin-bottom: 50px; } #box2 { margin-top: 30px; } /* 2. 嵌套传递 */ #box3 { width: 200px; height: 200px; background-color: lightblue; } #box4 { width: 100px; height: 100px; background-color: lightcoral; } /* 这里我们给子盒子一个上边距 */ /* #box4 { margin-top: 50px; } */ #box3 { padding-top: 50px; height: 150px; } /* 3. 自动挤压 */ #box5 { width: 100px; height: 100px; background-color: lightcoral; } #box5 { margin: 0 auto; /* margin-left: auto; */ /* margin-right: auto; */ }
运行实例 »
点击 "运行实例" 按钮查看在线实例
1. 同级塌陷
从图中可以看出,位于上方的盒子的下外边距占据了两个盒子之间的全部位置。这是因为上盒子设置了margin-bottom:50px; 而下盒子设置的是margin-top:30px; 明显在垂直高度上,上盒子的外边距大于下盒子的外边距,所以以上盒子的外边距为准。解决方法:将较小一方的margin纳入到较大一方的margin作为较大一方的margin样式。
2. 嵌套传递
在示例中,我给了子盒子一个上外边距margin-top:50px; 按照想法,子盒子应该往下移动50px。但是从图片可以看出,子盒子没有发生移动,反而父盒子下移了。这是因为存在嵌套关系时,子元素的margin属性会传递到父元素上导致的。解决方法:将子元素的margin转化为父元素相应的padding,例如子元素的margin-top转换为父元素的padding-top。但这又会产生一个新的问题:padding把盒子撑大了,这时可以通过修改父元素的高度来解决。
3. 自动挤压
在示例中,我给盒子添加了一个样式margin-left: auto; 这个语句的意思是以左边为基准居中。但由于这时margin样式,它会默认为其他元素让出尽量大的空间,所以我们的元素跑到了最右边。如果想要让元素居中,可以使用margin: auto;
0x05 总结
1. 相邻选择器与兄弟选择器的区别主要表现在:相邻选择器是选择紧接在某个元素后的一个元素;兄弟选择器是选择在某个元素后的所有同父元素的同名元素。它们都是选择拥有相同父元素的元素。
2. nth-child( )和nth-of-type( )在用法上是相似的,它们最重要的区别是它们的关注点不同。如果关注点是位置,用nth-child( );如果既关注位置又关注类型,用nth-of-type( )。
3. padding:盒子的内边距,当给内边距增添大小时会把盒子撑大,但我们有三种方式解决:
(1)重新手动定义盒子宽度;
(2)宽度分离,给盒子添加一个中间层,好处是不用再改变本来外盒子的宽度;
(3)box-sizing,将内容区、内边距和边框一同作为一个盒子,这样盒子的内容就不能撑开盒子了;注意:这里必须设置宽度作为基准参照物,否则默认是整个屏幕
4. margin:盒子的外边距。它有三种特殊的现象,以下是相关总结:
(1)同级塌陷(垂直方向上的高度塌陷),会以相邻盒子的较大一方的外边距作为两盒子间的距离;解决方法:将较小一方的margin纳入到较大一方的margin作为较大一方的margin样式。
(2)嵌套传递(存在在嵌套关系上,子元素的外边距会自动传递到父元素上去);解决方法:将子元素的margin转化为父元素相应的padding,例如子元素的margin-top转换为父元素的padding-top。但这又会产生一个新的问题:padding把盒子撑大了,这时可以通过修改父元素的高度来解决。
(3)自动挤压(这是好处;当一个元素设置了左外边距或右外边距时,会产生自动挤压,将尽可能多的空间留给其他元素),常常用于布局;