前言
由于本人学新技术时,喜欢把所有相关知识堆在一块,经常文章过长,想要定位到某一特定知识点时非常不方便,因此想着给长随笔加一个导航链接。一开始没明白博客园自定义样式的工作原理,吭哧吭哧把代码码好,发布出去一看,WTF,样式不对啊,这么丑的东西才不是我写的。
赶紧打开F12,一看,原来是博客园本身的样式覆盖了我的自定义属性,知道原因事情就好(并)办(没)了(有)。
总之,经过一番艰辛的尝试后,一个还算可以的导航列表总算是大功告成,为了纪念一下这个令人高兴的时刻,应该写点什么。话不多说,马上开始正片。
你需要预先了解的知识
由于本人设计经验非常有限,并且组件只到1.0版本,所以也没用到什么高深的技术,你只需要了解HTML和CSS就行,最好也能了解CSS3。
准备阶段
首先,你需要分析,哪些标题需要显示在列表中,将它们按照标题的级别(h1~h6)分层排列。
然后,将标题按照导航列表模板进行嵌套,以下是我的模板:
<ul class="nav-list"> <!-- 这里是一级列表项,对应于你最高一级的标题,倒不一定都是h1,这个看个人发挥 --> <li class="nav-list-li"><a href="#目标标题">一级列表项</a></li> <li class="nav-list-li"><a href="#目标标题">一级列表项</a></li> <li class="nav-list-li"><a href="#目标标题">一级列表项</a></li> <li class="nav-list-li"><a href="#目标标题">一级列表项</a></li> <li class="nav-list-li"> <a href="#目标标题">一级列表项</a> <!-- 这里是二级列表,你可以嵌套更多层,但尽量不要超过3层,否则会太丑。是的,就是丑,这是最不能忍的,不然还有什么意思。 --> <ul class="nav-list"> <li><a href="#目标标题">二级列表项</a></li> <li><a href="#目标标题">二级列表项</a></li> <li><a href="#目标标题">二级列表项</a></li> <li><a href="#目标标题">二级列表项</a></li> </ul> </li> </ul>
------------------------------------------------------------我是一条分界线---------------------------------------------------------------
接下来是重点,为列表添加一套自己的样式,以下是我的样式表:
<style> /*导航列表*/ .nav-list { position: fixed!important; top: 50%!important; right: 0!important; height: 276px!important; margin: -143px -20px -20px 0!important; padding: 0 20px 0 0!important; border: 1px solid #e5e5e5!important; overflow: auto!important; -moz-border-radius: 6px!important; -webkit-border-radius: 6px!important; -o-border-radius: 6px!important; border-radius: 6px!important; font-size: 14px!important; visibility: hidden;/*为避免网速较慢时会看到本应隐藏的导航列表,直接将其默认设置为隐藏*/ } /*显示导航列表,配合JS,实现当前位置距离页面顶部一定距离后才显示*/ .show { visibility: visible; } /*所有列表项*/ .nav-list li { list-style: none!important; } /*链接*/ .nav-list a { border-top: 1px solid #F5F5F5!important; border-bottom: 1px solid #F5F5F5!important; margin-top: -1px!important; padding: 10px!important; text-decoration: none!important; display: block!important; color: #2589BB!important; opacity: 0.5!important; } .nav-list a:link { background-color: transparent; } .nav-list a:visited { background-color: #57B8ED; color: #005580; } .nav-list a:hover { background-color: #F5F5F5; color: #005580; } .nav-list a:active { background-color: #57B8ED; color: #005580; } /*导航列表一级列表项*/ .nav-list-li>a{ border-top: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5; opacity: 0.7; } /*二级、三级以及更深层次的子列表*/ .nav-list ul { margin-left: 10px!important; overflow: hidden!important; margin-bottom: 0!important; } /*注意*/ .alert { color: red; } </style>
简单的解析:根据代码中绿色文字分隔不同的步骤(字多不看的请忽略这一段)
第一步:为最外层容器设置样式,包括容器的位置、高度、边框。我这里是固定到窗口右侧,垂直居中;自动根据列表项的多少滚动显示隐藏内容;设置边框以及圆角
第二步:统一去除列表项前面的小圆点
第三步:为链接添加文字颜色,无背景色,上下边框(左右无),去除链接的下划线,让链接充满父元素宽度,并设置透明度;然后是l-v-h-a大法,改链接文字的颜色、背景色和透明度(透明度显示的效果可能肉眼区别不大)
第四步:为二级(以及更下面的子列表)设置偏移量,请根据喜好酌情添加;以及设置当元素溢出时隐藏溢出部分:overflow:hidden,这一步是为后面设置列表项的边框做准备
关于每一行代码后面的!important,作用是强制覆盖他人设定的样式(自己设定的有可能会被写在下面的样式覆盖),这是由于CSS样式有着“权重”这一概念,就算是写在下面的代码,同样有可能因为权重不够而被覆盖,此方法可以直接提升样式优先级为最高(比用户在浏览器中直接修改还是要低的),方便不是很了解CSS语言的小伙伴使用;对于在前端方面有所涉猎或者比较熟悉的小伙伴,可以按需添加或删除!important,毕竟这个方法并不是十分完美。
这一阶段,有能力的小伙伴可以自己到浏览器里调试,改出想要的样式后再记录下来。
-------------------------------------------------------------我也是一条分界线--------------------------------------------------------------
接下来是JS部分,实现滚动条距离页面顶部一定距离后显示导航列表,而未达到时默认隐藏的效果。做这个效果是因为我现在的博客使用的是博客园默认的CSS样式,右侧的侧边栏都是贴着窗口右边缘且数量较多,不隐藏的话,会在一进去页面时遮挡部分内容,不够美观。
function DiaplayNavList($navList, top) { this.$window = $(window),//window对象的jQuery化 this.$navList = $navList,//你的导航列表的ID,jQuery化 this.top = top || 0,//滚动条距离页面顶部的距离 this.init = function() {//初始化导航列表 this.displayNavList(this.$navList, this.top); this.scroll(); }, this.displayNavList = function(){ //大于规定的距离后显示 if(this.$window.scrollTop()>=top) { this.$navList.addClass('show'); }else {//否则隐藏 this.$navList.removeClass('show'); } }, this.scroll = function() { //保存this对象的引用, //使self指向DisplayNavList的实例, //以便在内嵌方法中使用 var self = this; this.$window.scroll(function(){ self.displayNavList(self.$navList, self.top); }); } } (function() {//IIFE实例化DisplayNavList对象并初始化 var $navList = $('#my-nav-list'); var myNavList = new DiaplayNavList($navList, 1900); myNavList.init(); })();
简单的解析:首先,创建一个JS的“类”(注意区别于其他面向对象语言的“类”概念),赋予它一些必要的属性和方法;然后使用IIFE实例化该类的一个对象,并将其初始化。具体每一步的目的请看绿色注释。
关于为什么在文件里直接实例化对象,而不是将文件作为模块,然后在具体的页面中插入JS做实例化,是因为直接插入后我的代码变成了下面这样:
<script type="text/javascript">// <![CDATA[ var $navList = $('#my-nav-list'); var myNavList = new DiaplayNavList($navList, 1900); myNavList.init(); // ]]></script>
博客园默认添加了// <![CDATA[......
// ]]>的注释,将JS代码完全注释掉了,也就相当于没写这段代码,暂时不知道要怎么避免这个机制,所有将实例化与模块直接放在了一起。
使用代码
做完准备工作,接下来就是最关键的上传代码了。HTML可以直接打开相应随笔的编辑页面,点击编辑HTML源代码按钮,然后直接粘贴到最下面。
CSS由于是通用样式,可以一起粘贴到源代码里,或者统一保存在个人设置的自定义样式区。
而JS因为上面提到的问题,无法直接使用,也为了更加符合模块化的要求,将JS作为单独的文件上传到博客园的个人文件系统中。位置在个人主页“管理”标签->“文件”标签,选择好文件后上传。
当然还需要在页面中进行引用,此案例中的引用为
<script type="text/javascript" src="https://files.cnblogs.com/files/cjc917/displayNavList.js"></script>
引用你自己的文件时仅需要修改src属性为"https://files.cnblogs.com/files/你的用户名/文件名.js即可。
至此,自定义导航列表组件大功告成,撒花❀❀❀❀
注意:由于我的设计里列表是半透明的,因此当列表正好处于公告栏上方时,会有些看不清列表项的文字。此时建议给列表添加背景色,并将透明度调高(最高位1,不透明;最低为0,完全透明)。当然,也可以像上面那样JS动态隐藏和显示。另外,有些小伙伴可能权限不够,而导致样式不能正常加载,可以尝试与工作人员交流,开通相应权限。
如果有需要更多更好看样式的小伙伴,可以自行研究和开发,例如将二级列表隐藏,鼠标悬浮或点击后展开等。添加JavaScript还可以给列表增加更多神奇的功能。