最近有时间,想把酝酿的几篇博客都写出来,今天前端小学生带着10个问题,跟你们分享一下学习CSS的一些体会,我以为想学好CSS,必须保持一颗好奇心和刨根问底的劲头,而不是复制粘贴,得过且过。本人能力有限,这篇文章从构思加完成用了四五天,若是你和我同样是前端小白,不妨仔细斟酌体会,以期领悟到一些东西;若是你是业界大牛,也请你驻足随意瞄上两眼,把言辞内容不妥的地方指出来,咱们共同讨论。css
时刻保持好奇心html
第一问:当margin的值为百分比形式时,为何浏览器会根据父容器宽度得出计算值?前端
在我以前一篇博客检验你的前端基础——Sit the test中,聊到了margin值为<percentage>时的计算方法。假若有一个父容器宽度400px,高度600px,其子元素设置margin:20% 20%后的计算值应该为“margin:120px 80px”仍是“margin:80px 80px”呢?按照那篇博客中的理论,第二个是正确答案。可是在今天这篇文章中,我给出的答案是第一个确定错,第二个也不必定对。一个符合W3C标准的浏览器会根据父容器的宽度进行计算,可是这个仅限于书写模式为横向的时候。由于在横向排版时,宽度“有迹可循”,能够把浏览器宽度做为参考,可是高度是不固定的,因此margin百分比值在计算时会参考父容器的宽度。当书写模式改成纵向,其计算参考便会变为父容器的高度了。戳我查看DEMO(请在webkit内核或IE下查看)。html5
/*修改书写模式*/
.demo{ -webkit-writing-mode: vertical-rl; /* for browsers of webkit engine */ writing-mode: tb-rl; /* for ie */ }
第二问:margin:auto为何只能实现水平居中,不能垂直居中?css3
当一个常规流中块级元素的margin属性左右值设为关键字auto,且它拥有固定宽度时,它便会平分剩余的水平空间,居中显示。然而若是设置上下值为auto,浏览器获得的计算值为0,并不起任何的效果。那么问题来了,为何垂直方向的auto不生效?程序员
与上一问相似,这与布局相关。网页排版时,常规流的块级元素水平方向老是铺满浏览器窗口,垂直方向各块级元素按照前后顺序从上往下排列,当页面内容过多时网页会出现纵向滚动条,所以原理上纵向是能够无限扩展的,计算时找不到一个固定的参考值,因此纵向的auto没法生效。web
一样,margin:auto会受书写模式的影响。当书写模式为纵向时,margin:auto垂直方向是能够居中的,水平方向仍然能够居中(仅当父元素为body时,见下方评论)。不信?请本身写个demo试试吧。其实受到书写模式影响的属性除了这些外,还有margin折叠、padding百分比值的计算等。面试
第三问:可让一个position:fixed的元素相对于一个容器定位而非浏览器视口吗?浏览器
提到position:fixed,不少人都会说这是一个定位属性,与absolute的区别是它针对浏览器视口定位。个人博客导航栏就是利用“position:fixed”属性,让其始终保持在窗口的最上方。不过仍是不要忘记“世事无绝对”,CSS实现了一个position:fixed的元素相对于一个容器定位,请在FireFox下查看此DEMO。网络
当一个元素应用了CSS3的transform属性后,它的后代元素的fixed都将失效。http://www.w3.org/TR/css3-transforms/#issue-ca2c412c。所以能够利用这个Bug模拟出一个相对于某个包含块fixed的效果。
关于transform更多的影响能够在张鑫旭的博客中看到:CSS3 transform对普通元素的N多渲染影响。
第四问:能够用CSS实现面板的隐藏和显示吗?
如今要实现这样一个功能,经过CSS切换某个面板的显示或隐藏。当提到CSS,咱们天然而然想到了控制某个单一元素的样式,一旦涉及到多个元素交互,咱们每每使用JavaScript操做Dom。事实上这个需求不但能够用CSS来实现,甚至实现方式不止一种,请狂戳DEMO:三种CSS方式实现面板隐藏和显示。
第一种利用了label和checkbox,使控制方和被控制方不须要有特定的HTML结构关系,可是须要额外的HTML标签来支持。第二种方式利用了hover和子元素选择器,第三种方式利用了focus和兄弟元素选择器,后两种都受限于特定的HTML结构。三种方法都只使用CSS实现了面板的隐藏显示。
第五问:能够用CSS作出一个图标吗?好比一个三角形?一个小房子?
一个标签,放在HTML中,只能表明一种语义。然而一个标签加CSS,则能够创造出无限的可能。请看DEMO:CSS实现三角形,小房子图案。
利用border互相覆盖呈现出的斜线,能够模拟出多种多样的几何状。在CSS3中,每一个元素都有::before和::after两个伪元素,对同一个标签,由CSS能够操控的单位由一个变为三个,再加上绝对定位的辅佐,各类各样的形状被创造了出来。
你能想象吗?这些图标都是用CSS画出来的。要想了解更多的CSS3图标,能够访问这个网站:http://www.uiplayground.in/css3-icons/
第六问:我想写针对IE6,7的hack,该怎么写呢?
你可能会这么回答:使用 “>”,“_”,“*”等各类各样的符号来写hack。是的,这样作没错,可是须要记住每一个符号分别被哪些浏览器识别,而且若是写的太乱将形成代码 阅读起来十分困难。学习CSS必须抱有一种质疑精神,有没有一种hack方法能够不写这些乱七八糟的符号,而且代码易维护易读呢?咱们能够看看好搜首页是怎么作的:在页面顶端有这样一句话:
<!DOCTYPE html> <!--[if lt IE 7 ]><html class="ie6"><![endif]--> <!--[if IE 7 ]><html class="ie7"><![endif]--> <!--[if IE 8 ]><html class="ie8"><![endif]--> <!--[if IE 9 ]><html class="ie9"><![endif]--> <!--[if (gt IE 9)|!(IE)]><!--><html class="w3c"><!--<![endif]--> <head>
在页面的CSS中,会看到这样的规则:
.ie7 #hd_usernav:before, .ie8 #hd_usernav:before { display: none } .ie6 .skin_no #hd_nav li, .ie7 .skin_no #hd_nav li, .ie8 .skin_no #hd_nav li { border-right-color: #c5c5c5 } .ie6 .skin_no #hd_nav a, .ie7 .skin_no #hd_nav a, .ie8 .skin_no #hd_nav a { color: #c5c5c5 } ……
这样作的优势就是克服了使用特殊符号hack的那些缺点,缺点是须要写更多的代码,使页面增大。
一个前端er对上面这些问题知道与否,并不影响他是否能够完成一个项目,建设一个网站。可是若是没有好奇心,不想追究内在缘由,仅抱着“我不想知道这么多东西,反正我会用就行”这样一种态度,那么他充其量算是一个“程序员”,而非一位“工程师”。
就是要刨根问底!
第七问:行内级元素能够设置宽高吗?
不会为自身内容造成新的块,而让内容分布在多行中的元素叫作行内级元素。此类元素能够与其它行内级元素在同一行中显示而不会另起一行,例如span,strong。在面试时,当被问到行内级元素能否设置宽高时,根据咱们的经验每每会回答不能。可是这样每每着了面试官的道,由于有一些特殊的行内元素,好比img,input,select等等,是能够被设置宽高的。一个内容
不受CSS视觉格式化模型控制,CSS渲染模型并不考虑对此内容的渲染,且元素自己通常拥有固有尺寸(宽度,高度,宽高比)的元素,被称之为置换元素。好比img是一个置换元素,当不对它设置宽高时,它会按照自己的宽高进行显示。因此这个问题的正确答案应该是置换元素能够,非置换元素不能够。
第八问:CSS规则根据优先级生效,低优先级的规则会被浏览器忽略仍是覆盖?
在个人以前一篇博客中,提到了浏览器中CSS优先级的使用规则:多个优先级的样式都会被渲染,只不太高优先级会覆盖住低优先级,元素呈现为高优先级的样式。如今请考虑这样一个问题,在一个div应用了两条background-image规则,照以前的理论来看,两条规则都会渲染,那么请问浏览器会请求被覆盖规则的背景图片吗?
真实状况是浏览器会聪明到只请求当前应用的背景图片。简单理解的话,浏览器只会为生效的CSS规则中的图片资源发出http请求。若是深究的话,就必须谈谈浏览器的工做原理了。本人目前水平不够,如下红色字体为我的理解,请选择性阅读。
在现代浏览器中,一个页面从请求到呈现,大体须要通过解析-构建DOM树-构建呈现树(框架树)-布局(重排)-绘制等几个步骤。一个页面的展示并非一蹴而就的,而是分步骤有条不紊的进行。众所周知的样式表层叠顺序和特异性计算发生在构造呈现树的过程当中,就是为了解决规则不止一个时的问题。以上面提到的背景图案为例,浏览器计算完优先级后,只有后定义的背景图案规则被构建到呈现树上。接下来浏览器会进行重排和绘制,浏览器在绘制时才会请求背景图片规则用到的图片文件。这就是为何只发出一个HTTP请求的缘由。
了解浏览器的工做原理不只能够认清CSS解析和渲染过程,还能够体会到重排和重绘发生的时机,这对咱们写出高效的CSS规则和JavaScript Dom操做有着很是深入的指导意义。这个话题太大,目前个人水平也不足以涉猎到此,等学有所成后我会再发一篇文章详细谈谈。这里有一篇经典的文章,感兴趣的能够看看:浏览器的工做原理:新式网络浏览器幕后揭秘。若是没法访问,查看此国内地址:w3ctech:浏览器的工做原理。
第九问:使用margin能够作出圆角按钮的原理是什么?
当不能使用border-radius时,如何制造一个圆角按钮?如今有一个制造1px圆角的小技巧:button中嵌套span,设置span的margin为:“margin:1px -1px”。戳我查看DEMO。
知道这个小tip的人不在少数,那么是什么原理致使这种现象呢?学习CSS就须要刨根问底,一张图能够把这个问题说明白。
图中红色框为span标签,蓝色框为a标签。当设置span的左右margin为-1px时,其便会在左右各突出1px,形成一种1px圆角的视觉效果。一样的道理,在实现一些古老浏览器下的圆角与底色渐变的按钮时,一般也会利用到多层元素层叠制造视觉偏差的原理。
第十问:清除浮动有N种方式,他们间有什么共同点吗?
所谓清除浮动,通常是为了解决子元素浮动致使父容器高度坍塌。目前有多种方式来解决这个问题,最多见的有after伪元素,父元素设置“overflow:hidden”等等,请看DEMO:七种清除浮动的方法。
其实按照原理,这几种方法能够概括为两种:clear:both法和构造BFC法。
方法 | 分类 |
浮动末尾添加新标签,设置样式为clear:both | clear:both |
浮动末尾添加<br />标签 | clear:both |
使用::after伪元素 | clear:both |
父元素设置display:table | 构造BFC |
父元素设置overflow:auto | 构造BFC |
父元素设置overflow:hidden | 构造BFC |
让父元素也浮动 | 构造BFC |
使用“clear:both”来清除浮动天然没必要多说,那么什么是构造BFC法呢?
Block formatting contexts(BFC),块级格式化上下文是在CSS2.1中提出的一个概念,在布局中,BFC自成体系,对本身内部的元素负责,不会与浮动元素重叠,相邻BFC上下margin也不会重叠。因此咱们会经过构造一个BFC来防止margin重叠,清除浮动或者实现一个双栏布局。
那么如何构造一个BFC呢?1.float设置为非none值;2.overflow设置为非visible;3.display设置为table-cell,table-caption,inline-block;4.position设置为absolute或fixed。这些方法恰好与上面提到构造BFC来清除浮动的方法相呼应。
须要特别注意的是,在IE6,7下没有BFC这个概念,可是有一个与BFC性质类似的概念:layout。在IE6,7中遇到的不少bug均可以经过让元素has layout来解决,好比浮动margin双边距,躲猫猫,3像素间距等等。
有些元素例如table,input自己就has layout,那么如何让一个普通元素has layout呢?包括但不限于如下几种方法:1.position:absolute;2.float不为none;3.display:inline-block;4.height:除auto外任意值;5.width:除auto外任意值;6.zoom:除normal外任意值;7.overflow非visible(仅限IE7)。
这也是为何咱们会在IEhack中常常看到“height:1%”、“zoom:1”、“display:inline-block”、“overflow:hidden”这些字眼的主要缘由,其实就是为了让元素has layout嘛!
因此在IE6-7下,清除浮动除了可使用clear:both外(::after伪元素没法使用),另外一种方法就是让父元素has layout。
关于清除浮动更多的探讨能够在一丝冰凉的博客中看到:那些年咱们一块儿清除过的浮动。
总结
学习任何一门语言,或者一个事物都不能得过且过,抱着前人播种后人收的思想。纵然站在巨人的肩膀上能够少走不少弯路,可是我的仍然要保持好奇心和刨根问底、质疑的精神。多想一下“为何”,少记一些“该这样作”,这在CSS的学习中尤为重要。
CSS很简单,她的出现仅仅是为了排版。CSS很复杂,一个简单的排版每每有N种解决方案。
望诸君共勉。
(完)