一个项目的前端布局给我的思考

6,004 阅读6分钟

内容包括: HTML(讲述你不知道的absolute和float关系)和javascript(自己写的一段原生js实现双击切换效果)

最近在一个项目中发现一个自己一直忽视的问题 position 和 float 的混用问题,position定位给我们前端开发中页面的布局带来了很多的好处,但如果页面使用过多的position定位,你将会发现,页面的布局超出了你的控制,就算是最终经过各种修改尝试,页面达到了你的设计效果,但是回过头来你再审视你的代码你会不禁感慨‘我擦,这是一坨什么!’。

所以,需要加深基础的学习,从而简化布局工作量,用最少的代码来实现我们所需要的布局效果,通过这次的实践我发现了自己前端开发中存在知识缺陷问题,所以写了一篇文章和大家相互学习。

要实现的页面布局效果是下面这个样子的,它由三部分组成菜单按钮,导航栏,侧边栏,看到这个样子同学会不以为然,‘不就是这么常见的布局吗?貌似也不会有什么技术含量呀!你不会是在逗我吧’

点击查看效果示例

最终效果图

这时我想说,‘no!no no no!各位看官莫急,且听在下慢慢道来’,我们如果在每个模块加上不同颜色的边框你就会发现不同之处,下面图片中的一些模块的名称定义,需要记一下哟,这会更方便你阅读全文:
点击查看效果示例
各个模块加边框后的显示效果

1.使用图文混合的布局解决导航栏的布局

<a class="l-link" href="javascript:;">
    <div class="l-float">
        ![](./svg/menu.svg)
    </div>
</a>

<ul class="l-list">
    <li class="l-list-item">首页</li>
    <li class="l-list-item">分类一</li>
    <li class="l-list-item">分类二</li>
    <li class="l-list-item">分类三</li>
</ul>

我们常见的形式为:

 ![](default.jpg)
 <p>这是一个图文混合布局</p>

是有一个行内元素和一个块状元素组成,或者是有inline, inline-block, block转换的行内元素或者块状元素。

2.使用position定位中的 absolute或者fixed的特性,由于fixed是absolute的扩展,只是定义改变了定位出现的形式,所以fixed继承了absolute的破坏性和包裹性两个特性。对于这两个特性不了解的同学可以百度相关方面的文章。

百度搜索好文章

在上述代码结构上加上l-container容器,使用position:fixed,使用fixed的包裹性
效果图如下:

包裹特性使用后效果图

使用过图文混合效果的同学应该知道,右边导航栏的高度随着左边的高度变化而变化,所以解决l-list 的高度不是内容的高度的方法即是在l-list中加入overflow:hidden;即可做到如下图的效果:

position-float-5.png

  代码结构如下:

 <div class="l-container">
      <a class="l-link" href="javascript:;">
         ……
      </a>

      <ul class="l-list">
        ……
      </ul>
</div>

3.侧边栏和菜单按钮的布局(讲述你不知道的absolute和float关系)

它们是兄弟关系,都能使元素脱离文档流(慕课网知识充电),但是还有一层关系你要知道?集中注意力往下看你哟!
如何使导航栏中的菜单按钮达到更好的用户触发使用效果?
所以设计成了如最终效果图显示的布局,
a,增大按钮的可触发范围使之与侧边栏的宽度等距;
b,使菜单按钮一部分遮挡侧边栏的一部分区域,从而实现更好的切换效果

实现a设计简单增加宽高样式,如果不能设置将元素转化为行内块状元素。
侧边栏的实现不用说就是position:fixed;或者position:absolute;
实现b就要稍微动一下心思。
通常,当我们写完代码后测试发现,效果并不是我们想的样子,我们发现实际显示效果是侧边栏的一部分遮挡住了菜单按钮,‘我擦,这个难不住机智的我们’,使用z-index:99999999;但是我们刷新页面后发现不是这个样子的,这是为什么呢?

我们都知道float ,和 absolute 都能使被修饰的模块脱离文档流,但是脱离文档流后两者的层级关系如何,这个问题有的人想过,可能大部分人都没有想过,这个我也看过很多文章发现基本没有人说的明白。但是这并不妨碍我发表一下个人的观点:
虽然float和absolute都能使元素脱离文档流,但是absolute脱离文档流后就不影响原来所处容器内的元素布局,但是float却不是,举一个最常见的例子就是清除浮动,所以,虽然说float,absolute都是脱硫文档流,但严格地讲float应该称之为半脱离文档流。因此在层级关系上来说absolute的层级更高。 从我们写的这个例子来讲l-container positon:fixed;
l-menu float:left;样式后,l-container包裹(理解包裹特性)l-menu也可以知道absolute的层级高于float的层级。
github下载代码如果喜欢记得添加个星星^-^
虽然有些同学不知道这是为什么,但是不妨碍我们解决问题,那就是将l-container和 l-postion这两个同根模块都设置position:absolute或者position:fixed;样式,对就是这个样子的,我们开发的过程中与到类似的问题,我们也是采用了‘同一性’的原则,就像我们在解决不同浏览器兼容性问题时采用的normal.css一样,将属性同一。

这部分的代码结构是:

 <div class="l-container">
      <a class="l-link" href="javascript:;">
         ……  // 菜单按钮
      </a>

      <ul class="l-list">
        ……  // 导航
      </ul>
</div>

<div class="l-position">
 …… // 侧边栏
</div>

附上:js侧边栏实现的js原生代码:

var flag = true; // 显隐标识符
var obj = document.getElementsByClassName('l-link')[0]; 
var lPos = document.getElementsByClassName('l-position')[0];

obj.onclick = function(){
    if(flag){
        // 添加选择器l-active
        objClass = lPos.getAttribute('class') || '';
        lPos.setAttribute('class', objClass + ' l-active');
        return flag = false;
    } else {
        // 去除选择器l-active
        objClass = lPos.getAttribute('class');
        objArr = objClass.split(/\s+/);
        if(objArr && objClass !== null){
            for(var i=0, len=objArr.length; i<len; i++ ) {
                if(objArr[i] === 'l-active'){
                    objArr.splice(i, 1);
                }
            }
            var objClass2 = objArr.join(' ').replace(/^\s|\s$/g, '');
            lPos.setAttribute('class', objClass2) ;
            return flag = true;
        }
    }
}

github下载地址:

本文相关文件为position-float.html和position-float.html

其他文件有时间不妨也点一下,相信或多或少会对你有一定的帮助!感谢支持!