那些CSS的细节问题(1)

几个月前写了一篇 那些JavaScript的细节问题(1),专记些细微的,古怪的,甚少有用的东西,不过,可以当作茶余饭后的消遣。这次凑了3个CSS的问题,也好给JavaScript那个系列凑个成对。

好了废话不多说了,来看看下面这些或易或难的无聊问题吧~

1. 指针样式的变化

隐藏或显示带有指针样式的对象后,指针样式会马上改变吗?

文字上很难一言概之。想象一下有两个正方形的div,背景一红一蓝,它们都绝对定位并重叠,红色(鼠标样式为默认)在下,蓝色(鼠标样式为手形)在上。初始状态下,鼠标蓝色层上,数秒后,蓝色层被隐藏,鼠标落在红色上,问题就来了,鼠标样式是否立即更换?可能这么表述还是不怎么直观,不过看下面这张图就能一下子明白这个细节的有趣之处:

现在,思考一下,鼠标会不会变呢?我的第一直觉是会,因为鼠标更换了指向的对象,所以理所当然样式要跟着作出改变不是么?然而,答案却并非如此。在测试了所有浏览器之后,结论是:Firefox是唯一立即更新鼠标显示的浏览器。而其他浏览器对图层隐藏从而改变指针指向似乎并不在意,它们只在鼠标在那移动之后才做出指针样式上的更新...对此,我直接写了一个DEMO,你可以自己观察指针变化和查看源码。这里为了减少鼠标点击造成的干扰,所以设置了Timeout定时2秒来隐藏位于上方的蓝色层。

这个问题是有意义的,虽然鼠标移动后所有浏览器更新指针样式,但是仍有片刻可能造成用户的违和感,像是上一个场景卡住一样,在某些特定场景会特别明显。因此应该尽可能避免。

2. 哪些CSS不占空间?

这么表述虽然不准确,但却最直观的。如果你阅读面广泛,可能已经看到最近的这篇文章:CSS Things That Don’t Occupy Space 的长篇总结:

  1. 绝对定位的元素:即 position:absolute; 以及 position:fixed;
  2. 有偏移的相对定位的元素,指的是偏移后的元素不影响布局
  3. outlines
  4. Transforms变换属性偏移的元素
  5. 各种阴影属性
  6. 其他杂项:WebKit反射属性/IE私有滤镜/text-decoration/display: none

其实是一个非常有趣的列表,作者甚至把 text-decorationdisplay: none 都包含在内...但其实,就如其所说,“不占空间”的说法是不准确甚至是不正确的。这些元素最多只是不影响流,而且其中很多项是牵强的。精简一下最主要的应该只剩下 绝对定位/outline/阴影 三者。值得一提的是,虽然定义很早就表明,“阴影不会触发滚动条,也不会增加可滚动区的大小”,但是早期的Firefox在实现的时候是错误的。

不得不承认,这一题其实是拿来凑数的:) 当然多少也为下面本期“最蛋疼”问题做一个小小的铺垫~

3. 实现彩虹的色彩

实现彩虹的颜色,需要多少个Div

这算是个老掉牙的问题吧~如果放在几年之前,很多人一定会这么回答:1个DIV,加上这个DIV的伪元素before和after,三者的边框和背景,足以表示9种颜色。只不过,时至今日,问题已然需要其他答案。

渐变是个好主意,而且,通过一些在线工具我们甚至都不需要我们写代码。但这里我要说的是更令人蛋疼的法子。也许你已经想到了,就是问题2里提到的“阴影”。

box-shadow 被用做边框或者渐变也不是什么新鲜事了,一年前我写的 CSS3 box-shadow 详解(2) 里曾经详细讨论过这些问题。由于多重阴影的出现,颜色何止是9种,那是要多少就有多少啊!于是,真正的第三个蛋疼的问题是:到底能有多少种颜色,到底,多重阴影的数量限制在哪里?

为了更快的制造多重阴影,我用下面这段JS代码来生成对应的 box-shadow 代码:

var r = g = b = 0;
for(var i = 0; i < 70000; i++){
	console.log('0 ' + i + 'px 0 rgb('+r+','+g+','+b+'),');
	if(r < 255){
		r++;
	}else{
		r = 0;
		if(g < 255){
			g++;
		}else{
			g = 0;
			if(b < 255){
				b++
			}else{
				break;
			}
		}
	}
}

在数量还是1万次循环的情况下,我的工作用机还能跑跑。不过到了10万数量级,我就只好跑回家用新买的机器跑了。最后遗憾的是,即便我跑了7万重阴影,浏览器似乎也毫无问题(除了Opera挂掉了以外)——虽然加载一个光CSS就有2M的页面有点慢,不过渲染的时候还是很给力!我了个擦,面对这样的结果我只好放弃,再往下走好像就极端了... :)

如果你对你的机子有信心,可以打开这个 DEMO 页面,看看7万重阴影"一丝一丝"的拼成的渐变,可能会有点卡顿,但至少在i5级别的CPU下还是很流畅的。结论就是,和标准一样,多重阴影没有什么数量上的限制...值得一提的是,渲染速度上 Firefox > Chrome > Safari,而 Opera 无法通过测试直接崩溃了。由于我的工作机是 XP,所以没有 IE9/10 的测试信息。

回过头再来看彩虹问题,赤橙黄绿青蓝紫,阴影的数量足够胜任画出一个色谱。和刚才一样,我写一个脚本跑出 box-shadow 的代码:

var r = 255;
var g = b = 0;
for(var i = 0; i < 256*5 - 4; i++){
	console.log('0 ' + (i+1) + 'px 0 rgb('+r+','+g+','+b+'),');
	if(g < 255 && r == 255 && b == 0){
		g++;
	}else if(g > 0 && r == 0 && b == 255){
		g--;
	}else if(r < 255 && g == 0 && b == 255){
		r++;
	}else if(r > 0 && g == 255 && b == 0){
		r--;
	}else if(b < 255 && r == 0 && g == 255){
		b++;
	}else if(b > 0 && r == 255 && g == 0){
		b--;
	}
}

我写了一个DEMO,你可以点击查看源码。看起来还不错,我限制了div的宽度以免满屏都是颜色。比起刚才的7万重阴影,现在1276层,刚才崩溃的Opera都能轻松显示。至此,这个问题就算完了。

之所以选择7万,无非是出于对65535这种数字的怀念。但无论是初定的1000,还是后来的7万,相信不会有人这么乱来。所以我也就没有继续蛋疼地挖下去。我想自己还不是那种蛋疼到非要测试出个极限不可的地步。小蛋疼怡情大蛋疼伤身啊...

这算是单身期间的最后一篇博客了吧,来月之后,也算是拖家带口之人了。总的来说,因为一直筹备婚礼和装修之类劳心老累之事,所以常常无法静下心来研习技术,以至于这一年博客产量很低,特别是技术方面的内容。希望来年生活稳定后,能够安安心心做技术方面(嘛,还有艺术方面)的事——想来也好久没做那木工之事,许久不曾绘画,常年未再篆刻,倒是偶有烹饪的练习,生活才不至于过于单调。

在这人生一大事即将定音之际,我对于这篇博文本身的吐槽是:不要太在意这些细节。只有在大局相似的情况下,细节才能决定成败,细节远没有大局重要。Just for fun,一如代码,一如人生。