-
Notifications
You must be signed in to change notification settings - Fork 790
Expand file tree
/
Copy pathOverview.src.html
More file actions
985 lines (801 loc) · 41.6 KB
/
Overview.src.html
File metadata and controls
985 lines (801 loc) · 41.6 KB
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
10BC0
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
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html><head><title>Flexible Box Layout Module</title>
<link rel="stylesheet" type="text/css" href="../default.css">
<style type="text/css">
p { margin: .5em 0; }
dd > p { text-indent: 0; }
a > b { font-weight: normal; color: #800; }
</style>
<link rel="stylesheet" type="text/css" href="http://www.w3.org/StyleSheets/TR/W3C-ED"> <!-- TODO: change before build -->
</head><body>
<div class="head">
<!--logo-->
<h1 id="head-box-flexible">Flexible Box Layout Module</h1>
<h2 class="no-num no-toc" id="w3c-working">[LONGSTATUS], [DATE]</h2>
<dl>
<dt>This version:
<dd><!-- <a href="http://www.w3.org/TR/[YEAR]/WD-[SHORTNAME]-[CDATE]/">http://www.w3.org/TR/[YEAR]/WD-[SHORTNAME]-[CDATE]/</a></dd> -->
<a href="http://dev.w3.org/csswg/[SHORTNAME]/">http://dev.w3.org/csswg/[SHORTNAME]/</a>
<dt>Latest version:
<dd><a href="http://www.w3.org/TR/css3-flexbox/">http://www.w3.org/TR/css3-flexbox/</a>
<dt>Previous version:
<dd><a href="http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/">http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/</a>
<dt>Editors:
<dd>Tab Atkins Jr. <a href="mailto:jackalmage@gmail.com">jackalmage@gmail.com</a>
<dd>Alex Mogilevsky <a href="mailto:alexmog@microsoft.com">alexmog@microsoft.com</a>
<dd>L. David Baron, Mozilla Corporation, <a href="mailto:dbaron@dbaron.org">dbaron@dbaron.org</a>
<dt>Authors and former editors:
<dd>Neil Deakin, Mozilla Corporation, <a href="mailto:enndeakin@gmail.com">enndeakin@gmail.com</a>
<dd>Ian Hickson, formerly of Opera Software, <a href="mailto:ian@hixie.ch">ian@hixie.ch</a>
<dd>David Hyatt, Apple, <a href="mailto:hyatt@apple.com">hyatt@apple.com</a>
</dl>
<!--copyright-->
<hr title="Separator for header">
</div>
<h2 class="no-num no-toc" id="abstract">Abstract</h2>
<p>The draft describes a CSS box model optimized for interface design.
It provides an additional layout system alongside the ones already in
CSS. [[!CSS21]] In this new box model, the children of a box are
laid out either horizontally or vertically, and unused space can be
assigned to a particular child or distributed among the children by
assignment of "flex" to the children that should expand.
Nesting of these boxes (horizontal inside vertical, or vertical inside
horizontal) can be used to build layouts in two dimensions. This
model is based on the box model in the XUL user-interface language
used for the user interface of many Mozilla-based applications
(such as Firefox).</p>
<h2 class="no-num no-toc" id="status">Status of this document</h2>
<!--status-->
<h2 class="no-num no-toc" id="table">Table of contents</h2>
<!--toc-->
<!-- ====================================================================== -->
<h2 id="overview">
Overview</h2>
<p>CSS 2.1 defined four layout modes, algorithms which determine the size and
position of boxes based on their relationships with their sibling and ancestor
boxes: block layout, designed for laying out documents and simple applications,
inline layout, designed for laying out text,
table layout, designed for laying out information in a tabular format, and
positioned layout, designed for very explicit positioning without much regard
for other elements in the document. This module introduces a new layout mode,
flexbox layout, which is designed for laying out more complex applications and
webpages.</p>
<p>Flexbox layout is superficially similar to block layout. It lacks many of
the more complex text or document-formatting properties that can be used in
block layout, such as 'float' and 'columns', but in return it gains more simple
and powerful tools for aligning its contents in ways that webapps and complex
web pages often need. The contents of a flexbox can be laid out in any direction,
can have their order swapped around dynamically, and can "flex" their sizes
and positions to respond to the available space.</p>
<p>Similar to other layout modes such as table layout, a flexbox acts like a
block when placed into other layout modes. Inline flexboxes can also be declared,
which act like inline-blocks.</p>
<p>Block-level and atomic inline-level children of the flexbox are referred
to as <dfn>flexbox item</dfn>s in this specification. Inline children are
wrapped in anonymous blocks, and these anonymous blocks are also <i>flexbox item</i>s.</p>
<div class="example">
<p>For example:</p>
<pre class=html>
<p style="width: 400px; display: flexbox;">
<button style="width: 200px;">Child 1</button>
<button style="width: 100px;">Child 2</button>
</p>
</pre>
<p>In this example, the first button is 200 pixels wide and the second button is
100 pixels wide. As the flexbox is 400 pixels wide, there is extra space left over
which is placed after the two buttons but inside the flexbox. The placement of this
extra space may be modified using the various flex properties described in the next
sections. Neither the height of the buttons nor the height of the flexbox are specified,
so the height is computed intrinsically from the content. In this case, the buttons
will be the height needed to display the label and button border, and the flexbox will
also be this height plus any margins around the buttons.</p>
</div>
<!-- ====================================================================== -->
<h2 id=display-flexbox>
New values for 'display' property</h2>
<table class="propdef">
<tbody>
<tr>
<th>Name:
<td>display
<tr>
<th>New value:
<td>flexbox | inline-flexbox
</tbody>
</table>
<p class=issue>ISSUE: The proliferation of "inline-*" display values is untenable and
restrictive. Table cells should be able to use the flexbox layout mode for
their contents, for example, rather than being forced to use block layout.
It's expected that this will be fixed by splitting the 'display' property
into subproperties controlling how the element formats its contents ('display-inside')
and how it reacts to its surroundings ('display-outside'). Once that occurs,
this section will instead describe a single new 'display-inside' value that
triggers flexbox layout.</p>
<p>You can declare that an element is a flexbox, and thus should use flexbox
layout, by setting the 'display' property on the element to the value
''flexbox''.</p>
<p>The special behaviors of a flexbox, such as flexing and reordering children,
only apply to <i>flexbox item</i>s. All block-level or atomic inline-level
children of the flexbox are <i>flexbox item</i>s. Contiguous runs of non-replaced
inline children are wrapped in an anonymous block-level box, which is itself
a <i>flexbox item</i>.
<p class=note>Note that out-of-flow elements like absolutely positioned elements
leave behind a 'placeholder' inline element in their original position in the
document <span class=issue>(ISSUE: This will be defined in Positioned Layout.)</span>
Floats are also out-of-flow, but children of flexboxes can't float.
<span class=issue>(ISSUE: Should this restriction exist, or should I just wrap
floats in the anonymous boxes like other inlines?)</span> It is recommended
that authors avoid creating inline flexbox children, as the anonymous block
that is generated can't be targetted and controlled by the various flexbox
properties.</p>
<div class=issue>
<p>ISSUE: Need to reword how flexbox items are determined. The
algorithm clearly operates on the box tree, as it creates anonymous boxes,
but it needs to operate kinda on elements. In particular, an inline child
element that contains a block should be wrapped in a single flexbox item, rather
than wrapping the pre-block and post-block parts in separate anonymous blocks
and then the block inside being a flexbot item on its own.</p>
<p>Whatever wording is used here should be shared with the table-fixup
algorithm, because it's essentially the identical problem. Perhaps we can
have it operate on the element-tree and create anonymous pseudo-elements,
similar to how ::outside would work? Pseudoelements don't interfere with
normal selectors, so this would let us insert wrappers that work correctly
without screwing up the way selectors work.</p>
</div>
<p>A flexbox item creates a new BFC. The margins of a flexbox item
do not collapse with any other margin. Flexboxes "shrinkwrap" their contents
by default (when their 'width' or 'height' properties are ''auto''), similar
to tables or floats.</p>
<p>Setting ''display:flexbox'' on an element forces it to use a new layout
algorithm, and so some properties that were designed with the assumption of
block layout don't make sense in a flexbox context. In particular:</p>
<ul>
<li>all of the 'column-*' properties in the Multicol module compute to their initial
values on a flexbox ('break-before', 'break-inside', and 'break-after' are still
valid on a flexbox).</li>
<li>'float' and 'clear' compute to their initial values on a flexbox item</li>
<li>'vertical-align' has no effect on a flexbox item</li>
<li class=issue>[Others?]</li>
</ul>
<!-- ====================================================================== -->
<h2 id=flex-direction>
Flexbox Direction: the 'flex-direction' property</h2>
<table class=propdef>
<tbody>
<tr>
<th>Name:
<td><dfn>flex-direction</dfn>
<tr>
<th>Values:
<td>lr | rl | tb | bt | inline | inline-reverse | block | block-reverse
<tr>
<th>Initial:
<td>inline
<tr>
<th>Applies To:
<td>flexboxes
<tr>
<th>Inherited:
<td>no
<tr>
<th>Computed Value:
<td>lr | rl | tb | bt (See text)
<tr>
<th>Media:
<td>visual
</tbody>
</table>
<p>The 'flexbox-direction' property specifies how <i>flexbox item</i>s
are placed in the flexbox. A value of ''lr'' means that
the first flexbox item is placed against the left edge of the flexbox, with
later children placed immediately to the right of the preceding flexbox item.
A value of ''rl'' is the same, but with the initial flexbox item
placed against the right edge of the flexbox and later children placed to the
left. Both of these values mean that the flexbox is a <dfn>horizontal
flexbox</dfn>. A value of ''tb'' means that the first flexbox
child is placed against the top edge of the flexbox, with later children placed
immediately below it, while ''bt'' means the first child is placed
against the bottom edge of the flexbox, with later children placed immediately
above it. Both of these values mean that the flexbox is a <dfn>vertical
flexbox</dfn>.</p>
<p>A value of ''inline'' computes to one of ''lr'', ''rl'', ''tb'', or ''bt'',
depending on the direction and block-flow of the flexbox: if the start side of
the flexbox is the left side, ''inline'' must compute to ''lr''; similarly, if
the start side of the flexbox is the right, top, or bottom side, ''inline''
must compute to ''rl'', ''tb'', or ''bt'' respectively. ''inline-reverse'',
''block'', and ''block-reverse'' determine their computed value identically to
''inline'', but use the location of the end side, before side, and after side
of the flexbox, respectively.</p>
<div class=example>
<p>A vertical flexbox can be used to emulate the functionality of HTML's
''<center>'' element:</p>
<pre>
<div>
<span>foo foo foo foo</span>
<span>bar bar<br>bar bar</span>
<span>foo foo foo foo foo foo foo foo foo foo foo foo</span>
</div>
<style>
div {
display: flexbox;
flex-direction: tb;
width: 200px;
}
span {
margin: 0 auto;
}
</style>
</pre>
<p><img alt="" src="images/basic-vertical-flexbox.png"></p>
</div>
<p>In the rest of this specification, the direction in which new <i>flexbox item</i>s
are laid out will be referred to as the <dfn>measure direction</dfn> (if a
precise direction is required) or the <dfn>measure axis</dfn> (if only the axis
orientiation is required).</p>
<p>The axis perpendicular to the ''measure axis'' will be refered to as the
<dfn>length axis</dfn>, with the <dfn>length direction</dfn> being
either a line extending from the ''before'' side of the flexbox to the ''after''
side, or from the ''start'' side of the flexbox to the ''end'' side, whichever
would produce a direction parallel to the ''length axis''.</p>
<p>Similarly, the <dfn>inner measure</dfn> is the width of the flexbox item in
a horizontal flexbox, or the height in a vertical flexbox. The <dfn>inner length</dfn>
is the height of the flexbox item in a horizontal flexbox, or the width in a
vertical flexbox.</p>
<!-- ====================================================================== -->
<h2 id=flex-order>
Display Order: the 'flex-order' property</h2>
<p><i>flexbox item</i>s are, by default, displayed and laid out in the same order
as they appear in the source document. The 'flex-order' property may be used
to change this ordering.</p>
<table class=propdef>
<tr>
<th>Name:
<td><dfn>flex-order</dfn>
<tr>
<th>Value:
<td><integer>
<tr>
<th>Initial:
<td>1
<tr>
<th>Applies to:
<td><i>flexbox item</i>s</td>
<tr>
<th>Inherited:
<td>no
<tr>
<th>Computed value:
<td>specified value
<tr>
<th>Media:
<td>visual
</table>
<p class=issue>Maybe name this 'flex-index' instead, to be consistent with 'z-index'.</p>
<p><i>flexbox item</i>s may be assigned to ordinal groups using the 'flex-order'
property. This property is an integer with an initial value of 1.</p>
<p>Ordinal groups control the order in which <i>flexbox item</i>s appear. A flexbox
will lay out its children starting from the lowest numbered ordinal group and
going up. Elements with the same ordinal group are laid out in the order they
appear in the source document.
<div class=example>
<p>This example shows how ordinal groups might be used.</p>
<pre><code>
div { display: flexbox; }
#span1 { flex-order: 2; }
#span3 { flex-order: 2; }
#span4 { flex-order: 1; }
<div>
<span id="span1">span1</span>
<span id="span2">span2</span>
<span id="span3">span3</span>
<span id="span4">span4</span>
</div></code></pre>
<p>The first ordinal group, 1, contains span2 and span4. As span2 does not
specify an ordinal group, it will default to 1. The elements will be displayed
in document order, so span2 will be displayed before span4. The second ordinal
group, 2, contains the remaining two spans. The resulting display order will
be:</p>
<pre><code>span2 span4 span1 span3</code></pre>
</div>
<!-- ====================================================================== -->
<h2 id=flexibility>
Flexibility</h2>
<p>The defining aspect of flexbox layout is the ability to make various lengths
of the <i>flexbox item</i>s flexible. Flexible lengths can be used for the 'width',
'height', 'padding', and 'margin' properties of <i>flexbox item</i>s. A
<dfn>flexible length</dfn> can grow if the flexbox has extra space available,
or shrink if the flexbox would otherwise overflow. The ''flex()'' function
is used to specify a <i>flexible length</i> and it's parameters.</p>
<div class=example>
<p class=issue>TODO: Examples!</p>
</div>
<h3 id=resolving-flexible-lengths>
Resolving Flexible Lengths</h3>
<p>CSS resolves a <i>flexible length</i> into a definite length by first collecting
all the lengths, flexible or inflexible, that will share some space. For example,
for a horizontal flexbox, the lengths of the left and right margins, left and right
borders, left and right paddings, and widths of all <i>flexbox item</i>s share
the width of the flexbox itself. Conversely, each <i title="<i>flexbox item</i>s">flexbox item's</i>
vertical margins, borders, padding, and height individually share the height
of the flexbox.</p>
<div class=figure>
<p class="caption issue">TODO: Diagram showing the relevant lengths
in each axis.</p>
</div>
<p>CSS then sums the <dfn>preflex size</dfn> of the lengths in each set. The
<i>preflex size</i> of an inflexible length is just the length itself. The
<i>preflex size</i> of a flexible length is its <i>preferred size</i>. The
<dfn>preferred size</dfn> defaults to ''0'', and can be set to a different value
with the optional third argument to the ''flex()'' function (defined below).</p>
<p>If the sum of all the <i title="preflex size">preflex sizes</i> is less than
the available width/height of the flexbox, then the difference is split up among all the
<i title="flexible length">flexible lengths</i> with <dfn>positive flexibility</dfn>
(a non-zero value for the first argument to the ''flex()'' function), with the
space divvied up proportionally to the flexibility of each length. If the sum
is greater than the available width/height, then all the
<i title="flexible length">flexible lengths</i> with <dfn>negative flexibility</dfn>
(a non-zero value for the second argument to the ''flex()'' function) shrink
in proportion to their flexibility to try and make the sum equal the available
width/height.</p>
<p>The 'flex-pack' and 'flex-align' properties offer more complex control over
free-space distribution. The precise details of how free space is determined
and assigned to flexible lengths is detailed in a later chapter.</p>
<h3 id=flex-function>
The ''flex()'' function</h3>
<p>The ''flex()'' function is used to specify the parameters of a
<i>flexible length</i>: the <i title="positive flexibility">positive</i>
and <i>negative flexibility</i>, and the <i>preferred size</i>. The syntax
of the ''flex()'' function is:</p>
<pre class=prod>flex( <i title="positive flexibility"><pos-flex></i> [, <i title="negative flexibility"><neg-flex></i> [, <i title="preferred size"><preferred-size></i> ]? ]? )</pre>
<p>The first argument sets the <i>positive flexibility</i> of the length.
It must be a non-negative <number> - anything else is a syntax error.</p>
<p>The second argument sets the <i>negative flexibility</i> of the length.
It must also be a non-negative <number>, with anything else being a syntax
error. This argument is optional; if omitted, it defaults to ''0''.</p>
<p>The third and final argument sets the <i>preferred size</i> of the length.
It must be a <length> or a <percentage>, or the keyword ''auto'' -
anything else is a syntax error. This argument is also optional; if omitted,
it defaults to ''0''.</p>
<p class=issue>The precise syntax of the flex() function is still under discussion.</p>
<!-- ====================================================================== -->
<h2 id=flex-pack>
The 'flex-pack' property</h2>
<table class=propdef>
<tr>
<th>Name:
<td><dfn>flex-pack</dfn>
<tr>
<th>Value:
<td>start | end | center | justify</td>
<tr>
<th>Initial:
<td>start
<tr>
<th>Applies to:
<td>flexboxes
<tr>
<th>Inherited:
<td>no
<tr>
<th>Computed Value:
<td>specified value
<tr>
<th>Media:
<td>visual
</table>
<p>Between and around the margins of <i>flexbox item</i>s there are additional
flexible lengths, called <dfn>packing space</dfn>. Packing space can absorb
leftover free space in a flexbox if there aren't any other <i>flexible length</i>s,
or if all the <i>flexible length</i>s have reached their maximum size. The
'flex-pack' property defines the flexibility of these packing spaces:
<dl>
<dt><dfn id=flex-pack-start>start</dfn></dt>
<dd><i>flexbox item</i>s are packed toward the start of the flexbox. The
last packing space (between the margin of the last flexbox item and the
edge of the flexbox) must absorb all leftover free space; all other packing
spaces must have a length of ''0''.</dd>
<dt><dfn id=flex-pack-end>end</dfn></dt>
<dd><i>flexbox item</i>s are packed toward the end of the flexbox. The
first packing space (between the edge of the flexbox and the margin of the
first flexbox item ) must absorb all leftover free space; all other packing
spaces must have a length of ''0''.</dd>
<dt><dfn id=flex-pack-center>center</dt>
<dd><i>flexbox item</i>s are packed toward the center of the flexbox. The
first and last packing spaces must equally split all leftover free space;
all other packing spaces must have a length of ''0''.</dd>
<dt><dfn id=flex-pack-justify>justify</dfn></dt>
<dd><i>flexbox item</i>s are evenly distributed through the flexbox. The
first and last packing spaces must have a length of ''0''; all other packing
spaces must equally split all leftover free space.</dd>
</dl>
<div class=figure>
<p class=caption><span class=issue>TODO: Provide a diagram showing packing
spaces.</p>
</div>
<div class=example>
<p class=issue>TODO: Examples showing the four values.</p>
</div>
<!-- ====================================================================== -->
<!-- Aborted new introduction to flexboxes
<p>A flexbox has two axes, which are treated differently by the space distribute algorithm: the <i>measure axis</i>, which is the axis along which the flexbox grows as you add more children, and the <i>length axis</i>, which is the perpendicular axis.</p>
<img alt="In a horizontal flexbox, the measure axis is horizontal, while the length axis is vertical.">
<p>The measure axis is more interesting, as there are more places where things can potentially flex. As such, there are more controls for specifying how to distribute free space in this axis: the 'width' or 'height' property starts things off, modified by the 'flex' property; the 'margin' property gives individual control over spacing between <i>flexbox item</i>s; and the 'flex-pack' property gives a more flexbox-global level of control over the between-children spacing.</p>
<p>In general terms, determining where to allocate free space in the measure axis starts by determining just how much free space there is. All the non-flexible lengths, and the preferred sizes of all the flexible widths or heights, are subtracted from the total width or height of the flexbox. If a positive length is left over, this is split up among all the flexible lengths according to their flexibility. Flexible margins automatically have a flexibility of 1, while widths or heights have their flexibility specified by the 'flex-grow' property.</p>
<div class=example>
<p>Three boxes, all with a preferred size of 0, will end up with sizes exactly proportional to their flex-grow values.</p>
<img alt="">
</div>
<div class=example>
<p>If the three boxes have different preferred sizes, then they'll split the free space proportionately, but their final sizes won't be exactly proportional.</p>
<img alt="">
</div>
<div class=example>
<p>Margins can also participate in flex calculations. They have a preferred size of 0, and a flexibility of 1.</p>
<img alt="">
</div>
<p>If none of the lengths are flexible, or if all the flexible widths or height have reached their maximum size (if 'max-width' or 'max-height' properties are in effect), then any leftover space is distributed according to the 'flex-pack' property between the margins of the <i>flexbox item</i>s.</p>
<div class=example>
<p>If the flexbox is small enough, then the flexible child can absorb all the space...</p>
<img>
<p>...but if it gets large enough, there'll be extra space left over for 'flex-pack' to distribute.</p>
<img>
</div>
<p>If the original calculation of how much free space was left gave a negative length (that is, if the preferred sizes of all the <i>flexbox item</i>s sum to a larger length than the width or height of the flexbox), then flexible margins get set to 0, 'flex-pack' has no effect, and <i>flexbox item</i>s with a non-zero 'flex-shrink' value split the responsibility for shrinking between themselves proportionally. Just like when they grow, their size starts from the preferred size, then combines that with the proportional share of (negative) space.</p>
<div class=example>
<p>When the children are too wide, the shrinkable elements reduce their size to fit...</p>
<img>
<p>...but if they all reach their minimum size, they just overflow.</p>
</div>
[write the length axis section]
-->
<!-- ====================================================================== -->
<h2 id=flex-align>
The 'flex-align' property</h2>
<table class=propdef>
<tr>
<th>Name:
<td><dfn>flex-align</dfn>
<tr>
<th>Value:
<td>auto | baseline
<tr>
<th>Initial:
<td>auto
<tr>
<th>Applies to:
<td>flexboxes
<tr>
<th>Inherited:
<td>no
<tr>
<th>Computed Value:
<td>specified value
<tr>
<th>Media:
<td>visual
</table>
<p>By default, laying out <i>flexbox item</i>s in the <i>length axis</i> is
a simple matter of determining free space and then splitting it between any
<i>flexible length</i>s in that axis. This is not always sufficient, however;
in particular, it is often useful to align <i>flexbox item</i>s by their baseline.
The 'flex-align' property changes the way free space is allocated in the
<i>length axis</i>.</p>
<dl>
<dt>auto</dt>
<dd>Allocate free space in the <i>length axis</i> as normal, by distributing
it proportionally between <i>flexible length</i>s in that axis.</dd>
<dt>baseline</dt>
<dd>
<p>Align all <i>flexbox item</i>s so that their baselines line up, then distribute
free space above and below the content.</p>
<p>This only has an effect on <i>flexbox item</i>s with a horizontal baseline
in a horizontal flexbox, or <i>flexbox item</i>s with a vertical baseline
in a vertical flexbox. Otherwise, alignment for that flexbox item
proceeds as if ''flex-align:auto'' had been specified.</p>
</dd>
</dl>
<p>The precise effects that 'flex-align' has on alignment and free space
distribution are detailed in a later chapter.</p>
<!-- ====================================================================== -->
<h2 id=free-space-algorithm>
Free Space Calculation and Distribution</h2>
<p>The following algorithms detail precisely how to determine the dimensions
and positions of a flexbox and its contents, and how to resolve flexible lengths
used on <i>flexbox item</i>s into definite lengths.</p>
<p>The algorithm described here is designed to be clear, but not necessarily
efficient. Implementations may use different algorithms, but they must generate
the same results as this algorithm.</p>
<p>This section defines several terms to clarify the operation of the algorithms
described within:</p>
<dl>
<dt><dfn>relevant length</dfn></dt>
<dd>The width, height, margin, border, or padding of a flexbox item. Also,
the <i>packing space</i>s of a flexbox.</dd>
<dt><dfn>flex tuple</dfn></dt>
<dd>A 5-tuple of information about a flexible length, containing a minimum
size, a maximum size, a preferred size, a positive flexibility, and a
negative flexibility.</dd>
<dt><dfn>available free space</dfn></dt>
<dd>The inner width/height of the flexbox minus the sum of the preflex sizes
of all the relevant lengths.</dd>
</dl>
<h3 id=initial-computation>
Initial Computation</h3>
<p>This step computes necessary information required to run the free-space
distribution algorithms.</p>
<ol>
<li>Determine the measure of the flexbox. Flexboxes are sized like shrinkwrapped
blocks (if ''display:flexbox'' is used) or inline-blocks (if ''display:inline-flexbox''
is used). A horizontal flexbox's measure is its width, while a vertical
flexbox's measure is its height. <span class=issue>ISSUE: Do I need to
explicitly define the sizing algorithm? I think I should be able to rely
on the generic multi-directional block sizing algorithm, perhaps with a
specification of the inputs, like what size to use for flexible lengths.</span></li>
<li>
<p>Resolve all <i>relevant length</i>s on the flexbox and its
<i>flexbox item</i>s into <dfn>flex tuples</dfn> of [preferred size,
minimum size, maximum size, positive flex, negative flex].</p>
<dl>
<dt>For margins and padding:</dt>
<dd>
<p>Set the minimum size to 0 and the maximum size to infinity.</p>
<p>If the length is inflexible, set the preferred size to the
length itself and both positive and negative flexibility to 0.</p>
<p>Otherwise, if the length was specified with the ''flex()'' function,
set the positive flexibility, negative flexibility,
and preferred size to the values specified in the function.</p>
<p>If the length is a margin with the value ''auto'', set the
preferred size to 0, the positive flexibility to 1, and the negative
flexibility to 0.</p>
</dd>
<dt>For borders:</dt>
<dd>
<p>Borders are always inflexible. Set the minimum size to 0, the
maximum size to infinity, the preferred size to the border-width,
and the positive and negative flexibility to 0.</p>
</dd>
<dt>For width and height:</dt>
<dd>
<p>Set the minimum size to the value of the 'min-width' or 'min-height',
as appropriate. Set the maximum size to the value of the 'max-width'
or 'max-height' property, as appropriate, unless the value is ''none'',
in which case set the maximum size to infinity.</p>
<p>If the length is inflexible, set the preferred size to the length
itself and both positive and negative flexibility to 0.</p>
<p>Otherwise, if the length was specified with the ''flex()'' function,
set the positive and negative flexibility to the values specified
in the function. If the preferred size argument specified in the
function is a <length>, set the preferred size to that length.
If the argment is a <percentage>, resolve it relative to the
width or height of the flexbox, as appropriate, and set the preferred
size to the resultant length. If the argument is ''auto'',
set the preferred size to the item's intrinsic dimension in the
appropriate axis.</p>
<p>Otherwise, if the length was ''auto'', set the preferred size
to the item's intrinsic dimension in the appropriate axis, the positive
flexibility to 1, and the negative flexibility to 0.</p>
<p>If the preferred size is now less than the minimum size, set
it equal to the minimum size. If the preferred size is now greater
than the maximum size, set it equal to the maximum size.</p>
</dd>
<dt>For <i>packing space</i>s:</dt>
<dd>
<p>If the flexbox's 'flex-pack' is <i title=flex-pack-start>start</i>,
the last <i>packing space</i> (between the final <i>flexbox item</i>,
after reordering by 'flex-order', and the end of the flexbox) has
a minimum size of 0, a maximum size of infinity, a preferred size
of 0, a positive flexibility of 1, and a negative flexibility of
0. All other <i>packing space</i>s have minimum size, maximum size,
preferred size, positive flexibility, and negative flexibility of
0.</p>
<p>If the flexbox's 'flex-pack' is <i title=flex-pack-end>end</i>,
the first <i>packing space</i> (between the first <i>flexbox item</i>,
after reordering by 'flex-order', and the start of the flexbox)
has a minimum size of 0, a maximum size of infinity, a preferred
size of 0, a positive flexibility of 1, and a negative flexibility
of 0. All other <i>packing space</i>s have minimum size, maximum
size, preferred size, positive flexibility, and negative flexibility
of 0.</p>
<p>If the flexbox's 'flex-pack' is <i title=flex-pack-center>center</i>,
the first and last <i>packing space</i>s (as defined above) have
a minimum size of 0, a maximum size of infinity, a preferred size
of 0, a positive flexibility of 1, and a negative flexibility of
0. All other <i>packing space</i>s have minimum size, maximum size,
preferred size, positive flexibility, and negative flexibility of
0.</p>
<p>If the flexbox's 'flex-pack' is <i title=flex-pack-justify>justify</i>,
the first and last <i>packing space</i>s (as defined above) have
a minimum size, maximum size, preferred size, positive flexibility,
and negative flexibility of 0. All other <i>packing space</i>s
have a minimum size of 0, a maximum size of infinity, a preferred
size of 0, a positive flexibility of 1, and a negative flexibility
of 0.</p>
</dd>
</dl>
</li>
</ol>
<h3 id=first-distribution-round>
First Distribution Round</h3>
<p>This step distributes free space to the flexible lengths of the flexbox
in the <i>measure axis</i>.</p>
<p>Collect the set of <i>flex tuple</i>s that can participate in this step:</p>
<ol>
<li>If the flexbox is horizontal, collect the widths of every <i>flexbox item</i>.
If the flexbox is vertical, instead collect the heights of every <i>flexbox item</i>.</li>
<li>Collect the margins of every <i>flexbox item</i> that are in the flexbox's
measure axis.</li>
<li>Collect the borders of every <i>flexbox item</i> that are in the flexbox's
measure axis, if the <i>flexbox item</i> has a 'box-sizing' value of ''content-box''
or ''padding-box''.</li>
<li>Collect the paddings of every <i>flexbox item</i> that are in the flexbox's
measure axis, if the <i>flexbox item</i> has a 'box-sizing' value of ''content-box''.</li>
</ol>
<p>Invoke the <i>free space allocation algorithm</i> with the set of <i>flex tuple</i>s
collected above, and an <i>available free space</i> equal to the flexbox's
inner measure.</p>
<h3 id=second-distribution-round>
Second Distribution Round</h3>
<p>This step distributes any leftover available space to the <i>packing space</i>,
so that the flexbox items are arranged within the flexbox as desired.</p>
<p>Collect the same set of <i>flex tuple</i>s as in the first distribution round
(now inflexible lengths), and additionally collect the flexbox's <i>packing space</i>s.</p>
<p>Invoke the <i>free space allocation algorithm</i> with the set of <i>flex tuple</i>s
collected above, and an <i>available free space</i> equal to the flexbox's
inner measure.</p>
<h3 id=intermediate-computation>
Intermediate Computation</h3>
<p>Determine the length of the flexbox, given the sizes that have already
been determined.</p>
<h3 id=third-distribution-round>
Third Distribution Round</h3>
<p>This step distributes free space to the flexible lengths of each flexbox
item in the <i>length axis</i>. <strong>It is run for each <i>flexbox item</i>
independently.</strong></p>
<p class=issue>ISSUE: This step doesn't yet take 'flex-align' into account.
I need to decide whether to always default to stretching or shrinking when
doing baseline-alignment, or coming up with some heuristic for it. Perhaps
specify the behavior in the 'flex-align' values instead? Once this decision
is made, the behavior is relatively simple - either adjust margin (if shrunk)
or padding (if stretched)
<p>Collect the set of <i>flex tuple</i>s from the current <i>flexbox item</i>
that can participate in this step:</p>
<ol>
<li>If the flexbox is horizontal, collect the height of the <i>flexbox item</i>.
If the flexbox is vertical, instead collect the width of the <i>flexbox item</i>.</li>
<li>Collect the margins of the <i>flexbox item</i> that are in the flexbox's
length axis.</li>
<li>Collect the borders of the <i>flexbox item</i> that are in the flexbox's
length axis, if the <i>flexbox item</i> has a 'box-sizing' value of ''content-box''
or ''padding-box''.</li>
<li>Collect the padding lengths of the <i>flexbox item</i> that are in the
flexbox's length axis, if the <i>flexbox item</i> has a 'box-sizing' value
of ''content-box''.</li>
</ol>
<p>Invoke the <i>free space allocation algorithm</i> with the set of <i>flex tuple</i>s
collected above, and an <i>available free space</i> equal to the flexbox's
inner length.</p>
<h3 id=free-space-allocation-algorithm>
Free Space Allocation Algorithm</h3>
<p>This section describes the algorithm used to allocate free space to a set
of flexible lengths. The inputs to this algorithm are a set of <i>flex tuple</i>s
and a length representing the <i>available free space</i>, which may be positive
or negative. The output is a set of inflexible lengths.</p>
<p>If the <i>available free space</i> is 0, transform all the <i>flex tuple</i>s
into inflexible lengths equal to their preferred size and return them.</p>
<p>If the <i>available free space</i> is a positive length, it will be distributed
between all the <i>flex tuple</i>s with positive flexibility:</p>
<ol>
<li>Sum the <i>positive flexibility</i> of all the <i>flex tuple</i>s. This
is the <i>total flexibility</i>.</li>
<li>If the <i>total flexibility</i> is 0, transform all the <i>flex tuple</i>s
into inflexible lengths equal to their preferred size and return them.</li>
<li>
<p>For each <i>flex tuple</i> with non-zero <i>positive flexibility</i>,
set its preferred size to:</p>
<pre><code>[preferred size] + ( [available free space] * [positive flexibility] / [total flexibility] )</code></pre>
</li>
<li>If any <i>flex tuple</i>s now have a preferred size greater than their
maximum size, set their preferred size to their maximum size, set their
positive flexibility to 0, and restart this algorithm.</li>
<li>Transform all the <i>flex tuple</i>s into inflexible lengths equal to
their preferred size, and return them.</li>
</ol>
<p>If the <i>available free space</i> is a negative length, all the <i>flex tuple</i>s
with negative flexibility will shrink to attemp to fit the set of <i>flex tuple</i>s
into the available space:</p>
<ol>
<li>Sum the <i>negative flexibility</i> of all the <i>flex tuple</i>s. This
is the <i>total flexibility</i>.</li>
<li>If the <i>total flexibility</i> is 0, transform all the <i>flex tuple</i>s
into inflexible lengths equal to their preferred size and return them.</li>
<li>
<p>For each <i>flex tuple</i> with non-zero <i>negative flexibility</i>,
set its preferred size to:</p>
<pre><code>[preferred size] + ( [available free space] * [negative flexibility] / [total flexibility] )</code></pre>
<p class=note>Note that the <i>available free space</i> is a negative
length here, so the sum will result in a smaller length.</p>
</li>
<li>If any <i>flex tuple</i>s now have a preferred size lesser than their
minimum size, set their preferred size to their minimum size, set their
negative flexibility to 0, and restart this algorithm.</li>
<li>Transform all the <i>flex tuple</i>s into inflexible lengths equal to
their preferred size, and return them.</li>
</ol>
<!-- ====================================================================== -->
<h2 id="layout-interface">
Interface With Other Layout Algorithms</h2>
<div class=issue>
<p>This section seems necessary, but not the precise way it's written. I
need to identify precisely what data needs to be exposed both by the containing
measure model (for the flexbox to use) and by the flexbox (for the containing
measure model to use), and then write that up. Then the other measure models
we produce can re-use the same template.</p>
<p>Need to define:</p>
<ul>
<li>The min/max/fit-content widths and heights of flexboxes in block contents</li>
<li>Other stuff?</li>
</ul>
</div>
<p>
<!--
<p>
A box placed in a block is considered a block level element and will be positioned
and sized according to the rules for CSS 2.1 (section 10.3 for widths). Specifically,
the following equation applies for calculating the width:
</p>
<blockquote>
<p>'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + scrollbar width (if any) = width of containing block
</p>
</blockquote>
<p>All children of 'box' elements are block-level. If inline-level elements are nested
inside boxes, they get wrapped in an anonymous block which then takes part in the
box layout.
</p><p>
If the width of a child of a flexible box is computed as 'auto', then the used value
is the shrink-to-fit width. This calculation is done similarly to how the width of
a floating element is determined. Otherwise if the width has a computed value,
then that value is used as the width.
</p><p>
In a horizontally oriented box, the flexibility is then applied which may increase
or decrease the used width. In a vertically oriented box, the position and size
of the child may be adjusted by the value of the container's
<span class="property">'box-align'</span> property.
</p><p>
The <span class="property">'min-width'</span>, <span class="property">'min-height'</span>,
<span class="property">'max-width'</span>, and <span class="property">'max-height'</span>
CSS properties act the same on boxes as on blocks.
</p><p>
The height of a child of a flexible box is determined in the same manner as specified
in the CSS specification. The used height may further be adjusted by the container's
<span class="property">'box-align'</span> property in a horizontally
oriented box, or the flexibility in a vertically oriented box.
</p><p>
Note that it is possible for a horizontally oriented box that the height of a
flexible child containing an inline descendant will change when the flexibility is
applied. Similarly, in a vertically oriented box, the height of a child may change
based on the <span class="property">'box-align'</span> property of the
box.
</p>
-->
<hr title="Separator from footer">
<h2 class="no-num" id="acknowledgments">Acknowledgments</h2>
<p>[This section will contain further acknowledgments.]</p>
<p>Thanks for feedback from James Elmore and Shinichiro Hamaji.</p>
<h2 class="no-num" id="references">References</h2>
<h3 class="no-num" id="normative">Normative references</h3>
<!--normative-->
<h2 class="no-num" id="index">Index</h2>
<!--index-->
<h2 id="property" class="no-num">Property index</h2>
<!--properties-->
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-declaration:"~/SGML/HTML4.decl"
sgml-default-doctype-name:"html"
sgml-minimize-attributes:t
sgml-nofill-elements:("pre" "style" "br")
sgml-live-element-indicator:t
End:
-->
</body></html>