(自己翻译的,原文链接点击查看原文即可)
我学做网站的的时候用了一种老掉牙的方式:F12看网站的HTML源代码然后直接拷下来用,然后投身于一些奇怪的书研究那些看不见的东西(比如PHP/MySQL),后来我就变成老司机了(滑稽。
当时是1999年,那时候我们还写像
和DHTML(Dynamic HTML,现在怕是绝迹了)这种玩意儿。
当CSS出现后我也是按之前的方法学习的(CV工程师万岁)。但是如果有可能的话我是真的想下功夫学一下CSS的,因为有很多基本的东西我搞不懂。
下面是一些我希望早点掌握的CSS知识点。
Block,inline and inline-block:
(块级元素,行内元素以及行内块元素,以下的CSS术语不再翻译为中文)
虽然我知道有这么些个属性,但是从来没有全面的去了解过他们。
举个例子:
block元素在水平方向占了一整行(像heading)。可以给他们设置垂直方向的margin。
inline元素在水平方向上只占满足他们内容的宽度(像strong或者em这种标签),不能给他们设置垂直方向的margin(无法调整距离上下的位置),并且他们通常应该位于block元素内部。
inline-block元素基本上跟inline一样,但是他们可以设置垂直方向的margin。很多地方可以用到,比如button,虽然他在一行内,但是可以设置margin-top/margin-bottom来在本行内上下调整位置。
下面的demo中block元素是蓝色的边框,inline元素是橙色的背景,而inline-block则是红色的边框:
Images are inline:
img标签默认的display是inline(行内元素),本身没毛病。但是当我们想给它们设垂直方向的margin时会让你很蛋疼。
如果你在全局重写默认样式时没写这玩意儿,我建议你加上:
这样会使img标签的行为更加可预测,也可以追加一条
max-width:100%;
防止img宽度超出容器 :)
How height and width are calculated:
(height和width到底该TM怎么计算)
“
CSS盒模型顺序很好记啊,苹果笔记本最贵的那个叫啥?
MBP嘛---Margin->Border->Padding
”
默认情况下,盒模型的height/width计算方式是这些玩意儿加起来:
Content area(里面内容的宽度)
Padding area(内边距)
Border area (边框宽度)
在我们计算height的时候一般没啥毛病---因为鬼知道内容会被撑到多高?但是在计算width的时候就蛋疼了,特别是一行内有多个元素的时候。
看下面的CSS:
这个class的真实width其实应该是50% + 4em +0.2rem,如果你以为设置50%可以一行放俩那就错了,绝对会换行,因为两个宽度加起来已经超出100%了。
这是因为有一个属性叫box-sizing,几乎应用于所有元素,它的默认值是content-box,意思是height/width属性设置的内容区域的宽高,别的padding、border啥的在这个基础上往外加。
可以为所有元素设置一个这样的样式:
再看上一个例子,元素的width/height现在是设置的从内容到border的宽高,所以现在例子里的总宽度应该是50%(别问padding,padding不是在border和content之间吗,一块算了)
Margin:
注意,本段没有考虑margin,因为margin是两个元素之间的间距,所以无论怎么设置box-sizing,margin都不会被计算到总的宽高里去。
Padding & margin aren’t the same:
(padding和margin:“我们不一样”)
如果一个元素没有设置background或者border,那么padding和margin看起来差不多,其实并不是。
margin是元素之间的填充距离
padding是元素内部的填充距离(从border到content)
在元素有background的时候padding会很有用。一般情况下我们不太愿意元素里的内容太靠近元素边界,设置padding的话可以使内容和边界之间产生距离,比较美观。
Margins collapse:
(当block元素的margin碰见margin:“老子会折叠”)
这是个困扰了CSS新手很久的问题。Rachel Andrew这么描述这个现象:
“When margins collapse, they will combine so that thespace between the two elements becomes the larger of the two margins. Thesmaller margin essentially ending up inside the larger one.”
(当margin折叠时,会以两个margin值之中最大的那个为准,小的那个margin本质上是在大的margin里面,当俩margin一样时,取其中一个,不会累加)
举个例子,如果我们有两个块元素,上面那个设置了margin-bottom:50px,下面那个设置了margin-top:100px,那么两个元素之间的margin其实是100px,而不是150px(没想到吧哈哈):
注意:margin折叠只发生在块元素(display : block)之间,且如果父元素设置了display: grid或者 display: flex的话则不会折叠。
Browsers have a default stylesheet:
(浏览器有自己默认的一些样式)
CSS全称层叠式-样式-表(Cascading-Style-Sheets,也有翻译级联式样式表的)
因此层叠是CSS的基本概念也没啥好奇怪的。
尽管我们可能知道自己写的样式是如何互相作用的,但是还是得记住一条:浏览器永远有自己默认的样式。不过由于这玩意儿在我们自己写的样式之前加载,所以很容易就重写了。
不同浏览器的默认样式不同,但是基本上这些是一样的:
Heading的大小不同(h1/h2/...)
文本颜色是黑的
列表前面有个点儿
元素有些有display属性(比如block或者inline)
等等等等……
即使网站只有一个CSS文件,它的样式也会和浏览器默认样式合并。
Use relative units everywhere:
(相对单位em/rem:请尽情的使用我吧)
像素(px)单位用起来是很爽的,因为很容易理解:
font-size: 24px
这么定义的话文本大小就是24px。但使用px有时候并不能带来很好的用户体验,特别是用户有时会用ctrl+滚轮缩放浏览器来调整内容的大小。
我很早就用em来作为font-size单位了(后来用rem),但是想要在比如padding,margin,letter-spacing和border这些属性上把em和rem用得很爽的话是需要下一些功夫的。
理解em和rem之间的区别是用好他们(相对单位)的关键。
例如:可能使用em来做@media媒体查询和垂直方向的margin,但是rem始终用来设置border-width。
下功夫研究相对单位的大小是很值得的,但是得小小的调整一下以前的思维模式。
::before and ::after need content:
(没有content你们是看不见老子的)
当使用::before和::after这种为元素时,必须要设置content,即使给一个空值:
如果不设置content,它们就不显示。
The ch unit:
ch(字符)这个单位也是很有用的,特别是粗略的根据一行内字符数量来设置宽度的时候。
仅仅是粗略估计吗?技术上来讲,ch这个单位不会计算一行内有多少个字符。他是基于0个字符时候的width来的。
Eric Meyer 这么写道:
“1ch is usually wider than the average character width,usually by around 20-30%.”
(1ch通常比一行内字符的平均宽度要宽一点,一般宽20%-30%左右)
如果你正在用ch控制段落(p标签)或者类似东西的大小,请注意下这一点。
Normal flow:
(正常的排版?)
这个词儿我听过很多次,但一直没理解啥意思。“正常流”(可能翻译不当)的意思是元素在页面上出现的顺序和代码中出现的顺序是一致的。例如:
不特别指定样式的话,页面上会先渲染一个
,在它下面再渲染一个
,这就是“正常流”。
如果一个元素跳出了正常流,他就不会在原有的位置渲染,float和absolute布局的元素就是很好的例子。
Styling :focus states:
(有伪元素,就有伪选择器)
头回研究:hover,:focus和:active这些伪选择器的时候是在解决a标签的样式时。那时我看到几乎所有例子都是这样的:
然而,如果设置不同的:focus属性会更好。
:focus是表示当用户使用tab键或者操作页面上具有焦点的元素(比如a,button等)时获取到焦点的元素的一个状态。
当用户按下tab键的时候,他们一般不会知道焦点会落到哪儿。而且,当用户注意鼠标悬浮的元素时,也不知道焦点在哪儿。
由于上述原因,最好给:focus一个不同于:hover和:active的样式,让用户能区分:
:nth-child():
(几个孩子啊?)
康康这个demo:
可以注意到所有行号为奇数的都有背景色,使用 :nth-child(even) 可以为偶数的行设置样式。
然而,:nth-child()是计算所有的兄弟元素的,如果指定p标签p:nth-child(odd),而p标签之前又有别的标签作为兄弟元素,那么p不会是第一个child。
所以解释了上面的demo中有颜色p行明明是奇数行,却用了:nth-child(even) even代表偶数,因为在p前面有一个h1标签。
如果我们想根据指定的类型或者标签来给nth-child加样式的话可以使用:nth-of-type()选择器,它可以值选择本身之前的标签或者样式,比如:
这个例子可以看出:nth-child() 和:nth-of-type()的细微差别,使用时操点心可以解决很多麻烦。
总结:
写熟练CSS不是难事儿,难的是知道它为啥这样写、原理是啥,这才是能写出更好CSS代码的关键。