写这篇随笔的动机是之前实习的时候出了自定义皮肤的需求,但是由于整个项目一开始前端基础就没打好,导致很多地方根本无法由前端程序猿控制,最后需要后端进行大量的重复劳动。在实习期间通勤的时候我一直在看Pro CSS for High Traffic Websites,结合里面的经验加上自己的思考就有了这篇随笔。
在前端开发中,标题栏、按钮、图标等元素经常需要使用图片来展现样式,并且这些东西常常会有类似自定义皮肤或者随季节性新主题更换的需求。如果使用HTML的img标签来插入它们,在遇到需要更改皮肤或主题的时候就要“伤筋动骨”,修改HTML里的大量img标签,这通常就需要后端修改相当多的代码。
实际上,这些图片应当属于“样式”,而不属于“内容”,因此不应该以img的形式出现在HTML里。这时候更好的做法是用语义化的HTML元素为它们留下空位,使用CSS的背景来添加图片。如果需求变动的时候,更换CSS,或者利用CSS的优先级覆盖掉默认样式即可。
在使用img的时候,可以用alt来保证accessibility,但是如果使用CSS添加图片,还要加上给屏幕阅读器或者爬虫留下提示性文字的话,一般的做法是在用于添加背景的HTML元素里留下文字,并且使用CSS将这些文字从页面上隐藏,如:
.hide-text { text-indent: -9999px; }
这样做还有一个好处,当用户网络出现问题,无法加载CSS,但是依然想使用网站的基础功能时,这些留下的文字可以替代背景图片作为指引。
注意:如果想要通过设置 text-indent 来隐藏文字,包含文字的元素的 display 应为 inline-block 或者 block。如果是 inline 则无法生效。此外还需要用CSS预留下图片的宽和高,因为 text-indent 之后,这个元素就几乎没有大小了。
一种简洁有效的做法是在需要使用新主题时,为<body>
加上新的类名,然后在默认CSS代码中涉及更改的部分的基础上,创建新的覆盖样式。举例来说,假如需要创建圣诞主题,先为body加上类名(如果后端使用了可嵌套的HTML模版,通常来说这里只要修改一处):
<body class="xmas"></body>
如果为一个模块的小标题使用了img标签显示,那么原来可能是这样的
<div class="popular-title"> <img alt="Popular" src="/some/path/popular.png"> </div>
重新组织一下,应该是
<h3 class="popular-title hide-text">Popular</h3>
然后利用CSS加上背景并隐藏文字
.popular-title { background: url(/some/path/popular.png) no-repeat left top; height: 100px; width: 330px; } .hide-text { text-indent: -9999px; }
那么,到了圣诞节的时候,需要更换主题,只需要在主题用的CSS里加上:
.xmas .popular-title { background: url(/some/path/popular-xmas.png) no-repeat left top; }
用原来的选择器加上之前为新主题添加的body
的类名,就可以获得更高的优先级,覆盖默认的样式。
后端在修改的时候,也只需要加入一个新的link。原来可能在head
里引入的CSS是
<link rel="stylesheet" type="text/css" href="/some/path/index.css">
那么只需要加多一句,变成
<link rel="stylesheet" type="text/css" href="/some/path/index.css"> <link rel="stylesheet" type="text/css" href="/some/path/index-xmas.css">
即可。同样地,如果后端使用了可嵌套的HTML模版,通常也只需要修改一处。这样一来,就能减少不少重复劳动和重复代码。