要实现前端换肤,大部分程序猿的思路无外乎下面两种:
1.通过全局class名称,切换全局类名称实现换肤;
2.通过js更改link标签的href进行加载不同的css文件。
但是,方法1的方案比较繁琐,全局class控制样式会提高全局样式优先级,如果换肤样式很多,代码会非常啰嗦,不利于维护;方法2通过js更改href时,会重新下载href指向的css文件,多个文件会有延迟,导致样式有个过度状态,用户体验不美丽。
下面介绍方法3,可以完美解决延迟问题。
实现原理
利用link标签的rel属性进行切换css渲染。首先,我们的css文件是这样引进的:
<link href='./css/blue.css' rel='stylesheet' type='text/css' id='blueStyle'></link>
上述语句中的rel属性设置为'stylesheet',当页面加载完成后,引入的该css文件会立即渲染页面。要想切换皮肤主题,我们要的效果是下载一个css文件作为备用,但是不要立即渲染页面,当用户点击换肤时,css文件才去渲染。怎样才能达到这样的效果呢,这就是我们方案三的关键点:把rel属性设置为'alternate stylesheet';
<link href='./css/red.css' rel='alternate stylesheet' type='text/css' id='redStyle'></link>
上述red.css文件由于在rel属性中加入了'alternate' 属性,加载完成后,该css不会渲染页面。这就达到了加载css文件但不渲染页面的目的。
至此,我们页面存在两个css文件,但是只有blue.css渲染了页面。当用户点击换肤时,我们在来切换两个css,选择对应的css文件进行渲染,就达到了我们换肤的效果,并且两个css文件都是预加载的,不会产生延迟。
切换方式
通过切换rel为'alternate stylesheet'和'stylesheet'进行不同css文件的渲染,比如,要加载red.css:
//加载red.css
redStyle.setAttribute('rel','stylesheet');
redStyle.disabled = false;
//卸载blue.css渲染,
blueStyle.setAttribute('rel','alternate stylesheet');
blueStyle.disabled = true;
通过上述语句,即可以实现red.css文件的渲染和blue.css的卸载。
优缺点
1. chrome,火狐,IE9+等浏览器支持该方案
2. 用户体验更加美丽,不会出现js更改href时的延迟现象,实现无缝样式切换
3. 所有css样式都会预加载,当主题样式较多,css文件较多时初次全部加载可能会耗时