Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/BlockLayout.md

Issue 2925273007: [LayoutNG] A little bit of documentation on margin collapsing. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Block Layout #
2
3 This document can be viewed in formatted form [here](https://chromium.googlesour ce.com/chromium/src/+/master/third_party/WebKit/Source/core/layout/ng/FlowLayout .md).
atotic 2017/06/10 00:26:51 s/FlowLayout/BlockLayout
ikilpatrick 2017/06/12 22:58:39 Done.
4
5 ## Floats ##
6
7 TODO.
8
9 ## An introduction to margin collapsing ##
10
11 A simple way to think about margin collapsing is that it takes the maximum margi n between two
12 elements. For example:
13
14 ```html
15 <!-- The divs below are 20px apart -->
16 <div style="margin-bottom: 10px;">Hi</div>
17 <div style="margin-top: 20px;">there</div>
18 ```
19
20 This is complicated by _negative_ margins. For example:
21
22 ```html
23 <!-- The divs below are 10px apart -->
24 <div style="margin-bottom: 20px;">Hi</div>
25 <div style="margin-top: -10px;">there</div>
26
27 <!-- The divs below are -20px apart -->
28 <div style="margin-bottom: -20px;">Hi</div>
29 <div style="margin-top: -10px;">there</div>
30 ```
31
32 The rule here is: `max(pos_margins) + min(neg_margins)`. This rule we'll refer t o as the _margin
33 collapsing rule_. If this only happened between top level elements it would be p retty simple,
34 however consider the following:
35
36 ```html
37 <!-- The top-level divs below are 10px apart -->
atotic 2017/06/10 00:26:51 It'd be clearer if there was only 1 way to get mat
ikilpatrick 2017/06/12 22:58:38 Done.
38 <div style="margin-bottom: 10px">
39 <div style="margin-bottom: -20px">
40 <div style="margin-bottom: 20px">Hi</div>
41 </div>
42 </div>
43 <div style="margin-top: 30px">
44 <div style="margin-top: -10px">there</div>
45 </div>
46 ```
47
48 In the above example as there isn't **anything** separating the edges of two fra gments the margins
dgrogan 2017/06/12 18:54:40 Could you add a parenthetical after **anything** t
ikilpatrick 2017/06/12 22:58:39 Done.
49 stack together. There are known as **adjoining margins**. If we apply our formu la to the above we
50 get: `max(10, 20, 30) + min(-20, -10) = 10`.
51
52 A useful concept is a **margin strut**. This is a pair of margins consisting of one positive and one
53 negative margin.
54
55 A margin strut allows us to keep track of the largest positive and smallest nega tive margin. E.g.
56 ```cpp
57 struct MarginStrut {
58 LayoutUnit pos_margin;
59 LayoutUnit neg_margin;
60
61 void Append(LayoutUnit margin) {
62 if (margin < 0)
63 neg_margin = std::min(margin, neg_margin);
64 else
65 pos_margin = std::max(margin, pos_margin);
66 }
67
68 LayoutUnit Sum() { return pos_margin + neg_margin; }
69 }
70 ```
71
72 A naïve algorithm for the above case would be to _bubble_ up margins. For exampl e each fragment
dgrogan 2017/06/12 18:54:40 Which "above case" do you mean? I suspect the adjo
ikilpatrick 2017/06/12 22:58:38 Done.
73 would have a **margin strut** at the block-start and block-end edge. If the chil d fragment was
74 **adjoining** to its parent, you simply keep track of the margins by calling `Ap pend` on the margin
dgrogan 2017/06/12 18:54:40 Could you say which of the 4 margin struts (block-
ikilpatrick 2017/06/12 22:58:38 Done? - added example code for bubbling. PTAL
75 strut.
76
77 When it comes time to collapse the margins you can use the margin collapsing rul e, e.g.
78 ```cpp
79 MarginStrut s1 = fragment1.block_end_margin_strut;
80 MarginStrut s2 = fragment2.block_start_margin_strut;
81 LayoutUnit distance =
82 std::max(s1.pos_margin, s2.pos_margin) +
83 std::min(s1.neg_margin, s2.neg_margin);
84 ```
85
86 This would be pretty simple - however it doesn't work. As we discussed in the fl oats section a
87 _child_ will position _itself_ within the BFC. If we did margin collapsing this way way we'd create
dgrogan 2017/06/12 18:54:40 "way way"
ikilpatrick 2017/06/12 22:58:39 Done.
88 a circular dependency between layout and positioning. E.g. we need to perform la yout in order to
89 determine the block-start margin strut, which would allow us to position the fra gment, which would
90 allow us to perform layout.
91
92 We **invert** the problem. A fragment now only produces an _end_ margin strut. T he _start_ margin
93 strut becomes an input as well as where the margin strut is currently positioned within the BFC.
94 For example:
95
96 ```cpp
97 Fragment* Layout(LogicalOffset bfc_estimate, MarginStrut input_strut) {
kojii 2017/06/10 05:12:13 Is "bfc_estimate" the "offset to BFC without the l
ikilpatrick 2017/06/12 22:58:38 Thats correct, another way of thinking about this
98 MarginStrut curr_strut = input_strut;
99 LogicalOffset curr_bfc_estimate = bfc_estimate;
100
101 // We collapse the margin strut which allows us to compute our BFC offset if
102 // we have border or padding. I.e. we don't have an adjoining margin.
103 if (border_padding.block_start) {
104 curr_bfc_estimate += curr_strut.Sum();
105 curr_strut = MarginStrut();
106
107 fragment_builder.SetBfcOffset(curr_bfc_estimate);
108 curr_bfc_estimate += border_padding.block_start;
109 }
110
kojii 2017/06/10 05:12:13 IIUC, up until here is common to all algorithms, a
ikilpatrick 2017/06/12 22:58:38 This is only for block and inline, but yeah.
111 for (const auto& child : children) {
112 curr_strut.Append(child.margins.block_start);
113 const auto* fragment = child.Layout(curr_strut);
kojii 2017/06/10 05:12:13 child.Layout(curr_bfc_estimate, curr_strut) ?
ikilpatrick 2017/06/12 22:58:38 Done.
114
115 curr_strut = fragment->end_margin_strut;
116 curr_strut.Append(child.margins.block_end);
117
118 curr_bfc_estimate = fragment->BfcOffset() + fragment->BlockSize();
119 }
120
121 fragment_builder.SetEndMarginStrut(curr_strut);
122
123 return fragment_builder.ToFragment();
124 }
125 ```
126
127 It isn't immediately obvious that this works, but if you try and work through an example manually,
128 it'll become clearer.
129
130 There are lots of different things which can "resolve" the BFC offset of an elem ent. For example
131 inline content (text, atomic inlines), border and padding, if a child _might_ be affected by
132 clearance.
133
134 ## Zero block-size fragments ##
135
136 TODO.
137
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698