文档章节

margin系列之圣杯拾遗

山哥
 山哥
发布于 2016/11/30 15:11
字数 2152
阅读 51
收藏 0
点赞 0
评论 0

margin系列之布局篇 一文结尾时,我们谈到了圣杯布局,说这个布局的实现本身存在了一些问题:“在IE6/7下报废,不过不用慌,因为它可被修复”。

圣杯布局的一些谈资

下面节选一段来自网路上对圣杯的描述(略有调整):

圣杯是宗教传说中的圣物,耶稣曾经用这个杯子吩咐门徒喝下里面象征他的血的红葡萄酒,借此创立了受难纪念仪式。因为这个特殊的原因,后来有些人认为这个杯子具有某种神奇的能力。很多传说相信,如果能找到这个圣杯而喝下其盛过的水就将返老还童、死而复生并且获得永生,这个传说广泛延续到很多文学、影视、游戏等作品中。

而所谓的圣杯布局也并不是一个具象的形容,更多的是指借希望于它能够实现某种特殊的布局。

这种特殊布局的需求是:侧边栏宽度固定,主内容栏宽度自适应,并且需要将主内容栏放在侧边栏前面,以便优先渲染(不论是两栏或者三栏,需求都是一样的)。

遗留的问题

在 margin系列之布局篇 里,我们用圣杯布局做了 图0 的效果。

图0:classsic layout

图0:classsic layout

下面是我们在上篇文章中写的圣杯布局核心代码(当然,这个 #demo 容器你也可以利用 body来取代):

HTML

1
2
3
4
5
6
7
8
<div id="demo">
    <header id="hd">头部</header>
    <div id="bd">
        <div id="main">主内容栏自适应宽度</div>
        <aside id="aside">侧边栏固定宽度</aside>
    </div>
    <footer id="ft">底部</footer>
</div>

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#demo {
    width: 80%;
}
#bd {
    *zoom: 1;
    overflow: hidden;
    padding-left: 210px;
}
#main {
    float: left;
    width: 100%;
}
#aside {
    _display: inline;
    float: left;
    position: relative;
    left: -210px;
    width: 200px;
    margin-left: -100%;
}

大家可以使用各种浏览器来测试一下这个示例 圣杯:左栏固定主内容自适应

一般情况下,你会发现除了IE6外,其它的浏览器看起来都算正常,然而问题的范围可能并不仅限于这些,大部分问题没被看出只不过是因为没到达边界。

问题列表:

  • IE6 布局错乱,侧边栏位置不对;
  • IE7 resize窗口时,侧边栏会跳动;
  • IE7及其它浏览器,当窗口缩小到主内容栏的宽度小于侧边栏的宽度时,布局错乱;

上面这几个问题,大家其实都可以自己去测测看,应该是当前的实现中都存在的。

对于第3点,我们看看上述的代码实现,还是能非常轻松的理解的。因为侧边栏定义了 margin-left: -100%,在这个场景中,100% 其实就等同于主内容栏的宽度。如果主内容栏的宽度小于侧边栏,那么侧边栏偏移了一个比自己小的宽度,自然是放不下自己的。

对于第1点,这个就有点意思了,基本上这又算是IE6的一个Bug,描述一下这个Bug的现象:

在IE6中,假定是处于默认的书写模式下,当一个浮动的元素定义了margin的值是一个百分比,那么此时,浮动元素的margin百分比参照最近的清除了浮动的包含块的父元素的宽度进行计算,或者参照body。(然而标准描述只是参考包含块的宽度进行计算,详情请参阅我之前的文章 margin系列之百分比

我会用一段伪代码来详述这个事,代码如下:

1
body > c > b > a

假设上述代码中的 a 就是我们说的浮动元素,正常情况下 a 设置了一个百分比的margin,百分比是要参考 b 的宽度进行计算的。

然后 IE6 并没有实现这个规则,它的特征是:

  • 浮动元素 a 定义了百分比的margin,假设它的祖先元素 b 和 c 都没有清除浮动,那么就会参照 body 的宽度进行百分比换算;
  • 假设 b 清除了浮动,那么就会参照 c 的宽度进行百分比换算;

对于这个Bug,我写了一个示例,大家可以对照着描述来看这个例子:浮动margin百分比在ie6上的Bug

好了,知道了在 IE6 中有这个Bug之后,关于问题列表中的第1点,我们就也能够理解了,因为 position: relative; left: -210px; 这个定义对于 IE6 来讲,其实是多余的。

对于第2点,应该是在resize过程中,不断的重绘造成的,它需要不断的去计算这个百分比的使用值。

杀死它们

所以如果想使得圣杯布局变得更靠谱一些,我们要么就是见招拆招,修复这个问题(比如说为 IE6 重置掉 position: relative; left: -210px; 定义),要么就避免遇上这些问题,我更喜欢第二种的方式。

我们如何做才能避免遇上这些问题?

其实我们可以细看一下,问题列表中的几点,其实都是因浮动元素的margin百分比引发的。既然浮动元素的margin百分比,在各浏览器下需要差异化处理,那么干脆弃用百分比,改用固定值(复杂度其实并没有上升,因为用百分比的时候,还得给left定义一个固定的偏移量)。

那么,新的问题来了。如果改用margin固定值,我们要如何知道这个固定值是多少?比如在这个布局中我们的容器宽度是视窗的 80%,我们无法得到侧边栏需要偏移的固定值是多少,除非我们使用运算表达式 calc(),但是它的兼容性并不是我们想要的。

这是因为主内容栏和侧边栏都是左浮动,并且侧边栏浮动在主内容栏后面,所以我们需要让侧边栏偏移 #main + #aside 的宽度,才能让侧边栏出现在正确的位置。

所以,其实我们可以转变一下思路,让主内容栏和侧边栏朝不同的方向浮动,这样的话,侧边栏只需要偏移自身的宽度就能出现在正确的位置上,不在需要使用margin百分比值。

新路

我们按照前面说的将代码调整一下,HTML不变:

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#demo {
    width: 80%;
}
#bd {
    *zoom: 1;
    overflow: hidden;
    padding-left: 210px;
}
#main {
    float: right;
    width: 100%;
}
#aside {
    _display: inline;
    float: left;
    width: 200px;
    margin: 0 10px 0 -210px;
}

我们来看看这个 进化的圣杯:左栏固定主内容自适应 效果,你会欣喜的发现,问题列表中的3个问题都被我们跳过了,这是一个更健康的实现。

当然,它也是可以任意调整列呈现顺序的,我们只需要这样就行:

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#demo {
    width: 80%;
}
#bd {
    *zoom: 1;
    overflow: hidden;
    padding-right: 210px;
}
#main {
    float: left;
    width: 100%;
}
#aside {
    _display: inline;
    float: right;
    width: 200px;
    margin: 0 -210px 0 10px;
}

于是我们就得到了一个 进化的圣杯:右栏固定主内容自适应 的布局。

总体来讲,圣杯布局只是有能力达成我们的需求,但就其本身来讲并不是太先进的布局,灵活性相对局限。

另外,你可能关注到了代码中出现的 margin 定义,它并不是一个单纯的负值,而是多了一个 10px,这其实是为了解决 IE6/7 右浮动子元素的向右负偏移量最大只能是自身宽度的问题(感兴趣的童鞋可以看看这个测试:右浮动margin-right负值在ie67上的bug),所以额外处理的间隙,但这其实并不影响其他浏览器。

最后

本文,更多的在于补全之前的那篇文章,算个简单的完结。本意其实并不在于说让大家去折腾那些古老而无趣的浏览器,而是希望看到的是对待任何事情,我们首先要觉得它可以解决,然后再抽丝剥茧的去实现它。未知并不可怕,可怕是恐惧未知。

本文转载自:http://blog.doyoe.com/2016/04/28/css/margin%E7%B3%BB%E5%88%97%E4%B9%8B%E5%9C%A3%E6%9D%AF%E6%8B%BE%E9

共有 人打赏支持
山哥

山哥

粉丝 242
博文 306
码字总数 136465
作品 0
南京
程序员
圣杯布局(holy grail)总结

什么是圣杯布局? 根据 wikipedia词条,圣杯指多列等高的网页布局。因为目前的实现方法都存在局限,而又很难找到一个最优解,圣杯因此而得名。 holy-grail.png 在Matthew Levine 的文章 中提...

一拾五 ⋅ 01/14 ⋅ 0

关于BFC的一些思考

Question 以下三个div将会会如何放置(margin collapsing)? 同一个BFC中,相邻的块状元素都是垂直放置吗? 如何清除浮动?根据什么原理? 如何对左侧栏200px,主内容自适应进行布局? 如何使...

shanyue ⋅ 2017/11/29 ⋅ 0

从css盒子与定位到布局

css盒子模型 原理:padding,border,margin三者构成一个盒子。 图片来自网络 Margin(外边距) - 清除边框外的区域,外边距是透明的。 Border(边框) - 围绕在内边距和内容外的边框。 Padding(内...

黑天很黑 ⋅ 2017/01/26 ⋅ 0

CSS布局终极方案之--改进圣杯布局(兼容IE6+,现代浏览器)

CSS兼容所有浏览器(IE6+,现代浏览器)的终极布局方案之 -- 改进版圣杯布局 改进思想: 通过对主内容区main增加一个额外包裹层div,将原来在父节点上的 padding-left|right 设置转移到包裹层上...

山哥 ⋅ 2015/01/16 ⋅ 0

CSS 布局技巧-基础网页布局、圣杯布局、双飞翼布局

概述 image.png image.png image.png image.png 概要 image.png CSS基础布局 image.png image.png 源码 在浏览器中展现的效果,上面将 .content 的高度设置为了 300px 才会出现下面这样的情况...

神秘者007 ⋅ 03/16 ⋅ 0

CSS经典三栏布局方案

1. float布局 最简单的三栏布局就是利用float进行布局。首先来绘制左、右栏: 此时可以得到左右两栏分布: 这里写图片描述 接下来再来看中间栏如何处理。我们知道对于float元素,其会脱离文档...

李牙刷儿 ⋅ 2017/11/30 ⋅ 0

CSS三栏布局的四种方法

前言 总括: 不管是三栏布局还是两栏布局都是我们在平时项目里经常使用的,也许你不知道什么事三栏布局什么是两栏布局但实际已经在用,或许你知道三栏布局的一种或两种方法,但实际操作中也只...

Damonare ⋅ 2016/12/11 ⋅ 0

CSS3与页面布局学习总结

一、负边距与浮动布局 1.1、负边距 所谓的负边距就是margin取负值的情况,如margin:-100px,margin:-100%。当一个元素与另一个元素margin取负值时将拉近距离。常见的功能如下: 1.1.1、向上移...

当当当当蛋糕 ⋅ 2016/12/07 ⋅ 0

CTNetworking源码拾遗

一句话简介:CTNetworking为casa大神针对iOS网络层方案的一个架构实例。 架构详解: 传送门 Github: 传送门 PS: 本拾遗系列文章只专注于代码以及工程层面知识点拾遗,架构层面作者文章已经进行...

AliThink ⋅ 2016/09/05 ⋅ 0

进一步了解flex布局—来实现这些常见布局吧

  flex布局具有便捷、灵活的特点,熟练的运用flex布局能解决大部分布局问题,这里对一些常用布局场景做一些总结。 web页面布局(topbar + main + footbar) 示例代码   要实现的效果如下:...

LT_bear ⋅ 05/29 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JavaScript零基础入门——(十)JavaScript的DOM基础

JavaScript零基础入门——(十)JavaScript的DOM基础 欢迎大家回到我们的JavaScript零基础入门,上一节课,我们了解了JavaScript中的函数,这一节课,我们来了解一下JavaScript的DOM。 第一节...

JandenMa ⋅ 36分钟前 ⋅ 0

Spring mvc DispatchServlet 实现原理

在Spring中, ContextLoaderListener只是辅助类,在web 容器启动的时候查找并创建WebApplicationContext对象,通过该对象进行加载spring的配置文件。而真正的逻辑实现其实是在DispatcherSer...

轨迹_ ⋅ 47分钟前 ⋅ 0

Weex起步

本教程假设你已经在你的本地环境安装了node 其实weex起步教程在 https://github.com/lilugirl/incubator-weex 项目说明文件中都已经有了,但为了有些同学看到英文秒变文盲,所以这里我重新写...

lilugirl ⋅ 55分钟前 ⋅ 0

Jenkins实践1 之安装

1 下载 http://mirrors.jenkins.io/war/latest/jenkins.war 2 启动 java -jar jenkins.war 前提:安装jdk并配置环境变量 启动结果节选: ************************************************......

晨猫 ⋅ 今天 ⋅ 0

组合数学 1-2000 中,能被6或10整除的数的个数

1--2000 中,能被6或10整除的数的个数 利用集合的性质 能被6整除的个数 2000/6 = 333 能被10整除的个数 2000/10 = 200 能被6和10整除的个数 2000/30 = 66 能被6或10整除的个数 333+200-66 =...

阿豪boy ⋅ 今天 ⋅ 0

一篇文章学懂Shell脚本

Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合。 Shell可以直接使用在win/Unix/Linux上面,并且可以调用...

Jake_xun ⋅ 今天 ⋅ 0

大数据工程师需要精通算法吗,要达到一个什么程度呢?

机器学习是人工智能的一个重要分支,而机器学习下最重要的就是算法,本文讲述归纳了入门级的几个机器学习算法,加大数据学习群:716581014一起加入AI技术大本营。 1、监督学习算法 这个算法由...

董黎明 ⋅ 今天 ⋅ 0

Kylin 对维度表的的要求

1.要具有数据一致性,主键值必须是唯一的;Kylin 会进行检查,如果有两行的主键值相同则会报错。 2.维度表越小越好,因为 Kylin 会将维度表加载到内存中供查询;过大的表不适合作为维度表,默...

无精疯 ⋅ 今天 ⋅ 0

58到家数据库30条军规解读

军规适用场景:并发量大、数据量大的互联网业务 军规:介绍内容 解读:讲解原因,解读比军规更重要 一、基础规范 (1)必须使用InnoDB存储引擎 解读:支持事务、行级锁、并发性能更好、CPU及...

kim_o ⋅ 今天 ⋅ 0

代码注释中顺序更改 文件读写换行

`package ssh; import com.xxx.common.log.LogFactory; import com.xxx.common.log.LoggerUtil; import org.apache.commons.lang3.StringUtils; import java.io.*; public class DirErgodic ......

林伟琨 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部