zoukankan      html  css  js  c++  java
  • 【css】回想下经典的布局

    各种方式实现的布局

      看到这张图相信大多数人都很熟悉,这曾经是一种经典的布局方式,一道经典的面试题,一般形如"实现一个布局,左右固定宽度,中间自适应"。随着岁月的流转,时光的交替(颇有一种“天下风云出我辈,一入江湖岁月催”的感慨,哈哈),它一步步逐渐退出了历史舞台,不过在经典,总是有它经典的含义在里面,今天笔者就尝试站在自己认知范围内,重新诠释了下经典,实现的手段则是用了各种可能的方式实现这一经典布局:

    1、基于FL FR的实现

    .layout1 {
    	height: 100px;
    	overflow: hidden
    }
    
    .layout1 .l {
    	height: 100%;
    	 100px;
    	float: left;
    }
    
    .layout1 .m {
    	height: 100%;
    	margin: 0 200px 0 100px;
    }
    
    .layout1 .r {
    	height: 100%;
    	 200px;
    	float: right;
    }
    
    <div class='layout1'>
    	<div class='l'></div>
    	<div class='r'></div>
    	<div class='m'>layout1</div>
    </div>
    

      图中的第一个行就是基于此方式实现的,原理很简单,利用浮动元素脱离文档流的特性,左边的左浮动,右边的有浮动,简单粗暴。

    2、圣杯布局

    .layout2 {
    	height: 100px;
    	overflow: hidden;
    	padding: 0 200px 0 100px;
    }
    
    .layout2 .m {
    	float: left;
    	 100%;
    	height: 100%;
    }
    
    .layout2 .l {
    	float: left;
    	 100px;
    	margin-left: -100%;
    	position: relative;
    	left: -100px;
    }
    
    .layout2 .r {
    	 200px;
    	margin-left: -200px;
    	float: left;
    	position: relative;
    	right: -200px;
    }
    
    <div class='layout2'>
    	<div class='m'>layout2</div>
    	<div class='l'></div>
    	<div class='r'></div>
    </div>
    

      为了保证dom元素的尽快展示,而将最重要的元素放在最前解析,优化用户体验,使用负margin和相对定位调整左右元素位置,使用大容器的padding作为调整空间的hack,十分经典的手法;

    3、双飞翼布局

    .layout3 {
    	height: 100px;
    	overflow: hidden;
    }
    
    .layout3 .m-wrap {
    	 100%;
    	float: left;
    	height: 100%;
    }
    
    .layout3 .m {
    	margin: 0 200px 0 100px;
    }
    
    .layout3 .l {
    	float: left;
    	 100px;
    	margin-left: -100%;
    }
    
    .layout3 .r {
    	float: left;
    	 200px;
    	margin-left: -200px;
    }
    
    <div class='layout3'>
    	<div class='m-wrap'>
    		<div class='m'>layout3</div>
    	</div>
    	<div class='l'></div>
    	<div class='r'></div>
    </div>
    

      与之前的方式基本一致,唯一的不同是添加了一个标签,而没有依赖根容器做hack。

      1、2、3三种实现都是基于BFC(Block Formatting Contexts)规则的,直译作“块级格式化上下文”,它会在页面上隔离出一个渲染区域,容器里的子元素并不会在布局上影响到外面的元素。如何产生BFC呢?它需要满足以下规则:

    1. float 除了none以外的值
    2. overflow 除了visible 以外的值(hidden,auto,scroll )
    3. display (table-cell,table-caption,inline-block, flex, inline-flex)
    4. position值为(absolute,fixed)
    5. fieldset元素

      虽然概念可能有些陌生,其实我们在解决边界重叠(父子兄弟元素的margin重合)问题会经常通过触发BFC的方式来解决,另外,清除浮动也是这个原理,不过这些并不是本文的重点,那么让我们继续,看看其他的实现方式。

    4、flex实现

    .layout4 {
    	display: flex;
    	height: 100px;
    }
    
    .layout4 .l {
    	flex: 0 0 auto;
    	 100px;
    }
    
    .layout4 .m {
    	flex: 1 1 auto;
    }
    
    .layout4 .r {
    	flex: 0 0 auto;
    	 200px;
    }
    
    <div class='layout4'>
    	<div class='l'></div>
    	<div class='m'>layout4</div>
    	<div class='r'></div>
    </div>
    

      实现十分简单,利用伸缩盒模型的特性,只需要开启中间元素的flex-grow(为了保证缩小时的正常显示笔者还开启了flex-shrink)就能个很轻易的实现这种布局,不过为了美观,笔者并没有贴上兼容性的代码。当然,想实现之前那种优先渲染的方式flex也是支持的:

    .layout4 {
        display: flex;
        height: 100px;
    }
    
    .layout4 .l {
        flex: 0 0 auto;
         100px;
    }
    
    .layout4 .m {
        order: 1;
        flex: 1 1 auto;
    }
    
    .layout4 .r {
        order: 2;
        flex: 0 0 auto;
         200px;
    }
    
        <div class='layout4'>
            <div class='m'>layout4</div>
            <div class='l'></div>        
            <div class='r'></div>
        </div>
    

      原理也很简单,使用order属性就可以轻松实现了。

      flex实现与之前不同,基于的是FFC(Flex Formatting Contexts)规则,即“自适应格式化上下文”。与BFC略显复杂的触发规则不同,只要有元素满足display为flex或inline-flex,则会应用这套规则。

      想来所有方式似乎都已穷举?其实不然,还有去年刚出台的新规则css-grid可以一试,于是

    5、css grid

    .layout5 {
    	height: 100px;
    	display: grid;
    	grid-template-columns: 100px 1fr 200px;
    }
    
    <div class='layout5'>
    	<div class='l'></div>
    	<div class='m'>layout5</div>
    	<div class='r'></div>
    </div>
    

      可以看到,基于css grid的实现是最为便捷的,基于不需要操作grid item,只需要设置容器就可以轻易实现,不过由于是新事物,所以兼容性比较差。

      对应grid也有其对应的规范叫作“GFC”(Grid layout Formatting Contexts),即“网格布局格式化上下文”,与flex类似,只需要设置disply为grid即可开启,但是请注意,它与我们通常理解的table(相信大家心里都有很多想关于table的吐槽)布局并不一致,正如上面例子中的,这种css grid布局提供了很多方便的属性给我们用于绘制网格。

      除了以上BFC、FFC、GFC,常见的还有一个IFC(Inline Formatting Contexts),即“内联格式化上下文”,display为inline、inline-block、inline-table的元素,在IFC中,行内元素是一个接一个排列的,起点是容器的顶部,虽然横向的margin、padding、border得以保留,但是垂直方向上则会以不同的方式对齐,通常额可以设置vertical-align来控制其对齐方式。值得注意一点的是虽然行内元素内部可以形成一个BFC,而对外它则会形成IFC。

      话说回来,这确实是一种经典的布局,几乎所有新的布局方式都是很友好的在支持它,从蛮荒时代的要使用各种hack手段来实现,到现代的轻而易举的实现,也足见其在css发展中的重要地位,现在想来也确实,css3之前的css更多的像是一种工具式的语言,它没有任何优雅的特性,了无生趣,而到了css3时代,无论从性能上的优化,工程上的提高,都是可圈可点的。

      当然,类似经典的实现在css中还有很多,例如各种垂直居中的方法,与js更新换代的方式不同,旧的技术不断被新技术替换,而在css领域,这种返古现象却经常发生,当然也和浏览器厂商、各个平台,复杂的兼容性场景有关,但是其中蕴含的思想就像jQuery那种设计理念,却不会随着岁月的流逝而过时,反而在特定的时间上,更是弥足珍贵的。  

  • 相关阅读:
    jquery2
    数据库回顾
    jquery
    BOM DOM 注意事項
    JavaScript 注意
    javascrip
    CSS
    html
    网络编程
    淘宝下单高并发解决方案
  • 原文地址:https://www.cnblogs.com/mfoonirlee/p/6986953.html
Copyright © 2011-2022 走看看