aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/guide/css/visual_formatting_model/index.html
blob: 7a5de3590927ed06d56d5690f54aa8a12d94a29a (plain)
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
---
title: Модель визуального форматирования
slug: Web/Guide/CSS/Visual_formatting_model
translation_of: Web/CSS/Visual_formatting_model
---
<p>{{CSSRef}}</p>

<p><span class="seoSummary"><em>Модель визуального форматирования </em>CSS<em> </em> - это алгоритм, используемый для обработки документа и его визуального отображения. Это базовая концепция CSS</span>. Модель визуального форматирования задаёт трансформацию каждого элемента в документе и создаёт ноль, одну или несколько боксов, согласно <a href="https://developer.mozilla.org/ru/docs/Web/CSS/box_model">боксовой модели CSS</a>. Расположение (layout) каждого бокса определяется:</p>

<ul>
 <li>размерами бокса: точно заданными или заданными ограничениями. Если размеры не заданы, это правило игнорируется;</li>
 <li>типом бокса: inline, inline-level, atomic inline-level, block box;</li>
 <li><a href="https://developer.mozilla.org/en-US/docs/CSS/Box_positioning_scheme">схемой позиционирования</a>: normal flow, float или absolute;</li>
 <li>другими элементами дерева: дочерними и соседними;</li>
 <li>размерами и расположением окна просмотра ({{glossary("viewport")}});</li>
 <li>внутренними размерами содержащихся изображений;</li>
 <li>другой внешней информацией.</li>
</ul>

<p>Бокс отображается относительно краев <em>содержащего его блока. </em>Как правило, бокс определяет родительский блок для своих потомков. Однако, стоит заметить, что бокс не ограничен содержащим его блоком. Такое поведение слоев, выходящих за пределы своих содержащих блоков, называется <em>переполенинем</em> (<em>overflow).</em></p>

<h2 id="Генерация_бокса">Генерация бокса</h2>

<p>Генерация бокса - часть алгоритма модели визуального форматирования, процедура, генерирующая блоки из элементов. Различные типы боксов определяют различное поведение в контексте форматирования. Тип бокса зависит от свойства CSS {{ cssxref("display") }}.</p>

<h3 id="Блочные_эклементы_и_блок-боксы">Блочные эклементы и блок-боксы</h3>

<p>Говорят, что элемент является блочным, когда вычисленное значение его CSS свойства {{ cssxref("display") }} равно: <code>block</code><code>list-item</code>, или <code>table</code>. Блочный элемент визуально форматируется как блок (например, параграф), предназначенный для вертикальной компоновки (в столбик).</p>

<p>Каждый элемент блочного уровня участвует в <a href="/ru/docs/CSS/block_formatting_context" title="block formatting context">контексте блочного форматирования</a>. Каждый элемент блочного уровня генерирует как миниум один блок-бокс, названный <em>главным блок-боксом</em>. Некоторые элементы, например, такие как list-item, создают дополнительные боксы для хранения маркеров и других типографических элементов, содержащихся в list item. Большинство блочных элементов генерирует только один, главный блок-бокс.</p>

<p>Главный блок-бокс содержит сгенериованные боксы-потомки и сгенериованный контекст. Он так же будет боксом, участвующем в <a href="/en-US/docs/CSS/Positioning_scheme" title="CSS/Positioning scheme">схеме позиционирования</a>.</p>

<p><img alt="venn_blocks.png" class="internal lwrap" src="/@api/deki/files/5995/=venn_blocks.png" style="float: left;">Элемент блочного уровня так же может быть блоком-контейнером. Блок-контейнер - это блок, который содержит либо только другие элементы блочного уровня, либо создаёт <a href="/en-US/docs/CSS/Inline_formatting_context" title="CSS/Inline formatting context">контекст инлайнового форматирования</a> и, таким образом, содержит только инлайновые элементы.</p>

<p>Важно понимать, что понятие блочного элемента и понятие блочного контейнера - это разные вещи. Первое описывает, как блок будет себя вести по отношению к своему родителю и своим соседям/братьям. А второе - описывает, как блок будет взаимодействовать со своими потомками. Некоторые элементы блочного уровня, например, таблицы, не являются содержащими блоками. И наоборот, некоторые блоки-контейнеры, например, ячейки таблицы, не являются элементами блочного уровня.</p>

<p>Элементы блочного уровня, которые так же являются контейнерами, называются <em>блок-боксами</em>.</p>

<h4 id="Анонимные_блок-боксы">Анонимные блок-боксы</h4>

<p>В некоторых случаях алгоритм визуального форматирования  вынужден добавлять дополнительные боксы. Так как эти боксы невозможно как-то проименовать и к ним невозможно применить css-селекторы, поэтому эти боксы называют <em>анонимными</em>.</p>

<p>Из-за того, что к анонимным боксам невозможно применить селекторы, их невозможно изменить с помощью таблицы стилей. Это значит, что все наследуемые CSS свойства для них будут иметь значение <code>inherit</code>, а все ненаследуемые свойства будут иметь значение <code>initial</code>.</p>

<p>Блоки-контейнеры содержат либо только инлайн-боксы, либо только элементы блочного уровня. Но, как правило, документ содержит и те и другие. В этом случае анонимные блок-боксы создаются вокруг примыкающих к ним инлайн-боксов.</p>

<h3 id="Пример">Пример</h3>

<p>Возьмём следующий HTML код (со стилями по умолчанию, то есть элементы {{ HTMLElement("div") }} и {{ HTMLElement("p") }} имеют значение <code>display:block</code> :</p>

<pre class="syntaxbox"><code>&lt;div&gt;Some inline text &lt;p&gt;followed by a paragraph&lt;/p&gt; followed by more inline text.&lt;/div&gt;</code></pre>

<p>Здесь создались два анонимных блока: один для текста перед параграфом (<code>Some inline text</code>), и второй для текста после параграфа (<code>followed by more inline text.</code>). И у нас получилась вот такая структура:</p>

<p style="text-align: center;"><img alt="anonymous_block-level_boxes.png" class="default internal" src="https://developer.mozilla.org/@api/deki/files/5996/=anonymous_block-level_boxes.png"></p>

<p>Выглядеть это будет так:</p>

<pre class="line-numbers language-html"><code class="language-html">Some inline text
followed by a paragraph
followed by more inline text.</code></pre>

<p>В отличие от параграфа {{ HTMLElement("p") }}, Web разработчик не может напрямую контролировать стили этих двух анонимных боксов. Те свойства, которые наследуются, берут своё значение от элемента {{ HTMLElement("div") }}, например {{ cssxref("color") }}, определяющий цвет текста. А другие значения, ненаследуемые, устанавливаются в значение <code>initial</code>. Например, у них не будет своего свойства {{ cssxref("background-color") }}, он всегда будет в состоянии "прозрачный" (transparent), значении по умолчанию для этого свойства, и поэтому будет видно тот background, который установлен у элемента <code>&lt;div&gt;</code>. А вот для параграфа <code>&lt;p&gt; </code>можно установить своё свойство цвета фона. Таким образом, эти два анонимных бокса будут иметь один и тот же цвет текста.</p>

<p>Ещё один случай, который приводит к созданию анонимных блок-боксов, это случай, когда инлайн-бокс содержит один или несколько блок-боксов. В этом случае элемент, содержащий блок-боксы, делится на два инлайн-бокса - один перед, а второй после блок-бокса. И потом инлайн-элементы перед и после блок-бокса дополнительно заключаются в <em>анонимные блок-боксы</em>. Таким образом блок-бокс становится соседом для анонимных блок-боксов, содержащих инлайн-элементы.</p>

<p>Если есть несколько блок-боксов, идущих подряд, без инлайн-элементов между ними, то анонимные блок-боксы создаются только перед и после такого набора блок-боксов.</p>

<h3 id="Пример_2">Пример</h3>

<p>Возьмём следующий HTML код, где установим для элемента {{ HTMLElement("p") }} значение <code>display:inline</code> и для элемента {{ HTMLElement("span") }} значение <code>display:block</code> :</p>

<pre class="syntaxbox"><code>&lt;p&gt;Some &lt;em&gt;inline&lt;/em&gt; text &lt;span&gt;followed by a paragraph&lt;/span&gt; followed by more inline text.&lt;/p&gt;</code></pre>

<p>Создадутся два анонимных блок-бокса, один для текста перед элементом span (<code>Some <em>inline</em> text</code>) и один для текста после него (<code>followed by more inline text</code>), и у нас получится вот такая структура:</p>

<p style="text-align: center;"><img alt="" src="https://mdn.mozillademos.org/files/13625/anonymous_block_box_break.png" style="height: 137px; width: 597px;"></p>

<p>Выглядеть она будет так:</p>

<pre class="line-numbers language-html"><code class="language-html">Some inline text
followed by a paragraph
followed by more inline text.</code></pre>

<h3 id="Элементы_инлайн-уровня_и_инлайн-боксы">Элементы инлайн-уровня и инлайн-боксы</h3>

<p>Элементы, которые называются <em>элементами инлайн-уровня</em> - это элементы, у которых вычисленное значение CSS свойства {{ cssxref("display") }} установлено в : <code>inline</code>, <code>inline-block</code> или <code>inline-table</code>. Визуально они не представляют собой какие-то отдельные блоки, но они они распологаются в одну линию с другим контентом инлайн-уровня. Например, содержание параграфа, с различным форматированием, таким как подчёркивание или картинка, состоит из элементов инлайн-уровня.</p>

<p><img alt="venn_inlines.png" class="internal lwrap" src="https://developer.mozilla.org/@api/deki/files/6008/=venn_inlines.png" style="float: left;"></p>

<div class="warning">
<p>Эта диаграмма использует устаревшую терминологию; см. примечания ниже. К тому же она некорректна, потому что жёлтый эллипс справа по определению должен быть изображён одинаковым по размеру с эллипсом слева или больше него  (it could be a mathematical superset), потому что в спецификации сказано: "Элементв инлайн-уровня генерируют боксы инлайн-уровня, участвующие в форматировании инлайн-уровня", см. CSS 2.2, глава 9.2.2</p>
</div>

<p>Элементы инлайн-уровня создают <em>боксы инлайн-уровня</em>, которые определены как боксы, участвующие в <a href="https://developer.mozilla.org/en-US/docs/CSS/Inline_formatting_context" title="CSS/Inline formatting context">контексте форматирования инлайн-уровня</a>. <em>Inline boxes</em> are both inline-level boxes and boxes, whose contents participate in their container's inline formatting context. This is the case, for example, for all non-replaced boxes with <code>display:inline</code>. Inline-level boxes, whose contents do not participate in an inline formatting context, are called <em>atomic inline-level boxes</em>. These boxes, generated by replaced inline-level elements or by elements with a calculated {{ cssxref("display") }} value of <code>inline-block</code> or <code>inline-table</code>, are never split into several boxes, as is possible with inline boxes.</p>

<div class="note"><strong>Note:</strong> Initially, atomic inline-level boxes were called atomic inline boxes. This was unfortunate, as they are <strong>not</strong> inline boxes. This was corrected in an erratum to the spec. Nevertheless, you can harmlessly read atomic inline-level box each time you meet atomic inline box in the literature, as this is only a name change.</div>

<div class="note">Atomic inline boxes cannot be split into several lines in an inline formatting context.
<div style="-moz-column-width: 30em;">
<pre class="line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>style</span><span class="punctuation token">&gt;</span></span><span class="style token"><span class="language-css token">
  <span class="selector token">span</span> <span class="punctuation token">{</span>
    <span class="property token">display</span><span class="punctuation token">:</span>inline<span class="punctuation token">;</span> <span class="comment token">/* default value*/</span>
  <span class="punctuation token">}</span>
</span></span><span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>style</span><span class="punctuation token">&gt;</span></span>
<span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>div</span><span class="language-css style-attr token"><span class="attr-name token"> <span class="attr-name token">style</span></span><span class="punctuation token">="</span><span class="attr-value token"><span class="property token">width</span><span class="punctuation token">:</span><span class="number token">20</span><span class="token unit">em</span><span class="punctuation token">;</span></span><span class="punctuation token">"</span></span><span class="punctuation token">&gt;</span></span>
   The text in the span <span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>span</span><span class="punctuation token">&gt;</span></span>can be split in several
   lines as it<span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>span</span><span class="punctuation token">&gt;</span></span> is an inline box.
<span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>div</span><span class="punctuation token">&gt;</span></span></code></pre>
</div>
</div>

<p>which leads to:</p>

<div style="width: 20em;">The text in the span <span>can be split into several lines as it</span> is an inline box.</div>

<pre class="line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>style</span><span class="punctuation token">&gt;</span></span><span class="style token"><span class="language-css token">
  <span class="selector token">span</span> <span class="punctuation token">{</span>
    <span class="property token">display</span><span class="punctuation token">:</span>inline-block<span class="punctuation token">;</span>
  <span class="punctuation token">}</span>
</span></span><span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>style</span><span class="punctuation token">&gt;</span></span>
<span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>div</span><span class="language-css style-attr token"><span class="attr-name token"> <span class="attr-name token">style</span></span><span class="punctuation token">="</span><span class="attr-value token"><span class="property token">width</span><span class="punctuation token">:</span><span class="number token">20</span><span class="token unit">em</span><span class="punctuation token">;</span></span><span class="punctuation token">"</span></span><span class="punctuation token">&gt;</span></span>
   The text in the span <span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>span</span><span class="punctuation token">&gt;</span></span>cannot be split in several
   lines as it<span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>span</span><span class="punctuation token">&gt;</span></span> is an inline-block box.
<span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>div</span><span class="punctuation token">&gt;</span></span></code></pre>

<div class="note">
<div style="-moz-column-width: 30em;">
<p>which leads to:</p>

<div style="width: 20em;">The text in the span <span style="display: inline-block;">cannot be split into several lines as it</span> is an inline-block box.</div>
</div>
</div>

<h4 id="Anonymous_inline_boxes">Anonymous inline boxes</h4>

<p>As for block boxes, there are a few cases where inline boxes are created automatically by the CSS engine. These inline boxes are also anonymous as they cannot be named by selectors; they inherit the value of all inheritable properties, setting it to <code>initial</code> for all others.</p>

<p>The most common case where an anonymous inline box is created, is when some text is found as a direct child of a block box creating an inline formatting context. In that case, this text is included in the largest possible anonymous inline box. Also, space content, which would be removed by the behavior set in the {{ cssxref("white-space") }} CSS property, does not generate anonymous inline boxes because they would end empty.</p>

<div class="note">Example TBD</div>

<h3 id="Other_types_of_boxes">Other types of boxes</h3>

<h4 id="Line_boxes">Line boxes</h4>

<p><em>Line boxes</em> are generated by the <a href="https://developer.mozilla.org/en-US/docs/CSS/Inline_formatting_context" title="block formatting context">inline formatting context</a> to represent a line of text. Inside a block box, a line box extends from one border of the box to the other. When there are <a href="https://developer.mozilla.org/en-US/docs/CSS/float" title="float">floats</a>, the line box starts at the rightmost border of the left floats and ends at the leftmost border of the right floats.</p>

<p>These boxes are technical, and Web authors do not usually have to bother with them.</p>

<h4 id="Run-in_boxes">Run-in boxes</h4>

<p><em>Run-in boxes</em>, defined using <code>display:run-in</code>, are boxes that are either block boxes or inline boxes, depending on the type of the following box. They can be used to create a title that runs inside its first paragraph when possible.</p>

<div class="note"><strong>Note:</strong> Run-in boxes were removed from the CSS 2.1 standard, as they were insufficiently specified to allow for interoperable implementation. They may reappear in CSS3, but meanwhile, are considered <em>experimental</em>. They should not be used in production.</div>

<h4 id="Model-induced_boxes">Model-induced boxes</h4>

<p>Besides the inline and block formatting contexts, CSS specifies several additional <em>content models</em> that may be applied to elements. These additional models, used to describe specific layouts, may define additional box types:</p>

<ul>
 <li>The <a href="https://developer.mozilla.org/en-US/docs/CSS/table-layout" title="table-layout">table content model</a> may create a <em>table wrapper box</em> and a <em>table box</em>, but also specific boxes like <em>caption boxes</em>.</li>
 <li>The <a href="https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_multi-column_layouts" title="Using CSS multi-column layouts">multi-column content model</a> may create <em>column boxes</em> between the container box and the content<em>.</em></li>
 <li>The experimental grid, or flex-box content models, also create additional types of boxes.</li>
</ul>

<h4 id="Positioning_schemes">Positioning schemes</h4>

<p>Once boxes are generated, the CSS engine needs to position them on the layout. To do that, it uses one of the following algorithms:</p>

<ul>
 <li>The <em>normal flow</em> - positions each box one after the other.</li>
 <li>The <em>floats</em> algorithm - extracts the box from the normal flow and put it to the side of the containing box.</li>
 <li>The <em>absolute positioning</em> scheme - positions a box within an absolute coordinate system that is established by its containing element. An absolutely positioned element can cover other elements.</li>
</ul>

<h3 id="Normal_flow">Normal flow</h3>

<p>In the <em>normal flow</em>, boxes are laid out one after the other. In a block formatting context, they are laid out vertically; in an inline formatting context, they are laid out horizontally. The normal flow is triggered when the CSS {{ cssxref("position") }} is set to the value <code>static</code> or <code>relative</code>, and if the CSS {{ cssxref("float") }} is set to the value <code>none</code>.</p>

<h3 id="Example">Example</h3>

<div class="note">When in the normal flow, in a block formatting context, boxes are laid vertically one after the other out.<br>
<br>
When in the normal flow, in an inline formatting context, boxes are laid horizontally one after the other out.</div>

<div class="note">
<p>There are two sub-cases of the normal flow: static positioning and relative positioning:</p>

<ul>
 <li>In <em>static positioning</em>, triggered by the value <code>static</code> of the {{ cssxref("position") }} property, the boxes are drawn at the exact position defined by the normal flow layout.</li>
 <li>In <em>relative</em><em> positioning</em>, triggered by the value <code>relative</code> of the {{ cssxref("position") }} property, the boxes are drawn with an offset defined by the {{ cssxref("top") }}, {{ cssxref("bottom") }}, {{ cssxref("left") }} and {{ cssxref("right") }} CSS properties.</li>
</ul>
</div>

<h3 id="Floats">Floats</h3>

<p>In the <em>float positioning scheme</em>, specific boxes (called <em>floating boxes</em> or simply <em>floats)</em> are positioned at the beginning, or end of the current line. This leads to the property that text (and more generally anything within the normal flow) flows along the edge of the floating boxes, except if told differently by the {{ cssxref("clear") }} CSS property.</p>

<p>The float positioning scheme for a box is selected, by setting the {{ cssxref("float") }} CSS property on that box to a value different than <code>none</code> and {{ cssxref("position") }} to <code>static</code> or <code>relative</code>. If {{ cssxref("float") }} is set to <code>left</code>, the float is positioned at the beginning of the line box. If set to <code>right</code>, the float is positioned at the end of the line box. In either case, the line box is shrunk to fit alongside the float.</p>

<h3 id="Absolute_positioning">Absolute positioning</h3>

<p>In the <em>absolute positioning scheme</em>, boxes are entirely removed from the flow and don't interact with it at all. They are positioned relative to their <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/All_About_The_Containing_Block" title="CSS/Containing block">containing block</a> using the {{ cssxref("top") }}, {{ cssxref("bottom") }}, {{ cssxref("left") }} and {{ cssxref("right") }} CSS properties.</p>

<p>An element is absolutely positioned if the {{ cssxref("position") }} is set to <code>absolute</code> or <code>fixed</code>.</p>

<p>With a <em>fixed positioned element</em>, the containing block is the viewport. The position of the element is absolute within the viewport. Scrolling does not change the position of the element.</p>