📖
blog
  • README
  • JavaScript
    • 元素的宽高位置信息梳理
    • dom-align 源码浅析
    • Event Loop
    • 函数实参为对象时的陷阱
    • export 与 utils 方法书写规范
    • 手写 Promise 及相关代码理解
    • call,apply,bind 等函数的模拟实现
    • JavaScript继承
    • JavaScript 数据类型与类型判断
    • for..of 和 for..in 的区别
    • 写给自己看的 next 函数
    • JS 可选链与双问号
    • mouseenter 与 mouseover 事件的区别
    • Immutable相关知识
  • CSS
    • 不简单的 z-index
    • 两列布局,三列布局
    • CSS 居中方案整理
    • CSS 像素,设备像素,2倍图梳理
    • iconfont 的使用
  • Node JS
    • 实现简易的 express
  • React 核心知识点整理
    • 高阶组件
    • React 事件处理
    • React Hooks
    • React Context
  • React 状态管理
    • Redux 基础概念
    • Redux 中间件和异步操作
    • Redux Saga
    • Redux 只能有一个 store 对象嘛
  • React 开发实践
    • Ant Design Menu 组件的使用与深入
    • 讲讲吸顶效果与 react sticky
    • 基于 express,搭建 react 的开发环境
    • 通过 antd input 组件分析受控与非受控组件
    • DebounceClick 组件
    • react component Align 组件分析
    • React Portal 之事件冒泡
    • React Transition Group 源码浅析
    • React.cloneElement 父组件向子组件注入 props
    • 一次 Align 组件的问题记录
    • 如何知道子组件的类型
    • React Router 源码简单分析
    • React Redux 源码简单分析
  • Vue.js
    • Vue.js 概览
    • scoped 样式中的 deep
  • TypeScript 语法
    • 基础类型
    • 变量声明
    • 接口
    • 类
    • 函数
    • 泛型
    • 枚举
    • 类型推论
    • 类型兼容性
    • 高级类型
    • Symbol
    • 迭代器和生成器
    • 模块
    • 命名空间
    • JSX
  • 玩转 webpack
    • 第一章: webpack 与构建发展简史
    • 第二章:webpack基础用法
    • 第三章:webpack进阶用法
    • 第四章:编写可维护的 webpack 构建配置
    • 第五章:webpack构建速度和体积优化策略
    • 第六章:通过源代码掌握webpack打包原理
    • 第七章:编写Loader和插件
  • webpack 实践
    • 如何配置 output.library
  • 测试
    • 初识代码测试
    • Jest 中 如何测试 setTimeout
    • Jest Enzyme React 测试实践记录
  • WEB 开发,过往工作沉淀
    • Web安全(DVWA)
    • 内存泄露与事件移除的必要性
    • url to pdf api 与 服务部署踩坑记录
    • 前端调试指南
    • Markdown 转 email
    • github travis ci 自动部署
    • 浏览器缓存知识梳理
    • WEB 系统登录相关知识梳理
    • 将-Axios-请求参数和返回值进行格式化
    • source-map与源码调试
    • HTTPS
    • 使用 rollup 打造自己的 npm 包 (全流程)
    • father-build 是如何工作的
  • 书籍
    • 图解 HTTP 协议
    • 编写可维护的 JavaScript
    • 鸟哥的 Linux 私房菜
    • JavaScript Promise迷你书
  • Linux
    • vimtutor
    • CURL 使用指南
  • Nginx
    • 一次 nginx 分享
  • Git
    • Git Commit Message 须知
    • .gitignore 模板
    • git tag标签
  • 摄影
    • 摄影基础知识
    • 手机摄影从小白到大师
  • 翻译
    • log4js
    • log4js-node
    • 介绍GitLab上的CI/CD
    • 为GitLab Pages创建并调整GitLab CI/CD
    • 关于 rel=noopener
    • AngularJS 团队 Git 提交信息约定
    • JSON Schema
  • Lifehack
    • 20 个 Google 搜索 Tips 来高效使用 Google
    • 37 个高级 Google 搜索 Tips
Powered by GitBook
On this page
  • 前言
  • 1. 两列布局
  • 1.1 float + BFC (左边固定,右边自适应)
  • 1.2 float + margin-left (左边固定,右边自适应)
  • 1.3 absolute + margin-left (左边固定,右边自适应)
  • 1.4 absolute + absolute (左或右自适应宽度均可)
  • 1.5 float + 负外边距 (左或右自适应宽度均可)
  • 1.6 flex 布局 (左或右自适应宽度均可)
  • 1.7 table (左边固定宽度,右边自适应)
  • 1.8 table-cell 伪表格布局 (左边固定宽度,右边自适应)
  • 2. 三列布局
  • 2.1 圣杯布局
  • 2.2 双飞翼布局(淘宝对于圣杯布局的改进)
  • 2.3 绝对定位
  • 2.4 浮动定位
  • 2.5 flex 布局
  • 参考资料

Was this helpful?

  1. CSS

两列布局,三列布局

前言

一直以来对于布局自适应问题,都没有好好总结,趁着最近面试,忙碌之余也有空闲,便打算开始整理整理相关知识

1. 两列布局

1.1 float + BFC (左边固定,右边自适应)

<div>
  <div style="float: left; width: 200px; background: red;">
    left
  </div>
  <div style="background:green; overflow:hidden;">
    i am right; i am right; i am right;
    <br />
    i am right; i am right; i am right;
    <br />
    i am right; i am right; i am right;
    <br />
  </div>
</div>

单独设置 左 元素 float: left 时,该元素脱离文档流。此时 右 元素会占据 左 元素的位置,并被 左 元素遮挡。但文字会环绕 左 元素。

此时,可通过让 右 元素形成 BFC,打破环绕。

1.2 float + margin-left (左边固定,右边自适应)

<div>
  <div style="float: left; width: 200px; background: red;">
    left
  </div>
  <div style="background:green; margin-left: 200px;">
    i am right; i am right; i am right;
    <br />
    i am right; i am right; i am right;
    <br />
    i am right; i am right; i am right;
    <br />
  </div>
</div>

原理同上,通过 margin-left 使得 右 元素打破环绕。

1.3 absolute + margin-left (左边固定,右边自适应)

<div>
  <div style="position: absolute; width: 200px; background: red;">
    left
  </div>
  <div style="background:green; margin-left: 200px;">
    i am right; i am right; i am right;
    <br />
    i am right; i am right; i am right;
    <br />
    i am right; i am right; i am right;
    <br />
  </div>
</div>

同 float + margin-left 的方案,既然 float 可以使得左边元素脱离文档流,那么 absolute 也可以脱离文档流。

这个时候可以使用 margin-left 与左边元素隔开距离,但是使用 overflow: hidden; 不可以。

1.4 absolute + absolute (左或右自适应宽度均可)

<div style="position: relative;">
  <div style="position: absolute; left: 0; width: 200px;background: red;">
    left
  </div>
  <div style="position: absolute; left: 200px; right: 0;background: blue;">
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
  </div>
</div>

通过给两个子元素设置为 absolute, 绝对定位来自适应宽度。

1.5 float + 负外边距 (左或右自适应宽度均可)

1.5.1 左边自适应,右边定宽

.clearfix {
    content: "";
    display: block;
    clear: both;
}

<div class="clearfix">
  <div style="float: left; width: 100%;">
    <div style="margin-right: 200px;background: red;">
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
    </div>
  </div>
  <div style="float: left;background: blue; width: 200px; margin-left: -200px;">
    I’m the Sidebar!
  </div>
</div>

左右 元素均设置为左浮动,同时 左 元素宽度为 100%, 这时候 右 元素会被 挤 到下一行,而通过 margin-left 为 负的自身宽度(-200px), 又使得 左右 元素又在同一行。

但是这个时候, 左 元素会遮挡 右 元素,因此我们将真正内容作为 左 元素的子元素,设置子元素的 margin-right 确保与 右 元素隔开。

1.5.2 左边定宽,右边自适应

<div class="clearfix">
  <div style="float: left;background: blue; width: 200px; margin-right: -100%;">
    I’m the Sidebar!
  </div>
  <div style="float: left; width: 100%;">
    <div style="margin-left: 200px;background: red;">
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
      Main content in here;
    </div>
  </div>
</div>

左右两个元素设置为 float: left, 右 元素设置宽度为 100%, 这时候左右元素分为两行。

设置左 元素 margin-right 为 -100%, 将右 元素又拉回到和 左 元素同一行。

这时候,右 元素会把 左 元素遮挡,那么通过设置 margin-left 和 左 元素拉开距离。

1.6 flex 布局 (左或右自适应宽度均可)

<div style="display: flex;">
  <div style="width: 100%;background: red;">
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
  </div>
  <div style="background: blue; flex: 0 0 200px;">
    I’m the Sidebar!
  </div>
</div>

缺点: 1. 需要注意IE兼容性

通过设置 flex: 0 0 200px, 即 不伸长,不收缩,宽度为 200px

1.7 table (左边固定宽度,右边自适应)

<table>
  <tbody>
    <tr>
      <td width="200px" style="background: red;">i am the sidebar</td>
      <td style="background: blue;">
        Main content in here;
        Main content in here;
        Main content in here;
        Main content in here;
        Main content in here;
        Main content in here;
        Main content in here;
        Main content in here;
        Main content in here;
        Main content in here;
      </td>
    </tr>
  </tbody>
</table>

利用 table 布局,在宽度固定的 td 标签上设置 width,另外一个元素自然会占据剩余宽度。

优点: 1. 无需多余的 css 来实现自适应 2. 垂直方向会自动居中

缺点: 1. 很多多余的 HTML 结构嵌套

1.8 table-cell 伪表格布局 (左边固定宽度,右边自适应)

<div>
  <div style="display: table-cell;width: 200px;background: red;">
    left
  </div>
  <div style="display: table-cell;background: blue;">
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
    Main content in here;
  </div>
</div>

设置子元素为 table-cell, 可以实现和 table 一样的效果

2. 三列布局

2.1 圣杯布局

为了主内容区最先显示,因此在 dom 结构 middle 需要设置在最前面。

<div class='clearfix' style="padding: 0 200px 0 100px;">
  <div style="float: left;background: blue;width: 100%;">middle</div>
  <div style="float: left;background: red;width: 100px;margin-left: -100%;position: relative;left: -100px;">left</div>
  <div style="float: left;background: green;width: 200px;margin-left: -200px;position: relative;left:200px;">right</div>
</div>

三列元素,都设置为 float: left, 这时候,三个元素会凑在一起。设置 middle 宽度为 100%, 这时候 middle 独占一行,left 与 right 相连,在第二行。

left 元素设置 margin-left 为 -100%, -100% 相对于 父元素宽度,此时 left 与 middle 同一行,且与 middle 左边对齐。

同理 right 元素设置 margin-left 为 (-自身的宽度), 则 right 与 middle 同一行,且与 middle 右边对齐。

三个元素同在一行,但是此时的问题是,left 会遮挡 middle 的左边,right 会遮挡 middle 的右边,即 middle 的宽度过宽, 那么我们可以设置 三个元素的共同父元素的 padding。

设置完 padding 之后, middle 的位置合适,但是此时 left 和 right 都有一定的偏移,这时候可以将 left, right 设置为 relative, 并移动对应的距离即可。

缺点: 1. 在屏幕变小,middle 宽度小于 left 宽度时,布局会被破坏

2.2 双飞翼布局(淘宝对于圣杯布局的改进)

<div class='clearfix'>
  <div style="float: left;background: blue;width: 100%;">
    <div style="padding: 0 200px 0 100px;">  <!-- 使用 margin 也行 -->
      middle
    </div>
  </div>
  <div style="float: left;background: red;width: 100px;margin-left: -100%;">left</div>
  <div style="float: left;background: green;width: 200px;margin-left: -200px;">right
  </div>
</div>

同样是 float + 负 margin 的做法,放弃了 relative 定位的方式。而是通过增加一层 dom 结构,设置 padding 的值, 使得真正的内容显示在中间区域。

优点: 1. 解决了圣杯布局出现的,屏幕小时,布局被破坏的问题

缺点: 1. 需要多余的 dom 层级结构

2.3 绝对定位

<div style="position: relative;">
  <div style="background: red;width: 100px;position: absolute; left: 0; top: 0;">left</div>
  <div style="background: blue;margin: 0 200px 0 100px;">  <!-- padding 也行 -->
    middle
  </div>
  <div style="background: green;width: 200px;position: absolute;right: 0; top: 0;">right
  </div>
</div>

优点: 1. 左 中 右 dom 结构的位置顺序可以随意调整

缺点: 1. 左 中 右 的实际高度由 middle 决定,如果 left / right 高于 middle,此时 left / right 会遮挡 footer 区域

2.4 浮动定位

<div style="position: relative;">
  <div style="background: red;width: 100px; float: left;">left</div>
  <div style="background: green;width: 200px; float: right;">right</div>
  <div style="background: blue;margin: 0 200px 0 100px;"> <!-- padding 也行 -->
    middle
  </div>
</div>

同绝对定位一样,也就是使得 左 右 元素脱离文档流,middle 元素使用 padding 或 margin 与两个元素隔出距离。

缺点: 1. middle元素必须出现在 left 和 right 元素之后,不利于主题内容的呈现

2.5 flex 布局

<div style="display: flex;">
  <div style="background: red; flex: 0 0 100px;">left</div>
  <div style="background: blue; flex: 1 1 auto;">
    middle
  </div>
  <div style="background: green; flex:0 0 200px;">right
  </div>
</div>

优点: 1. 左 中 右 元素的 dom 结构顺序可以通过设置 order 来处理,很灵活

<div style="display: flex;">
  <div style="background: blue; flex: 1 1 auto;">
    middle
  </div>
  <div style="background: red; flex: 0 0 100px; order: -1;">left</div>
  <div style="background: green; flex:0 0 200px;">right
  </div>
</div>

缺点: 1. 需要注意 flex 在 IE 下的兼容性

参考资料

  1. [[布局]聊聊为什么淘宝要提出「双飞翼」布局

Previous不简单的 z-indexNextCSS 居中方案整理

Last updated 4 years ago

Was this helpful?

]()

CSS 布局 - 两栏自适应布局的几种实现方法汇总
CSS:两栏布局,三栏布局
https://github.com/zwwill/blog/issues/11
双飞翼布局介绍-始于淘宝UED-三列布局