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
|
---
title: 布局和包含块
slug: Web/CSS/All_About_The_Containing_Block
tags:
- CSS
- CSS Position
- Containers
- Guide
- Layout
- Position
- Style
- blocks
- containing block
- size
translation_of: Web/CSS/Containing_block
---
<p>{{cssref}}</p>
<p class="summary" dir="ltr">一个元素的尺寸和位置经常受其<strong>包含块(containing block)</strong>的影响。大多数情况下,包含块就是这个元素最近的祖先<a href="/zh-CN/docs/Web/HTML/Block-level_elements">块元素</a>的<a href="/zh-CN/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model#content-area">内容区</a>,但也不是总是这样。在本文中,我们来过一遍确定包含块的所有因素。</p>
<p dir="ltr">当一个客户端代理(比如说浏览器)展示一个文档的时候,对于每一个元素,它都产生了一个盒子。每一个盒子都被划分为四个区域:</p>
<ol dir="ltr" start="1">
<li>内容区</li>
<li>内边距区</li>
<li>边框区</li>
<li>外边距区</li>
</ol>
<p><img alt="Diagram of the box model" src="https://mdn.mozillademos.org/files/16558/box-model.png" style="height: 300px; width: 544px;"></p>
<p dir="ltr">许多开发者认为一个元素的包含块就是他的父元素的内容区。但事实并非如此。接下来让我们来看看,确定元素包含块的因素都有哪些。</p>
<h2 dir="ltr" id="包含块的影响">包含块的影响</h2>
<p dir="ltr">在学习如何确定元素包含块之前,先了解一下它的重要性。</p>
<p dir="ltr">元素的尺寸及位置,常常会受它的包含块所影响。对于一些属性,例如 {{cssxref("width")}}, {{cssxref("height")}}, {{cssxref("padding")}}, {{cssxref("margin")}},绝对定位元素的偏移值 (比如 {{cssxref("position")}} 被设置为 <code>absolute</code> 或 <code>fixed</code>),当我们对其赋予百分比值时,这些值的计算值,就是通过元素的包含块计算得来。</p>
<h2 dir="ltr" id="确定包含块">确定包含块</h2>
<p dir="ltr">确定一个元素的包含块的过程完全依赖于这个元素的 {{cssxref("position")}} 属性:</p>
<ol dir="ltr" start="1">
<li>如果 position 属性为 <code><strong>static</strong></code> 、<strong> </strong><code><strong>relative</strong></code><strong> 或 <code>sticky</code></strong>,包含块可能由它的最近的祖先<strong>块元素</strong>(比如说inline-block, block 或 list-item元素)的内容区的边缘组成,也可能会建立格式化上下文(比如说 a table container, flex container, grid container, 或者是 the block container 自身)。</li>
<li>如果 position 属性为 <code><strong>absolute</strong></code> ,包含块就是由它的最近的 position 的值不是 <code>static</code> (也就是值为<code>fixed</code>, <code>absolute</code>, <code>relative</code> 或 <code>sticky</code>)的祖先元素的内边距区的边缘组成。</li>
<li>如果 position 属性是 <strong><code>fixed</code></strong>,在连续媒体的情况下(continuous media)包含块是 {{glossary("viewport")}} ,在分页媒体(paged media)下的情况下包含块是分页区域(page area)。</li>
<li>如果 position 属性是 <code><strong>absolute</strong></code> 或 <code><strong>fixed</strong></code>,包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:
<ol start="1">
<li> {{cssxref("transform")}} 或 {{cssxref("perspective")}}<strong> </strong>的值不是 <code>none</code></li>
<li> {{cssxref("will-change")}} 的值是 <code>transform</code> 或 <code>perspective</code></li>
<li> {{cssxref("filter")}}<strong> </strong>的值不是 <code>none</code> 或 <code>will-change</code> 的值是 <code>filter</code>(只在 Firefox 下生效).</li>
<li> {{cssxref("contain")}} 的值是 <code>paint</code> (例如: <code>contain: paint;</code>)</li>
</ol>
</li>
</ol>
<div class="note">
<p dir="ltr"><strong>注意: </strong>根元素(<html>)所在的包含块是一个被称为<strong>初始包含块</strong>的矩形。他的尺寸是视口 viewport (for continuous media) 或分页媒体 page media (for paged media).</p>
</div>
<h2 dir="ltr" id="根据包含块计算百分值">根据包含块计算百分值</h2>
<p dir="ltr">如上所述,如果某些属性被赋予一个百分值的话,它的计算值是由这个元素的包含块计算而来的。这些属性包括盒模型属性和偏移属性:</p>
<ol dir="ltr" start="1">
<li>要计算 {{cssxref("height")}} {{cssxref("top")}} 及 {{cssxref("bottom")}} 中的百分值,是通过包含块的 <code>height</code><strong> </strong>的值。如果包含块的 <code>height</code> 值会根据它的内容变化,而且包含块的 <code>position</code> 属性的值被赋予 <code>relative</code> 或 <code>static</code> ,那么,这些值的计算值为 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">auto</span></font>。</li>
<li>要计算 {{cssxref("width")}}, {{cssxref("left")}}, {{cssxref("right")}}, {{cssxref("padding")}}, {{cssxref("margin")}} 这些属性由包含块的 <code>width</code> 属性的值来计算它的百分值。</li>
</ol>
<h2 dir="ltr" id="示例">示例</h2>
<p dir="ltr">接下来的示例,都使用如下 HTML 代码:</p>
<pre class="brush: html notranslate" dir="ltr"><body>
<section>
<p>This is a paragraph!</p>
</section>
</body></pre>
<p class="brush: html" dir="ltr">下面的示例,只有 CSS 不同。</p>
<h3 id="Example_1">Example 1</h3>
<p>这个示例中,P 标签设置为静态定位,所以它的包含块为 <code><section></code> ,因为距离最近的父节点即是她的包含块。</p>
<div class="hidden">
<pre class="brush: html notranslate" dir="ltr"><body>
<section>
<p>This is a paragraph!</p>
</section>
</body>
</pre>
</div>
<pre class="brush: css notranslate" dir="ltr">body {
background: beige;
}
section {
display: block;
width: 400px;
height: 160px;
background: lightgray;
}
p {
width: 50%; /* == 400px * .5 = 200px */
height: 25%; /* == 160px * .25 = 40px */
margin: 5%; /* == 400px * .05 = 20px */
padding: 5%; /* == 400px * .05 = 20px */
background: cyan;
}
</pre>
<p>{{EmbedLiveSample('Example_1','100%','300')}}</p>
<h3 id="Example_2">Example 2</h3>
<p>在这个示例中,P 标签的包含块为 <code><body></code><strong> 元素,</strong>因为 <code><section></code> 不再是一个块容器,所以并没有形成一个格式上下文。</p>
<div class="hidden">
<pre class="brush: html notranslate" dir="ltr"><body>
<section>
<p>This is a paragraph!</p>
</section>
</body>
</pre>
</div>
<pre class="brush: css notranslate" dir="ltr">body {
background: beige;
}
section {
display: inline;
background: lightgray;
}
p {
width: 50%; /* == half the body's width */
height: 200px; /* Note: a percentage would be 0 */
background: cyan;
}
</pre>
<p>{{EmbedLiveSample('Example_2','100%','300')}}</p>
<h3 id="Example_3">Example 3</h3>
<p>这个示例中,P 元素的包含块是 <code><section</code>>,因为 <code><section></code> 的 <code>position</code> 为 <code>absolute</code> 。P 元素的百分值会受其包含块的 <code>padding</code> 所影响。不过,如果包含块的 {{cssxref("box-sizing")}} 值设置为 <code>border-box</code> ,就没有这个问题。</p>
<div class="hidden">
<pre class="brush: html notranslate" dir="ltr"><body>
<section>
<p>This is a paragraph!</p>
</section>
</body>
</pre>
</div>
<pre class="brush: css notranslate" dir="ltr">body {
background: beige;
}
section {
position: absolute;
left: 30px;
top: 30px;
width: 400px;
height: 160px;
padding: 30px 20px;
background: lightgray;
}
p {
position: absolute;
width: 50%; /* == (400px + 20px + 20px) * .5 = 220px */
height: 25%; /* == (160px + 30px + 30px) * .25 = 55px */
margin: 5%; /* == (400px + 20px + 20px) * .05 = 22px */
padding: 5%; /* == (400px + 20px + 20px) * .05 = 22px */
background: cyan;
}
</pre>
<p>{{EmbedLiveSample('Example_3','100%','300')}}</p>
<h3 id="Example_4">Example 4</h3>
<p>这个示例中,P 元素的 <code>position</code> 为 <code>fixed</code>,所以它的包含块就是初始包含块(在屏幕上,也就是 viewport)。这样的话,P 元素的尺寸大小,将会随着浏览器窗框大小的变化,而变化。</p>
<div class="hidden">
<pre class="brush: html notranslate" dir="ltr"><body>
<section>
<p>This is a paragraph!</p>
</section>
</body>
</pre>
</div>
<pre class="brush: css notranslate" dir="ltr">body {
background: beige;
}
section {
width: 400px;
height: 480px;
margin: 30px;
padding: 15px;
background: lightgray;
}
p {
position: fixed;
width: 50%; /* == (50vw - (width of vertical scrollbar)) */
height: 50%; /* == (50vh - (height of horizontal scrollbar)) */
margin: 5%; /* == (5vw - (width of vertical scrollbar)) */
padding: 5%; /* == (5vw - (width of vertical scrollbar)) */
background: cyan;
}
</pre>
<p>{{EmbedLiveSample('Example_4','100%','300')}}</p>
<h3 id="Example_5">Example 5</h3>
<p>这个示例中,P 元素的 <code>position</code> 为 <code>absolute</code>,所以它的包含块是 <code><section></code>,也就是距离它最近的一个 <code>transform</code> 值不为 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">none</span></font> 的父元素。</p>
<div class="hidden">
<pre class="brush: html notranslate" dir="ltr"><body>
<section>
<p>This is a paragraph!</p>
</section>
</body>
</pre>
</div>
<pre class="brush: css notranslate" dir="ltr">body {
background: beige;
}
section {
transform: rotate(0deg);
width: 400px;
height: 160px;
background: lightgray;
}
p {
position: absolute;
left: 80px;
top: 30px;
width: 50%; /* == 200px */
height: 25%; /* == 40px */
margin: 5%; /* == 20px */
padding: 5%; /* == 20px */
background: cyan;
}
</pre>
<p>{{EmbedLiveSample('Example_5','100%','300')}}</p>
<h2 id="另见">另见</h2>
<ul>
<li>{{css_key_concepts}}</li>
<li>{{cssxref("all")}} 属性可将所有 CSS 声明重置为它所指定的状态</li>
</ul>
|