内容布局(二):水平布局

上期回忆了 position 布局,这期继续唠嗑传统布局中的水平布局。

概述

通常我们的页面会随内容增加沿垂直方向扩展,但现实排版中我们也会有左右水平扩展的需求。现在的开发自然是通过 flex box 解决这类问题。但是在一些老破旧系统,如银行系统的 ie6,ie9 这类页面之中,我们一般又是如何水平布局的呢?

浮动(float)布局

首先是 float 布局。float 模型和上一期的 position 模型一样,也是一种脱离文档流的技术,语法同样简单——直接在元素上添加float: none|left|right|initial|inherit;即可。虽说 float 共五种属性,但事实上真正起作用的也就 left 和 right;顾名思义,一个往左漂,一共往右漂。

OK,既然都是脱离文档流,position 和 float 的区别是什么?初学 CSS 时,我经常搞混它们俩。后来想想,无他,设计初衷不同:position 实现元素叠加的效果,而 float 则是实现元素环绕的效果。给个例子,先看原图:

figure & section

我希望图片能移动到布局右侧,并形成文字环绕的效果。

<main>
  <figure>
    <img src="..." alt="mvp">
  </figure>
  <section>
    <h1>MVP</h1>
    <p>
      Model–view–presenter (MVP) ....</p>
  </section>
</main>

代码很简单,一行搞定。

figure { float: right; }

添加float: right的浮动盒子会自动向右漂移,直到该盒子的 border 碰到包含块的内边缘(或接触到另一个浮动盒子外边缘)。后续元素根据常规文档流重新布局,但内部的行内块(inline-block)元素——如文字——会避开浮动盒子,这就形成了文字环绕的效果。

Surrounding

当然,这节的主题并不是文字环绕,只是人们突然发现,图片右浮动了,如果把文本块也浮动一下,不就形成左右两块浮动的水平布局了吗?

figure {
  float:right;
  width: 30%;
  margin: 0;
  border: dotted red;
}

section {
  float:  left;
  width: 65%;
  margin: 0;
  border: solid yellow;
}

块状元素默认会占据 100% 文档流宽度,我们分别给图片和文字设置 30% 和 65%的宽占比(5%留白);这样两个浮动盒子就互相错开了,形成了如下左右双视的布局。

Left & Right

不过这里还有个小问题,我特意给上图的包含块main加了蓝色的外边框。发现没有?包含块在两个浮动盒子的上侧,原因就是包含块内部的子元素全部走出了文档流,它反倒成了一个空盒子。解决方法很简单,给包含块内部再填一个空元素,并使用clear,这个空元素就会挤开包含块,直到避开所有浮动的兄弟元素。当然,我不是很想再修改 html 文本,比如给它加个 div 什么的;我的方法是:在 CSS 中引入伪类::after,它也会在包含块末尾生成一个盒子。试着给它应用 clear:

main::after {
  clear: both;
  display: block;
  content: '';
}

Bingo!

Pseudo-elements

行内块(inline-block)布局

我们再来看另一种水平布局的方式——inline-block 布局。我们常常用到如下几种原生 html tag:div、article、h1~h6。它们的布局默认是从下往下的,但还有几种 tag 的布局默认是从左往右的,如 span、time、a 等等。区别是,前者的 diaplay 是 block,而后者的 display 是 inline-block(行内块)。OK,有了这个先天的条件,我们发散地思考一下:如果把 div 的 display 设成 inline-block,那它不也就能从左往右水平布局了吗?

事实上,很多页面最上方的导航栏就是这么干的。

Navigation Bar

它们的实现是一般就是一组ul~li列表,如下所示:

<nav>
  <ul>
    <li><a href="/home">HOME</a></li>
    <li><a href="/onion">Onion</a></li>
    <li><a href="/garlic">Garlic</a></li>
    <li><a href="/ginger">Ginger</a></li>
  </ul>
</nav>

我们稍微添加一点效果:

nav {
  border: solid blue;
}

ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

li {
  width: 25%;
  margin: 0;
  outline:  1px solid blue;
  text-align: center;
}

这里主要是除去了 ul 原始的 style——不然,每行之前都会有个黑点。然后把 li 宽度设成 25%,以便之后四等分导航栏。

ul style none

接着,我们再将 li 做成行内块元素,这样它会从垂直布局变成水平布局。

li {
  display: inline-block;
  width: 25%;
  margin: 0;
  outline:  1px solid blue;
  text-align: center;
}
inline li

OK,效果有了,只是并非四等分的水平布局。仔细观察,各个导航块之间有细缝,但是我们已经把 margin 设成 0 了,那这又是什么呢?这其实是 html 源码中的换行符:

<li><a href="/garlic">Garlic</a></li>
<li><a href="/ginger">Ginger</a></li>

我们在编写源码时,换行了。这就导致了一件很有趣的事,浏览器把这些换行符渲染成了空白字符。因此,一行中无法容下四个 25%的导航块外加一些空白字符了,也就只能把第四块导航块放到第二行了。

解决方法很粗暴,就是把 ul 里的 font-size 设成 0,然后再在 li 里设回来。

ul {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 0;
}

li {
  display: inline-block;
  width: 25%;
  margin: 0;
  outline:  1px solid blue;
  text-align: center;
  font-size: 1rem;
}

OK,如期解决了空白问题,每一列都靠拢了,也就能撑到一行内了。

Navigation Bar

表格(table)布局

inline-block 布局其实挺麻烦的,要算好宽度,还要改字体。有没有更优雅的方式?

大家,可以试试 table 布局(当然我说的不是 dreamviewer 那个年代的摆放方式)display: table;

还是上面老的 html,把 ul 做成 table,li 做成 table 元素,然后浏览器会自动帮你调整好该行的所有导航块了。

ul {
  display: table;
  width: 100%;
  margin: 0;
  padding: 0;
}

li {
  display: table-cell;
  outline:  1px solid blue;
  text-align: center;
}
table layout

小结

这期,我们快速浏览了传统水平布局的三种实现方式:float 布局,inline-block 布局和 table 布局。怎么说呢,这些都是 CSS2 那个刀耕火种的年代里,前端程序员费劲心思挖掘出来的一种排版经验吧,但是总体来这些布局限制比较大,功能也很单一——不好用。正如某个姓黄的伟人所说:这些“奇技淫巧”终将消失在滚滚的历史洪流之中。现在的程序员也没有太大必要去深挖这些特性了,我们还是放眼未来,去学习更高效的工具——flex box 吧。

相关

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355