Mr.xu 发布的文章

前端框架浅析Bootstrap、Yui等

现在很多人会使用 CSS 框架进行快速建站。
那 CSS 框架是什么呢,它通常是一些 CSS 文件的集合,这些文件包括基本布局、表单样式、网格、简单组件、以及样式重置。使用 CSS 框架大大降低工作成本进行快速建站。
当然对于一些大型的项目,可能会很难照搬某些框架直接使用的,因为直接使用会带来一些限制或者冗余的问题。
但在 CSS 框架已经日趋成熟的今天,在我们设计项目架构、规范的时候,现时市面上一些优秀的框架也可以给我们提供很多可借鉴的地方。

目录分析


可以看到,在目录架构上4个框架基本都是遵循基本样式+用户定义扩展样式的常规方式进行组织。

然而,如果按 Bootstrap 做法的话,可能会出现把不常用组件样式也包含在全局样式中一并引入,如果把组件也写在全局 CSS 中,最好确保该组件出现频率较高才引入,避免不必要的带宽浪费

关于 hack:
对于针对低版本浏览器所写的 hack,对它的处理方式,Blueprint 和 Yaml 都是使用单独引入 hack 文件的形式进行处理,笔者也尝试过这样的做法。
个人觉得这种方式的好处是可以避免给高级浏览器带来冗余代码,而且通过条件判断引入 CSS 也不会给高级浏览器带来额外的请求。

这种方式比较适用于,高低级浏览器本来就刻意设计成有较大差别的情况下,即 hack 比较多的时候才使用。不然就为了十来行 hack 而多引入一个文件的话似乎也不太可取。

css规范

  1. 前缀
    框架中公用模块都有前缀,分别有以下3个思想:
  2. Yaml , Yui :无论如何都是统一的标识开头,再加上改模块名称。
  3. Bootstrap:直接模块名称,这方式需要定义关键字。公用模块是 button 都以 btn – 开头, image 则以 img- 开头。
  4. Nec :单字母开头来标识组件。

一般来说应用一个框架,我们先引入框架的样式,再在之上覆盖上自己的样式,所以可以把框架看作是我们的基础CSS。

我们可以借鉴框架的前缀规范来规划我们的基础 CSS 前缀,根据自己的项目实际情况采取不同的方案。

  1. 类的划分
    类的划分方式在框架中主要有2种标准,分别为:以【组件为粒度】,和以【属性为粒度】。
  2. 组件为粒度:把组件的所有样式封装在一个类名中,调用类名即可使用该组件。
  3. 属性为粒度:需要属性的时候,调用对应类名拼装。

在我们日常项目中,以属性对类名进行划分比较少见,因为一直遵循的都是“结构、样式、行为”分离的原则,力求降低三者的耦合度。

然而以这种方式划分在一些特定情况下也不是完全不可取。

例如对于一些元素的隐藏,如果没提供相关的类名的话,在js开发阶段开发就会直接内联 style 在对应的元素上(这将会触发 repaint/reflow),所以更好的方式是和js开发约定一个类名触发显示/隐藏的动作,在这种情况下,给 display: none 划分一个特定的类名,供给开发调用就会显得很实用了。

所以,更重要的是我们对所在的实际情况进行分析,并给出最佳的解决方案。

  1. 组件类名组合方式
    组件的样式,基本都是 基础类名+扩展类名 的套路来进行组合的变化。

但在选择符方面可以有3种方式, 目前最多框架使用的是:多类选择,通过修改 html 的类名组合,实现还原。

以按钮样式的实现为例:

这里采用常规的组合方式,不再赘述。

  1. 高级 CSS 选择器
    在对 Bootstrap 进行分析的过程中,发现 Bootstrap 定义了一系列的icon,这些 icon 的类名全部都是以 icon- 为前缀。

而在 CSS 中,Bootstrap 用到了子串匹配属性选择器。

[class^=”icon-“]

使用这个的好处是,对于 icon 类的标签,我们再也不需要对其加一个对于 icon 的公用类名,只需要类名是以 icon- 开头就可以匹配所有 icon ,省了一个类名。

使用这种方式可以降低一定的成本,但是只在 IE7+ 浏览器才适用,如果要使用该类选择器的话请考虑是否需要兼容 IE6。
虽然 IE6 不支持,但是高级 CSS 选择器的确十分吸引,并且可用于移动端,所以特此提一下。

图标和动画

在参考的 CSS 框架中,它们会提供一些简单的图形元素, 但是实现的方式也有彼此不同之处。

但是共同点是,现今较新的框架,对于一些简单的效果,都会使用 CSS3 实现一些简单的渐变,对低版本 IE 进行优雅降级。

综合实践

对于目录组织:
目录组织——
可以考虑结合 Bootstrap 与 Yaml/Blueprint 的思想。

a .把常用的基础样式压缩合成一个文件。

  1. 把不必现组件样式抽离成单独 CSS,按需加载。

【优化点】
减少了单个 global_min 文件的大小。

【权衡点】
需要考虑由此可能导致的请求数过多问题。

hack——
根据实际情况,可考虑把针对 IE6 的 hack 文件单独分出来。

【优化点】
便于对低级浏览器的大型差异化处理,并且减少对于高级浏览器的冗余代码。

对于 CSS 规范:
CSS 前缀——
可考虑尝试 Nec 的方式,约定 “单字母_xxx”为公用样式的标识,取消单一的公用前缀,通过以不同字母作为顶级前缀,对公用模块进行划分。

【优化点】
减免了“公用前缀_组件前缀_组件名”的多级前缀,通过以类名格式作为标识,代替了原来公用前缀的作用。

【权衡点】
仍需按项目实际情况考虑。

类的划分——
可考虑约定统一几个功能性的类名(以属性为粒度的类名),例如元素隐藏的类名,供给js调用。

【优化点】
减免让开发直接写 style 内联 CSS,造成页面的 reflow/repaint。

高级 CSS 选择器——
在对移动端页面进行重构时可以考虑使用更高级的 CSS 选择器。
例: [class^=”icon”],:first-child,:nth-child(n)….

【优化点】
相比于传统的方法,节省类名。

对于图形:
考虑与设计师约定,视觉效果在可接受范围内,部分效果使用 CSS3 实现,对低级浏览器实现优雅降级。

【优化点】
大量减少图片的使用,节省带宽以及请求数。

CSS实现垂直居中的5种方法

利用 CSS 来实现对象的垂直居中有许多不同的方法,比较难的是选择那个正确的方法。我下面说明一下我看到的好的方法和怎么来创建一个好的居中网站。

使用 CSS 实现垂直居中并不容易。有些方法在一些浏览器中无效。下面我们看一下使对象垂直集中的5种不同方法,以及它们各自的优缺点。

方法一

这个方法把一些 div 的显示方式设置为表格,因此我们可以使用表格的 vertical-align property 属性。

#wrapper {display:table;}
#cell {display:table-cell; vertical-align:middle;}

优点:
content 可以动态改变高度(不需在 CSS 中定义)。当 wrapper 里没有足够空间时, content 不会被截断

缺点:
Internet Explorer(甚至 IE8 beta)中无效,许多嵌套标签(其实没那么糟糕,另一个专题)

方法二:

这个方法使用绝对定位的 div,把它的 top 设置为 50%,top margin 设置为负的 content 高度。这意味着对象必须在 CSS 中指定固定的高度。

因为有固定高度,或许你想给 content 指定 overflow:auto,这样如果 content 太多的话,就会出现滚动条,以免content 溢出。

#content {
    position:absolute;
    top:50%;
    height:240px;
    margin-top:-120px; /* negative half of the height */
}

优点:
适用于所有浏览器
不需要嵌套标签

缺点:
没有足够空间时,content 会消失(类似div 在 body 内,当用户缩小浏览器窗口,滚动条不出现的情况)

方法三

这种方法,在 content 元素外插入一个 div。设置此 div height:50%; margin-bottom:-contentheight;。
content 清除浮动,并显示在中间。

#floater    {float:left; height:50%; margin-bottom:-120px;}
#content    {clear:both; height:240px; position:relative;}

优点:
适用于所有浏览器
没有足够空间时(例如:窗口缩小) content 不会被截断,滚动条出现

缺点:
唯一我能想到的就是需要额外的空元素了(也没那么糟,又是另外一个话题)

方法四

这个方法使用了一个 position:absolute,有固定宽度和高度的 div。这个 div 被设置为 top:0; bottom:0;。但是因为它有固定高度,其实并不能和上下都间距为 0,因此 margin:auto; 会使它居中。使用 margin:auto;使块级元素垂直居中是很简单的。

#content {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    margin:auto;
    height:240px;
    width:70%;
}

优点:
简单

缺点:
IE(IE8 beta)中无效
无足够空间时,content 被截断,但是不会有滚动条出现

方法五

这个方法只能将单行文本置中。只需要简单地把 line-height 设置为那个对象的 height 值就可以使文本居中了。

#content {height:100px; line-height:100px;}

优点:
适用于所有浏览器
无足够空间时不会被截断

缺点:
只对文本有效(块级元素无效)
多行时,断词比较糟糕

这个方法在小元素上非常有用,例如使按钮文本或者单行文本居中。

哪个方法?
我最喜欢的是方法三,缺点不多。因为 content 会清除浮动,所以可以在它上面放置别的元素,并且当窗口缩放时,
居中的 content 不会把另外的元素盖住。看例子。

#floater    {float:left; height:50%; margin-bottom:-120px;}
#top        {float:right; width:100%; text-align:center;}
#content    {clear:both; height:240px; position:relative;}

现在你知道是怎么回事了,现在我们开始创建一个简单但是有趣的网站。最终的样子是这样的:

IE6 浏览器常见兼容问题汇总

1.<!DOCTYPE HTML>文档类型的声明。

产生条件:IE6浏览器,当我们没有书写这个文档声明的时候,会触发IE6浏览器的怪异解析现象;

解决办法:书写文档声明。

2.不同浏览器当中,很多的标签的默认样式不同,如默认的外部丁内补丁。

产生条件:不同浏览器;

解决办法:利用CSS reset文件进行样式的清除,然后再根据需要进行设置。

3.横向双倍外边距

产生条件:在IE6中块元素浮动后,会出现横向双倍margin现象。

解决办法: 在float标签的样式控制中加入display:inline

4.默认行高

产生条件:IE6、IE7、遨游浏览器;设置的文字高度超出盒模型内容区域设置的高度时会影响布局。

解决办法:给超出高度的标签设置overflow:hidden;或者将文字的行高line-height设置为小于块的高度。

5.img外部的border

产生条件:img外部有a标签,即img标签有链接时

解决办法:设置img边框border:0;

6.图片默认有间距。

产生条件:img标签(每个img之后敲了回车)

解决办法:为img设置float的浮动布局方式。

7.经典3像素bug

产生条件:IE6浏览器,浮动块元素与未浮动块元素处于同一行,有默认的3px间距。

解决办法:设置非浮动元素浮动。

8.默认行高

产生条件:清除浮动的时候,有些人会采取一种清浮动的方法,使用一个空的div,然后为这个div设置{clear:both}。在大部分

浏览器当中,这样做是没有任何问题的,但是在IE6浏览器当中,div即使是空的,也会存在默认行高。

解决办法:设置其高度为0,并设置overflow:hidden。{height:0;overflow:hidden;clear:both;}

9.a标签hover不适用于所有标签

产生条件:IE6浏览器中hover只支持a标签的使用,不支持一切其它标签使用;

解决办法:合理用a标签嵌套其他行内标签或者用javascript模拟a的hover效果;详情请查看日志:兼容IE6 a标签hover效果

10.table标签当中border-color属性设置无效

产生条件:IE6中table设置属性border-color无效;

解决办法:运用CSS样式进行控制,而不是使用属性进行样式的处理。

11.png格式图片

产生条件:IE6浏览器,不支持透明;

解决办法:使用javascript进行处理;或者使用gif、jpg图像替代掉png图片的使用。

12.透明rgba与opacity

产生条件:IE6不支持此两种透明的设置方法;

解决办法:使用IE6当中的滤镜filter替代掉,如:opacity:0.6;filter:alpha(opacity=60)。

13.子选择器在IE6中不能使用

产生条件:IE6浏览器,使用E>F子选择器;

解决办法:采用其他选择器或者采用后代选择器进行控制,如:div p{margin:10px;} div p p{margin:0;}替代掉 div>p{margin:10px;}。

14.不支持最大最小宽高

产生条件:IE6浏览器,标签的最低高度/宽度设置(min/max-height)

解决办法:为IE6单独设置hack,即_height:最小高度值;_width:最小宽度值(对于IE6,当实际宽高超出定义的宽高时,元素会自动调整宽高)。对于最大高度和最大宽度,没有必要设置兼容,当前对于开发者来说,只需要保证IE6下正常显示即可,无需在它身上花费太多功夫。

15.纵向居中,IE6不支持display:table-cell

产生条件:IE6浏览器,设置一个元素在另一个元素中垂直方向上居中对齐,不能够支持以单元格的方式来显示元素;

解决办法:如果是单行文本,采用line-height和height的配合使得文本垂直居中,如果中间是其他元素或者多行文本,采用其他方法进行居中处理,处理方法有多种,详见日志:CSS元素水平垂直居中。

16.input 聚焦框颜色与样式不同

产生条件:各个浏览器表现不同;

处理方法:使用outline:none,清除默认样式之后再统一设置。

17.鼠标移上小手效果

产生条件:IE6,cursor:hand :IE完全支持。但是在firefox是不支持的,没有效果。cursor:pointer :是CSS2.0的标准。所以firefox是支持的,但是IE5.0既之前版本不支持。IE6开始支持。;

解决办法:设置两种cursor:pointer ; cursor:hand。

18.子标签无法撑开父标签的高度

产生条件:父标签内部含一个或多个子标签,父标签没有设置浮动,而子标签发生浮动;

处理方法:方法1:在子标签最后添加清除浮动的设置<div style='height:0;clear:both'></div>; 方法2:为父标签添加{overflow:hidden;}的样式; 方法3:为父标签设置固定高度。

19.li的间距问题

产生条件:IE6浏览器 li标签设置宽高,且li里面的元素发生了浮动;

处理方法:方法1:li不设置宽高; 方法2:li内部的标签不进行浮动。

20.行内元素布局混乱

产生条件:行内元素为包含框时,如果包含框包含的绝对定位元素以百分比为单位进行定位;

处理方法:在行内元素当中加入{zoom:1},触发IE的hasLayout。关于hasLayout的更多介绍请参见日志:hasLayout IE浏览器bug的来源。

21.多显示一个字

产生条件:多个浮动元素中间夹杂HTML注释语句,浮动元素宽度设置为100%;则在下一行多显示一个上一行的最后一个字符;

处理方法:果断删掉注释!

22.CSS优先级 !important

产生条件:IE6当中,在同一组CSS属性中,!important不起作用;

处理方法:单独设置。

23.img图片下部高度多余5px

产生条件:IE6浏览器;

处理方法:将图片转化为块级对象,即display:block。还有四种其他方法,详细解释参见日志:“IE6 BUG 图片元素img下 高度超出 出现多余空白”

hasLayout IE浏览器bug的来源

hasLayout是IE特有的一个属性。很多的ie下的css bug都与其息息相关。在ie中,一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元素来计算尺寸和组织内容。当一个元素的hasLayout属性值为true时,它负责对自己和可能的后代元素进行尺寸计算和定位。虽然这意味着这个元素需要花更多的代价来维护自身和里面的内容,而不是依赖于祖先元素来完成这些工作。

默认 hasLayout=true 的标签:

<table> <td> <body> <img> <hr> <input> <select> <textarea> <button> <iframe> <embed> <object> <applet> <marquee> 

很多情况下,把 hasLayout的状态改成true 可以解决很大部分ie下显示的bug。 hasLayout属性不能直接设定,通过设定一些特定的css属性来触发并改变 hasLayout 状态。

元素hasLayout而导致的问题其实一般都很容易发现:往往是内容出现错位甚至完全不可见。
如:当一个元素内含浮动或绝对定位的内容时,它通常会表现出奇怪和错误的行为

一般如果是因为layout而引起的显示不符期望效果的话,在ff下会表现正常,而在ie下会出现错误。这个时候可以尝试触发父容器及其中的子容器的haslayout属性,通常可以通过加上zoom: 1;来调试。直到找到了产生问题的元素,再进行针对性的修正。最好的办法是对这个元素设置尺寸属性。但是,有时不便指定尺寸属性的情况下,就只能寻找替代方案了。对于ie7 ,最好的办法是设置最小高度属性为0;这个技术是无害的,因为0本来就是这个属性的初始值。而且没有必要对其他浏览器隐藏这个属性。而对于ie6和更早版本中触发一个元素hasLayout的方法是在overflow属性是visible的情况下设置这个元素的高度属性为1%,然后对其他浏览器隐藏这个设置。这种技术就是著名的Holly hack。

display
启动haslayout的值:inline-block
取消hasLayout的值:其他值

width/height
启动hasLayout的值:除了auto以外的值
取消hasLayout的值:auto

position
启动hasLayout的值:absolute
取消hasLayout的值:static

float
启动hasLayout的值:left或right
取消hasLayout的值:none

zoom
启动hasLayout的值:有值
取消hasLayout的值:narmal或者空值
(zoom是微软IE专有属性,可以触发hasLayout但不会影响页面的显示效果。zoom: 1常用来除错, ie 5不支持。)

ie7还有一些额外的属性可以触发该属性(不完全列表):
min-height: (任何值)
max-height: (任何值除了none)
min-width: (任何值)
max-width: (任何值除了none)
overflow: (任何值除了visible)
overflow-x: (任何值除了visible)
overflow-y: (任何值除了visible)