byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8512
一, 大多数开发人员的实现
大多数前端开发人员实现网站皮肤更换功能大致下面两种方法:
一个全局 class 控制样式切换;
改变皮肤 link 元素的 href 地址. 例如:
<link id="skinLink" href="skin-default.CSS" rel="stylesheet" type="text/css">
换皮肤的时候 JS 改变 href 属性值:
skinLink.href = 'skin-red.css';
例如我 10 年前模拟腾讯网首页的换肤功能做的 demo 页面就是这么实现的.
都不完美. 全局 class 控制样式提高了样式优先级, 如果换肤样式很多, 代码会非常啰嗦, 不利于维护; 使用 JS 改变 href 属性会带来加载延迟, 样式切换不流畅, 体验不佳.
实际上, 浏览器有原生特性, 非常适合实现网站换肤功能.
二, 原生 html 特性下的网站换肤
此方法借助 HTML rel 属性的 alternate 属性值实现. 示意 HTML 如下:
- <link href="reset.css" rel="stylesheet" type="text/css">
- <link href="default.css" rel="stylesheet" type="text/css" title="默认">
- <link href="red.css" rel="alternate stylesheet" type="text/css" title="红色">
- <link href="green.css" rel="alternate stylesheet" type="text/css" title="绿色">
上面 4 个 <link> 元素, 共出现了 3 中不同性质的 CSS 样式文件加载:
- <link>
- <link>
- <link>
这里有个非常有趣的特性, 那就是 rel="stylesheet" 的 <link> 如果有 title 属性并有值, 性质上就变成了一个可以控制其渲染或者不渲染的特殊元素了.
如何控制呢?
一种说是浏览器自己会有样式切换菜单, 查看→页面, 选择 title 属性值对应的样式. 我猜这是 10 年前的说法了吧, 现在浏览器根本没有这些菜单选项, 至少我找了好久, 各个浏览器都找了个遍没找到.
另外一种就是使用 JS 进行控制了, 使用 JavaScript 代码修改 <link> 元素 DOM 对象的 disabled 值为 false , 可以让默认不渲染的 CSS 开始渲染. 注意, 必须是 DOM 元素对象的 disabled 属性, 而不是 HTML 元素的 disabled 属性, <link> 元素是没有 disabled 属性的.
例如:
- // 渲染 red.CSS 这个皮肤
- document.querySelector('link[href="red.css"]').disabled = false;
因此, 要实现换肤功能, 只要在页面上方几个换肤按钮, 点击的时候改变对应 <link> 元素 DOM 对象的 disabled 值就可以了.
眼见为实, 我专门做了 demo 页面, 您可以狠狠地点击这里: link rel alternate 实现网站换肤功能 demo
结果如下 GIF 截图所示(截自 IE 浏览器):
demo 页面是使用单选框模拟实现的, HTML 和 JS 代码如下:
- <input id="default" type="radio" name="skin" value="default.css" checked>
- <input id="red" type="radio" name="skin" value="red.css">
- <input id="green" type="radio" name="skin" value="green.css">
- var eleLinks = document.querySelectorAll('link[title]');
- var eleRadios = document.querySelectorAll('[type="radio"]');
- [].slice.call(eleRadios).forEach(function (radio) {
- radio.addEventListener('click', function () {
- var value = this.value;
- [].slice.call(eleLinks).forEach(function (link) {
- link.disabled = true;
- if (link.getAttribute('href') == value) {
- // 该样式 CSS 文件生效
- link.disabled = false;
- }
- });
- });
- });
三, link rel=alternate 方法实现优点
3 大优点:
兼容性非常好. IE9+(IE8 我没测, 理论也支持),Chrome 和 Firefox 均支持这种更原生的换肤效果实现.
语义非常好. 用户, 开发者, 尤其搜索引擎或者其他辅助阅读设备能够准确识别网站还有其他替换 CSS 样式.(alternate 的语义就是可替换的)
交互体验更好. rel=alternate 方法实现的换肤功能在网站样式变换的时候是瞬间切换, 完全无感知. 因为浏览器已经把换肤的 CSS 文件预加载好了, 比 JS 改变 href 地址的体验要更好. 配合 http2.0, 几乎可以说是完美无瑕的解决方案了.
为什么之前没有人提过这个方法?
此方法我也是最近在学习 rel 属性值的时候知道的, 看到 MDN 上关于 文档学到的, 之前并不知晓还有这么给力的实现.
Firefox4 就开始支持这一特性, 说明此方法很久远了, 我搜索了下, 还是有少数前辈知道并使用这种方法换肤的, 但是, 至少对于新人前端 (如果按照我在例会上的统计) 几乎无人知晓.
什么原因造成这种现象呢?
首先, 换肤是小众需求;
其次, 有符合常规认知的替换方案, 最终效果也能接受;
然后, 都在学习高大上的东西, 什么 HTML 基础知识根本无人问津;
最后, 缺少有影响力的的入口进行科普.
酒香也怕巷子深, 好的技术实现也要多多曝光才能让更多人知道, 提高整个行业的水平. 所以如果你觉得此方法确实不错, 可以转发分享让更多人知道.
最后, 感谢你的关注和阅读!
来源: http://www.tuicool.com/articles/3M7biun