1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
|
---
title: 介绍 CSS 布局
slug: Learn/CSS/CSS_layout/Introduction
tags:
- CSS
- flexbox
- 介绍
- 初学者
- 学习
- 定位
- 布局
- 文章
- 流
- 浮动
- 网格
- 表格
translation_of: Learn/CSS/CSS_layout/Introduction
---
<div>{{LearnSidebar}}</div>
<div>{{NextMenu("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout")}}</div>
<p class="summary">本文将回顾我们以前模块中已经介绍过的一些CSS布局特性——例如不同的{{cssxref("display")}}值——并介绍我们将在本模块中使用的一些概念。</p>
<table class="learn-box standard-table">
<tbody>
<tr>
<th scope="row">前提条件:</th>
<td>对HTML有一些基本的了解 (学习“<a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">HTML介绍</a>”), 并且理解CSS的工作原理 (学习“<a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">CSS介绍</a>”).</td>
</tr>
<tr>
<th scope="row">目标:</th>
<td>对CSS页面布局技术有一个总体的了解. 每种技术都能够在后面的教程中获取到更加详细的信息.</td>
</tr>
</tbody>
</table>
<p>CSS页面布局技术允许我们拾取网页中的元素,并且控制它们相对正常布局流、周边元素、父容器或者主视口/窗口的位置。在这个模块中将涉及更多关于页面<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/Layout_mode">布局技术</a>的细节:</p>
<ul>
<li>正常布局流</li>
<li>{{cssxref("display")}}属性</li>
<li>弹性盒子</li>
<li>网格</li>
<li>浮动</li>
<li>定位</li>
<li>CSS 表格布局</li>
<li>多列布局</li>
</ul>
<p>每种技术都有它们的用途,各有优缺点,相互辅助。通过理解各个布局方法的设计理念,你能够找到构建你想要的网页需要的布局方案。</p>
<h2 id="正常布局流Normal_flow">正常布局流(Normal flow)</h2>
<p>正常布局流(normal flow)是指在不对页面进行任何布局控制时,浏览器默认的HTML布局方式。让我们快速地看一个HTML的例子:</p>
<pre class="brush: html notranslate"><p>I love my cat.</p>
<ul>
<li>Buy cat food</li>
<li>Exercise</li>
<li>Cheer up friend</li>
</ul>
<p>The end!</p></pre>
<p>默认情况下,浏览器的显示如下:</p>
<p>{{ EmbedLiveSample('正常布局流Normal_flow', '100%', 200) }}</p>
<p>注意,HTML元素完全按照源码中出现的先后次序显示——第一个段落、无序列表、第二个段落。</p>
<p>出现在另一个元素下面的元素被描述为<strong>块</strong>元素,与出现在另一个元素旁边的<strong>内联元素</strong>不同,内联元素就像段落中的单个单词一样。</p>
<div class="blockIndicator note">
<p>注意:块元素内容的布局方向被描述为<strong>块方向</strong>。块方向在英语等具有水平<strong>书写模式</strong>(<code>writing mode</code>)的语言中垂直运行。它可以在任何垂直书写模式的语言中水平运行。对应的<strong>内联方向</strong>是内联内容(如句子)的运行方向。</p>
</div>
<p>当你使用css创建一个布局时,你正在离开<strong>正常布局流</strong>,但是对于页面上的多数元素,<strong>正常布局流</strong>将完全可以创建你所需要的布局。从一个结构良好的Html文档开始是如此重要,因为你可以按照默认的方式来搭建页面,而不是自己发明轮子。</p>
<p>下列布局技术会覆盖默认的布局行为:</p>
<ul>
<li><strong> {{cssxref("display")}} </strong>属性 — 标准的value,比如<code>block</code>, <code>inline</code> 或者 <code>inline-block</code> 元素在正常布局流中的表现形式 (见 <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Box_model#Types_of_CSS_boxes">Types of CSS boxes</a>). 接着是全新的布局方式,通过设置<code>display</code>的值, 比如 <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Grids">CSS Grid</a> 和 <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a>.</li>
<li><strong>浮动</strong>——应用 <strong>{{cssxref("float")}}</strong> 值,诸如 <code>left</code> 能够让块级元素互相并排成一行,而不是一个堆叠在另一个上面。</li>
<li><strong>{{cssxref("position")}} </strong>属性 — 允许你精准设置盒子中的盒子的位置,正常布局流中,默认为 <code>static</code> ,使用其它值会引起元素不同的布局方式,例如将元素固定到浏览器视口的左上角。</li>
<li><strong>表格布局</strong>— 表格的布局方式可以用在非表格内容上,可以使用<code>display: table</code>和相关属性在非表元素上使用。</li>
<li><strong>多列布局</strong>— 这个 <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Columns">Multi-column layout</a> 属性 可以让块按列布局,比如报纸的内容就是一列一列排布的。</li>
</ul>
<h2 id="display属性">display属性</h2>
<p>在css中实现页面布局的主要方法是设定<code>display</code>属性的值。此属性允许我们更改默认的显示方式。正常流中的所有内容都有一个<code>display</code>的值,用作元素的默认行为方式。例如,英文段落显示在一个段落的下面,这是因为它们的样式是<code>display:block</code>。如果在段落中的某个文本周围创建链接,则该链接将与文本的其余部分保持内联,并且不会打断到新行。这是因为{{htmlelement("a")}}元素默认为<code>display:inline</code>。</p>
<p>您可以更改此默认显示行为。例如,{{htmlelement("li")}}元素默认为<code>display:block</code>,这意味着在我们的英文文档中,列表项显示为一个在另一个之下。如果我们将显示值更改为<code>inline</code>,它们现在将显示在彼此旁边,就像单词在句子中所做的那样。事实上,您可以更改任何元素的<code>display</code>值,这意味着您可以根据它们的语义选择html元素,而不必关心它们的外观。他们的样子是你可以改变的。</p>
<p>除了可以通过将一些内容从<code>block</code>转换为<code>inline</code>(反之亦然)来更改默认表示形式之外,还有一些更大的布局方法以<code>display</code>值开始。但是,在使用这些属性时,通常需要调用其他属性。在讨论布局时,对我们来说最重要的两个值是<code>display</code>:<code>flex</code>和<code>display</code>:<code>grid</code>。</p>
<h2 id="弹性盒子Flexbox">弹性盒子(Flexbox)</h2>
<p>Flexbox 是CSS 弹性盒子布局模块(<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout">Flexible Box Layout</a> Module)的缩写,它被专门设计出来用于创建横向或是纵向的一维页面布局。要使用flexbox,你只需要在想要进行flex布局的父元素上应用<code>display: flex</code> ,所有直接子元素都将会按照flex进行布局。我们来看一个例子。</p>
<p>下面这些HTML标记描述了一个class为<code>wrapper</code>的容器元素,它的内部有三个<code><div></code>元素。它们在我们的英文文档当中,会默认地作为块元素从上到下进行显示。</p>
<p>现在,当我们把<code>display: flex</code>添加到它的父元素时,这三个元素就自动按列进行排列。这是由于它们变成了<em>flex项(flex items)</em>,按照flex容器(也就是它们的父元素)的一些flex相关的初值进行flex布局:它们整整齐齐排成一行,是因为父元素上<code>flex-direction</code>的初值是<code>row</code>。它们全都被拉伸至和最高的元素高度相同,是因为父元素上<code>align-items</code>属性的初值是<code>stretch</code>。这就意味着所有的子元素都会被拉伸到它们的flex容器的高度,在这个案例里就是所有flex项中最高的一项。所有项目都从容器的开始位置进行排列,排列成一行后,在尾部留下一片空白。</p>
<div id="Flex_1">
<div class="hidden">
<h6 id="Flexbox_Example_1">Flexbox Example 1</h6>
<pre class="brush: css notranslate">* {box-sizing: border-box;}
.wrapper > div {
border-radius: 5px;
background-color: rgb(207,232,220);
padding: 1em;
}
</pre>
</div>
<pre class="brush: css notranslate">.wrapper {
display: flex;
}
</pre>
<pre class="brush: html notranslate"><div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
</div>
</pre>
</div>
<p>{{ EmbedLiveSample('Flex_1', '300', '200') }}</p>
<p>除了上述可以被应用到flex容器的属性以外,还有很多属性可以被应用到flex项(flex items)上面。这些属性可以改变flex项在flex布局中占用宽/高的方式,允许它们通过伸缩来适应可用空间。</p>
<p>作为一个简单的例子,我们可以在我们的所有子元素上添加{{cssxref("flex")}} 属性,并赋值为<code>1</code>,这会使得所有的子元素都伸展并填充容器,而不是在尾部留下空白,如果有更多空间,那么子元素们就会变得更宽,反之,他们就会变得更窄。除此之外,如果你在HTML标记中添加了一个新元素,那么它们也会变得更小,来为新元素创造空间——不管怎样,最终它们会调整自己直到占用相同宽度的空间。</p>
<div id="Flex_2">
<div class="hidden">
<h6 id="Flexbox_Example_2">Flexbox Example 2</h6>
<pre class="brush: css notranslate"> * {box-sizing: border-box;}
.wrapper > div {
border-radius: 5px;
background-color: rgb(207,232,220);
padding: 1em;
}
</pre>
</div>
<pre class="brush: css notranslate">.wrapper {
display: flex;
}
.wrapper > div {
flex: 1;
}
</pre>
<pre class="brush: html notranslate"><div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
</div>
</pre>
</div>
<p>{{ EmbedLiveSample('Flex_2', '300', '200') }}</p>
<div class="note">
<p><strong>注意:</strong>为了找到更多关于Flexbox的信息,看看我们的 <a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a> 的文章。</p>
</div>
<h2 id="Grid布局">Grid布局</h2>
<p>Flexbox用于设计横向或纵向的布局,而Grid布局则被设计用于同时在两个维度上把元素按行和列排列整齐。</p>
<p>同flex一样,你可以通过指定display的值来转到grid布局:<code>display: grid</code>。下面的例子使用了与flex例子类似的HTML标记,描述了一个容器和若干子元素。除了使用<code>display:grid</code>,我们还分别使用 {{cssxref("grid-template-rows")}} 和 {{cssxref("grid-template-columns")}} 两个属性定义了一些行和列的轨道。定义了三个<code>1fr</code>的列,还有两个<code>100px</code>的行之后,无需再在子元素上指定任何规则,它们自动地排列到了我们创建的格子当中。</p>
<div id="Grid_1">
<div class="hidden">
<h6 id="Grid_example_1">Grid example 1</h6>
<pre class="brush: css notranslate"> * {box-sizing: border-box;}
.wrapper > div {
border-radius: 5px;
background-color: rgb(207,232,220);
padding: 1em;
}
</pre>
</div>
<pre class="brush: css notranslate">.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px;
grid-gap: 10px;
}
</pre>
<pre class="brush: html notranslate"><div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
<div class="box5">Five</div>
<div class="box6">Six</div>
</div>
</pre>
</div>
<p>{{ EmbedLiveSample('Grid_1', '300', '330') }}</p>
<p>一旦你拥有了一个grid,你也可以显式地将元素摆放在里面,而不是依赖于浏览器进行自动排列。在下面的第二个例子里,我们定义了一个和上面一样的grid,但是这一次我们只有三个子元素。我们利用 {{cssxref("grid-column")}} 和 {{cssxref("grid-row")}} 两个属性来指定每一个子元素应该从哪一行/列开始,并在哪一行/列结束。这就能够让子元素在多个行/列上展开。</p>
<div id="Grid_2">
<div class="hidden">
<h6 id="Grid_example_2">Grid example 2</h6>
<pre class="brush: css notranslate"> * {box-sizing: border-box;}
.wrapper > div {
border-radius: 5px;
background-color: rgb(207,232,220);
padding: 1em;
}
</pre>
</div>
<pre class="brush: css notranslate">.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px;
grid-gap: 10px;
}
.box1 {
grid-column: 2 / 4;
grid-row: 1;
}
.box2 {
grid-column: 1;
grid-row: 1 / 3;
}
.box3 {
grid-row: 2;
grid-column: 3;
}
</pre>
<pre class="brush: html notranslate"><div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
</div>
</pre>
</div>
<p>{{ EmbedLiveSample('Grid_2', '300', '330') }}</p>
<div class="note">
<p><strong>注意</strong>: 这两个例子只是展示了grid布局的冰山一角,要深入了解grid布局,请参阅我们的文章<a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid Layout</a>。</p>
</div>
<p>这篇指南的其余部分介绍了其他的布局方式,它们与你的页面的主要布局结构关系不大,但是却能够帮助你实现特殊的操作。同时,只要你理解了每一个布局任务的初衷,你就能够马上意识到哪一种布局更适合你的组件。</p>
<h2 id="浮动">浮动</h2>
<p>把一个元素“浮动”(float)起来,会改变该元素本身和在正常布局流(normal flow)中跟随它的其他元素的行为。这一元素会浮动到左侧或右侧,并且从正常布局流(normal flow)中移除,这时候其他的周围内容就会在这个被设置浮动({{cssxref("float")}})的元素周围环绕。</p>
<p>{{cssxref("float")}} 属性有四个可能的值:</p>
<ul>
<li><code>left</code> — 将元素浮动到左侧。</li>
<li><code>right</code> — 将元素浮动到右侧。</li>
<li><code>none</code> — 默认值, 不浮动。</li>
<li><code>inherit</code> — 继承父元素的浮动属性。</li>
</ul>
<p>在下面这个例子当中,我们把一个<code><div></code>元素浮动到左侧,并且给了他一个右侧的{{cssxref("margin")}},把文字推开。这给了我们文字环绕着这个<code><div></code>元素的效果,在现代网页设计当中,这是你唯一需要学会的事情。</p>
<div id="Float_1">
<div class="hidden">
<h6 id="Floats_example">Floats example</h6>
<pre class="brush: css notranslate">body {
width: 90%;
max-width: 900px;
margin: 0 auto;
}
p {
line-height: 2;
word-spacing: 0.1rem;
}
.box {
background-color: rgb(207,232,220);
border: 2px solid rgb(79,185,227);
padding: 10px;
border-radius: 5px;
}
</pre>
</div>
<pre class="brush: html notranslate"><h1>Simple float example</h1>
<div class="box">Float</div>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
</pre>
<pre class="brush: css notranslate">
.box {
float: left;
width: 150px;
height: 150px;
margin-right: 30px;
}
</pre>
</div>
<p>{{ EmbedLiveSample('Float_1', '100%', 600) }}</p>
<div class="note">
<p><strong>注意: </strong>: CSS浮动的知识会在我们关于 <a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">浮动</a>的教程当中被详细地解释。除此之外,如果您想要了解在Flexbox和Grid布局出现之前我们是如何进行列布局的(仍然有可能碰到这种情形),请阅读我们关于<a href="/zh-CN/docs/Learn/CSS/CSS_layout/%E4%BC%A0%E7%BB%9F%E7%9A%84%E5%B8%83%E5%B1%80%E6%96%B9%E6%B3%95">传统布局方式</a>的文章.</p>
</div>
<h2 id="定位技术">定位技术</h2>
<p>定位(positioning)能够让我们把一个元素从它原本在正常布局流(normal flow)中应该在的位置移动到另一个位置。定位(positioning)并不是一种用来给你做主要页面布局的方式,它更像是让你去管理和微调页面中的一个特殊项的位置。</p>
<p>有一些非常有用的技术在特定的布局下依赖于{{cssxref("position")}}属性。同时,理解定位(positioning)也能够帮助你理解正常布局流(normal flow),理解把一个元素移出正常布局流(normal flow)是怎么一回事。</p>
<p>有五种主要的定位类型需要我们了解:</p>
<ul>
<li><strong>静态定位(Static positioning)</strong>是每个元素默认的属性——它表示“将元素放在文档布局流的默认位置——没有什么特殊的地方”。</li>
<li><strong>相对定位(Relative positioning)</strong>允许我们相对于元素在正常的文档流中的位置移动它——包括将两个元素叠放在页面上。这对于微调和精准设计(design pinpointing)非常有用。</li>
<li><strong>绝对定位(Absolute positioning)</strong>将元素完全从页面的正常布局流(normal layout flow)中移出,类似将它单独放在一个图层中。我们可以将元素相对于页面的 <code><html></code> 元素边缘固定,或者相对于该元素的<em>最近被定位祖先元素(nearest positioned ancestor element)</em>。绝对定位在创建复杂布局效果时非常有用,例如通过标签显示和隐藏的内容面板或者通过按钮控制滑动到屏幕中的信息面板。</li>
<li><strong>固定定位(Fixed positioning)</strong>与绝对定位非常类似,但是它是将一个元素相对浏览器视口固定,而不是相对另外一个元素。 这在创建类似在整个页面滚动过程中总是处于屏幕的某个位置的导航菜单时非常有用。</li>
<li><strong>粘性定位(Sticky positioning)</strong>是一种新的定位方式,它会让元素先保持和<code>position: static</code>一样的定位,当它的相对视口位置(offset from the viewport)达到某一个预设值时,他就会像<code>position: fixed</code>一样定位。</li>
</ul>
<h3 id="简单定位示例">简单定位示例</h3>
<p>我们将展示一些示例代码来熟悉这些布局技术. 这些示例代码都作用在下面这一个相同的HTML上:</p>
<pre class="brush: html notranslate"><h1>Positioning</h1>
<p>I am a basic block level element.</p>
<p class="positioned">I am a basic block level element.</p>
<p>I am a basic block level element.</p></pre>
<p>该HTML将使用以下CSS默认样式:</p>
<pre class="brush: css notranslate">body {
width: 500px;
margin: 0 auto;
}
p {
background-color: rgb(207,232,220);
border: 2px solid rgb(79,185,227);
padding: 10px;
margin: 10px;
border-radius: 5px;
}</pre>
<p>渲染效果如下:</p>
<p>{{ EmbedLiveSample('简单定位示例', '100%', 300) }}</p>
<h3 id="相对定位">相对定位</h3>
<p>相对定位(relative positioning)让你能够把一个正常布局流(normal flow)中的元素从它的默认位置按坐标进行相对移动。比如将一个图标往下调一点,以便放置文字. 我们可以通过下面的规则添加相对定位来实现效果: </p>
<pre class="brush: css notranslate">.positioned {
position: relative;
top: 30px;
left: 30px;
}</pre>
<p>这里我们给中间段落的{{cssxref("position")}} 一个 <code>relative</code>值——这属性本身不做任何事情,所以我们还添加了{{cssxref("top")}}和{{cssxref("left")}}属性。这些可以将受影响的元素向下向右移——这可能看起来和你所期待的相反,但你需要把它看成是左边和顶部的元素被“推开”一定距离,这就导致了它的向下向右移动。</p>
<p>添加此代码将给出以下结果:</p>
<div id="Relative_1">
<div class="hidden">
<h6 id="Relative_positioning_example">Relative positioning example</h6>
<pre class="brush: html notranslate"><h1>Relative positioning</h1>
<p>I am a basic block level element.</p>
<p class="positioned">This is my relatively positioned element.</p>
<p>I am a basic block level element.</p></pre>
<pre class="brush: css notranslate">body {
width: 500px;
margin: 0 auto;
}
p {
background-color: rgb(207,232,220);
border: 2px solid rgb(79,185,227);
padding: 10px;
margin: 10px;
border-radius: 5px;
}
</pre>
</div>
<pre class="brush: css notranslate">.positioned {
position: relative;
background: rgba(255,84,104,.3);
border: 2px solid rgb(255,84,104);
top: 30px;
left: 30px;
}
</pre>
</div>
<p>{{ EmbedLiveSample('Relative_1', '100%', 300) }}</p>
<h3 id="绝对定位">绝对定位</h3>
<p>绝对定位用于将元素移出正常布局流(normal flow),以坐标的形式相对于它的容器定位到web页面的任何位置,以创建复杂的布局。有趣的是,它经常被用于与相对定位和浮动的协同工作。</p>
<p>回到我们最初的非定位示例,我们可以添加以下的CSS规则来实现绝对定位:</p>
<pre class="brush: css notranslate">.positioned {
position: absolute;
top: 30px;
left: 30px;
}</pre>
<p>这里我们给我们的中间段一个{{cssxref("position")}}的 <code>absolute</code>值,并且和前面一样加上 {{cssxref("top")}} 和{{cssxref("left")}} 属性。但是,添加此代码将给出以下结果:</p>
<div id="Absolute_1">
<div class="hidden">
<h6 id="Absolute_positioning_example">Absolute positioning example</h6>
<pre class="brush: html notranslate"><h1>Absolute positioning</h1>
<p>I am a basic block level element.</p>
<p class="positioned">This is my absolutely positioned element.</p>
<p>I am a basic block level element.</p></pre>
<pre class="brush: css notranslate">body {
width: 500px;
margin: 0 auto;
}
p {
background-color: rgb(207,232,220);
border: 2px solid rgb(79,185,227);
padding: 10px;
margin: 10px;
border-radius: 5px;
}</pre>
</div>
<pre class="brush: css notranslate">.positioned {
position: absolute;
background: rgba(255,84,104,.3);
border: 2px solid rgb(255,84,104);
top: 30px;
left: 30px;
}</pre>
</div>
<p>{{ EmbedLiveSample('Absolute_1', '100%', 300) }}</p>
<p>这和之前截然不同!定位元素现在已经与页面布局的其余部分完全分离,并位于页面的顶部。其他两段现在靠在一起,好像之前那个中间段落不存在一样。{{cssxref("top")}}和{{cssxref("left")}}属性对绝对位置元素的影响不同于相对位置元素。在这一案例当中,他们没有指定元素相对于原始位置的移动程度。相反,在这一案例当中,它们指定元素应该从页面边界的顶部和左边的距离(确切地说,是 <code><html></code>元素的距离)。我们也可以修改作为容器的那个元素(在这里是<code><html></code>元素),要了解这方面的知识,参见关于<a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Positioning">定位(positioning)</a>的课程</p>
<p>我们现在暂时不讨论固定定位( fixed positioning )——它基本上以相同的方式工作,除了它仍然固定在浏览器窗口的边缘,而不是它定位的父节点的边缘。</p>
<h3 id="固定定位">固定定位</h3>
<p>固定定位(fixed positioning)同绝对定位(absolute positioning)一样,将元素从文档流(document flow)当中移出了。但是,定位的坐标不会应用于"容器"边框来计算元素的位置,而是会应用于视口(viewport)边框。利用这一特性,我们可以轻松搞出一个固定位置的菜单,而不受底下的页面滚动的影响。</p>
<p>在这个例子里面,我们在HTML加了三段很长的文本来使得页面可滚动,又加了一个带有<code>position: fixed</code>的盒子。</p>
<pre class="brush: html notranslate"><h1>Fixed positioning</h1>
<div class="positioned">Fixed</div>
<p>Paragraph 1.</p>
<p>Paragraph 2.</p>
<p>Paragraph 3.</p>
</pre>
<div id="Fixed_1">
<div class="hidden">
<h6 id="Fixed_positioning_example">Fixed positioning example</h6>
<pre class="brush: html notranslate"><h1>Fixed positioning</h1>
<div class="positioned">Fixed</div>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
</pre>
<pre class="brush: css notranslate">body {
width: 500px;
margin: 0 auto;
}
.positioned {
background: rgba(255,84,104,.3);
border: 2px solid rgb(255,84,104);
padding: 10px;
margin: 10px;
border-radius: 5px;
}</pre>
</div>
<pre class="brush: css notranslate">.positioned {
position: fixed;
top: 30px;
left: 30px;
}</pre>
</div>
<p>{{ EmbedLiveSample('Fixed_1', '100%', 200) }}</p>
<h3 id="粘性定位">粘性定位</h3>
<p>粘性定位(sticky positioning)是最后一种我们能够使用的定位方式。它将默认的静态定位(static positioning)和固定定位(fixed positioning)相混合。当一个元素被指定了<code>position: sticky</code>时,它会在正常布局流中滚动,直到它出现在了我们给它设定的相对于容器的位置,这时候它就会停止随滚动移动,就像它被应用了<code>position: fixed</code>一样。</p>
<div id="Sticky_1">
<div class="hidden">
<h6 id="Sticky_positioning_example">Sticky positioning example</h6>
<pre class="brush: html notranslate"><h1>Sticky positioning</h1>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
<div class="positioned">Sticky</div>
<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> </pre>
<pre class="brush: css notranslate">body {
width: 500px;
margin: 0 auto;
}
.positioned {
background: rgba(255,84,104,.3);
border: 2px solid rgb(255,84,104);
padding: 10px;
margin: 10px;
border-radius: 5px;
}</pre>
</div>
<pre class="brush: css notranslate">.positioned {
position: sticky;
top: 30px;
left: 30px;
}</pre>
</div>
<p>{{ EmbedLiveSample('Sticky_1', '100%', 200) }}</p>
<div class="note">
<p><strong>注意</strong>: 想要发现更多关于定位的信息,请参阅我们的<a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a>和<a href="/en-US/docs/Learn/CSS/CSS_layout/Practical_positioning_examples">Practical positioning examples</a>文章。</p>
</div>
<h2 id="表格布局">表格布局</h2>
<p>HTML表格对于显示表格数据是很好的,但是很多年前——在浏览器中支持基本的CSS之前——web开发人员过去也常常使用表格来完成整个网页布局——将它们的页眉、页脚、不同的列等等放在不同的表行和列中。这在当时是有效的,但它有很多问题——表布局是不灵活的,繁重的标记,难以调试和语义上的错误(比如,屏幕阅读器用户在导航表布局方面有问题)。</p>
<p>一个{{htmlelement("table")}}标签之所以能够像表格那样展示,是由于css默认给{{htmlelement("table")}}标签设置了一组table布局属性。当这些属性被应用于排列非{{htmlelement("table")}}元素时,这种用法被称为“使用CSS表格”。</p>
<p>下面这个例子展示了一个这样的用法。使用CSS表格来进行布局,在现在这个时间点应该被认为是一种传统方法,它通常会被用于兼容一些不支持Flexbox和Grid的浏览器。</p>
<p>让我们来看一个例子。首先,创建HTML表单的一些简单标记。每个输入元素都有一个标签,我们还在一个段落中包含了一个标题。为了进行布局,每个标签/输入对都封装在{{htmlelement("div")}}中。</p>
<pre class="brush: html notranslate"><form>
<p>First of all, tell us your name and age.</p>
<div>
<label for="fname">First name:</label>
<input type="text" id="fname">
</div>
<div>
<label for="lname">Last name:</label>
<input type="text" id="lname">
</div>
<div>
<label for="age">Age:</label>
<input type="text" id="age">
</div>
</form></pre>
<p>现在,我们例子中的CSS。除了使用 {{cssxref("display")}} 属性外,大多数CSS都是相当普通的。 {{htmlelement("form")}}, {{htmlelement("div")}}, {{htmlelement("label")}}和{{htmlelement("input")}}被告知要分别显示表、表行和表单元——基本上,它们会像HTML表格标记一样,导致标签和输入在默认情况下排列整齐。我们所要做的就是添加一些大小、边缘等等,让一切看起来都好一点,我们就完成了。</p>
<p>你会注意到标题段落已经给出了 <code>display: table-caption;</code>——这使得它看起来就像一个表格{{htmlelement("caption")}} ——同时出于设计需要,我们通过<code>caption-side: bottom;</code> 告诉标题应该展示在表格的底部,即使这个{{htmlelement("p")}}标记在源码中是在<code><input></code>之前。这就能让你有一点灵活的弹性。</p>
<pre class="brush: css notranslate">html {
font-family: sans-serif;
}
form {
display: table;
margin: 0 auto;
}
form div {
display: table-row;
}
form label, form input {
display: table-cell;
margin-bottom: 10px;
}
form label {
width: 200px;
padding-right: 5%;
text-align: right;
}
form input {
width: 300px;
}
form p {
display: table-caption;
caption-side: bottom;
width: 300px;
color: #999;
font-style: italic;
}</pre>
<p>结果如下:</p>
<p>{{ EmbedLiveSample('CSS_表格', '100%', '170') }}</p>
<p>你可以在 <a href="https://mdn.github.io/learning-area/css/styling-boxes/box-model-recap/css-tables-example.html">css-tables-example.html</a> 看到预览版 (也可以见<a href="https://github.com/mdn/learning-area/blob/master/css/styling-boxes/box-model-recap/css-tables-example.html">源码</a>)</p>
<h2 id="多列布局">多列布局</h2>
<p>多列布局模组给了我们 一种把内容按列排序的方式,就像文本在报纸上排列那样。由于在web内容里让你的用户在一个列上通过上下滚动来阅读两篇相关的文本是一种非常低效的方式,那么把内容排列成多列可能是一种有用的技术。</p>
<p>要把一个块转变成多列容器(multicol container),我们可以使用 {{cssxref("column-count")}}属性来告诉浏览器我们需要多少列,也可以使用{{cssxref("column-width")}}来告诉浏览器以至少某个宽度的尽可能多的列来填充容器。</p>
<p>在下面这个例子中,我们从一个class为<code>container</code>的<code><div></code>容器元素里边的一块HTML开始。</p>
<pre class="brush: html notranslate"><div class="container">
<h1>Multi-column layout</h1>
<p>Paragraph 1.</p>
<p>Paragraph 2.</p>
</div>
</pre>
<p>我们指定了该容器的<code>column-width</code>为200像素,这让浏览器创建了尽可能多的200像素的列来填充这一容器。接着他们共同使用剩余的空间来伸展自己的宽度。</p>
<div id="Multicol_1">
<div class="hidden">
<h6 id="Multicol_example">Multicol example</h6>
<pre class="brush: html notranslate"> <div class="container">
<h1>Multi-column Layout</h1>
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p>
<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
</div>
</pre>
<pre class="brush: css notranslate">body { max-width: 800px; margin: 0 auto; } </pre>
</div>
<pre class="brush: css notranslate"> .container {
column-width: 200px;
}</pre>
</div>
<p>{{ EmbedLiveSample('Multicol_1', '100%', 200) }}</p>
<h2 id="总结">总结</h2>
<p>本文提供了关于您应该了解的所有布局技术的简要概述。阅读更多关于每一项技术的信息!</p>
<p>{{NextMenu("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout")}}</p>
|