当前位置: 首页 > news >正文

两列自适应布局方案整理

前提

本文讨论的是两列自适应布局:左列定宽/不定宽,右列自适应。

clipboard.png

clipboard.png

虽然分这两种情况,但实际上不定宽的方案同样适用于定宽的场景,因此不定宽的方案泛用度更高。

左列定宽,右列自适应

margin + float

<div class="parent">
    <div class="left"><p>left</p></div>
    <div class="right-fix">
        <div class="right">
            <p>right</p><p>right</p>
        </div>
    </div>
</div>
    .left{
        float: left;     //向左浮动
        width: 100px;    //固定宽度
        position: relative;//由于.left与.right-fix重合,且.right-fix在DOM树上的位置比.left要后,因此.right-fix会遮挡住.left,设置.left为relative可以让其冒出来。
    }
    .right-fix{
        float: right;     //向右浮动
        width: 100%;    //为了自适应设为100%
        margin-left: -100px;//由于宽度设为100%,.right-fix遭到浏览器换行处理;因此通过设置负的margin值,在左侧制造出100px的空白,使.right-fix与.left重合(即处于同一行)
    }
    .right{
        margin-left: 120px;    //由于.left和.right-fix重合了,因此给.right设置一个margin-left,避免内容区(.right)与.left重合。另外,120px - 100px = 多出来的20px实际上就相当于.left和.right之间的间隔了。
    }

这个方法其实已经是兼顾到低版本IE的完善版本了,缺点是代码冗长,而且有两个关键知识点比较难理解:

  1. 给.left加上position:relative;怎么就能让.left冒出来而不受.right-fix的遮挡了呢?
  2. .right-fix设置负的margin-left,怎么就能使.left与.right-fix重合了呢?

再者,这个方案由于.right-fix的margin-left和.left的width高度耦合,因此无法实现自适应,只能应用在左列(当然右列也成)固定宽度的场景。

absolute

<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>
.parent{
    position: relative;
}
.left{
    position: absolute;
    left: 0;
    width: 100px;
}
.right{
    position: absolute;
    left: 120px;    //比.left的left多出20px,相当于间隔
    right: 0;
}

这种方法是通过absolute配合left/right进行布局:

  1. 设置display: absolute后,通过top/right/bottom/left可以实现对元素的位置进行像素级的任意控制。因此,使用left属性即可控制各元素的起始位置,避免重叠。
  2. 自适应的关键在于leftright属性,在对元素同时设置这两个属性后,元素的宽度便会遭到拉伸,实现自适应。
  3. 需要注意的是父级元素需要设置display: relative

这种方案很容易理解,但缺点就是不能做到“不定宽”,因为.left和.right的left属性的值高度相关。

左列不定宽,右列自适应

float + BFC

<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>
.left{
    float: left;
    width: 100px;
    margin-right: 20px;    //形成20px的间隔
}
.right{
    overflow: hidden; //通过设置overflow: hidden来触发BFC特性
}

这个方法主要是应用到BFC的一个特性:

  1. 浮动元素的块状兄弟元素会无视浮动元素的位置,尽量占满一整行,这样该兄弟元素就会被浮动元素覆盖。
  2. 若浮动元素的块状兄弟元素为BFC,则不会占满一整行,而是根据浮动元素的宽度,占据该行剩下的宽度,避免与浮动元素重叠。
  3. 浮动元素与其块状BFC兄弟元素之间的margin可以生效,这将继续减少兄弟元素的宽度。

并不是一定要在.right上用overflow: hidden;,只要能触发BFC就好了,另外在IE6上也可以触发haslayout特性(推荐用*zoom: 1;)。
由于.right的宽度是自动计算的,不需要设置任何与.left宽度相关的css,因此.left的宽度可以不固定(由内容盒子决定)。

table布局

<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>
.parent{
    display: table; width: 100%;
    table-layout: fixed;
}
.left,.right{
    display: table-cell;
}
.left{
    width: 100px;
    padding-right: 20px;
}

这个方法是表格布局的典型运用。说真的,我也很迷惘要不要使用表格布局,毕竟已经是上个时代的产物了,虽然已经不再用<table>的HTML结构了,但用上相应的CSS其实思路跟以前是变化不大的。
这个方法主要是利用了表格(table)的宽度必然等于其所有单元格(table-cell)加起来的总宽度,那么只要表格的宽度一定,其中一个(或几个)单元格的宽度也一定,那么另外一个未设置宽度的单元格则会默认占满剩下的宽度,即实现自适应。

flex

<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>
.parent{
    display: flex;
}
.left{
    margin-right: 20px;
}
.right{
    flex: 1;
}
.left p{width: 200px;}

flex布局的自适应我就不多说了,本来就是设计来自适应的,只需要用上flex: 1;,就能让.right分到.parent的宽度减去.left的宽度。

推荐使用

我个人是比较推荐用float + BFC方案,浏览器兼容性很好,代码量也少,另外也很好理解;移动端上也可以考虑用上flex方案,不过还是那一句,注意用旧版的flex,兼容性会好一点。

扩展

说是说“两列自适应布局”,实际上,只要满足“只有一列是自适应”这一条件,多少列布局都行。

参考文章

  • 《The Definitive Guide to Using Negative Margins》
  • 《前端精选文摘:BFC 神奇背后的原理》

相关文章:

  • 在.net桌面程序中自定义鼠标光标
  • Beanstalkd中文协议解读
  • windows ping RPi 2B
  • BLE4.0相关
  • Steve Souders 高性能网站建设指南14条提升网站页面速度的最佳实践(1)
  • 生成日期序列
  • jQuery UI dialog插件出错信息:$(this).dialog is not a function
  • SPOJ QTREE4 lct
  • 2014 I/O归来:Google连接一切
  • kvm虚拟化技术中虚拟机vcpu与物理cpu绑定
  • YMP开发框架快速上手(一)
  • Apache CXF 框架结构和基本原理
  • PostgreSQL 9.5 使用 import foreign schema 语法一键创建外部表
  • 应用如何在后台执行
  • c语言随机数
  • 《Java编程思想》读书笔记-对象导论
  • 2017届校招提前批面试回顾
  • canvas 五子棋游戏
  • ES10 特性的完整指南
  • Flannel解读
  • JavaScript学习总结——原型
  • mockjs让前端开发独立于后端
  • PhantomJS 安装
  • Python连接Oracle
  • 第十八天-企业应用架构模式-基本模式
  • 开源SQL-on-Hadoop系统一览
  • 使用API自动生成工具优化前端工作流
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 数据科学 第 3 章 11 字符串处理
  • 学习笔记:对象,原型和继承(1)
  • 学习笔记TF060:图像语音结合,看图说话
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 关于Android全面屏虚拟导航栏的适配总结
  • 国内开源镜像站点
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • (3)选择元素——(17)练习(Exercises)
  • (C语言)二分查找 超详细
  • (NSDate) 时间 (time )比较
  • (规划)24届春招和25届暑假实习路线准备规划
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (图)IntelliTrace Tools 跟踪云端程序
  • (一)Thymeleaf用法——Thymeleaf简介
  • .NET delegate 委托 、 Event 事件,接口回调
  • .NET6实现破解Modbus poll点表配置文件
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • @modelattribute注解用postman测试怎么传参_接口测试之问题挖掘
  • @基于大模型的旅游路线推荐方案
  • [ vulhub漏洞复现篇 ] struts2远程代码执行漏洞 S2-005 (CVE-2010-1870)
  • []串口通信 零星笔记
  • [ActionScript][AS3]小小笔记
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt
  • [Asp.net mvc]国际化
  • [c#基础]值类型和引用类型的Equals,==的区别
  • [C++]——带你学习类和对象