layout/fragment_tree/containing_block.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use style::computed_values::position::T as ComputedPosition;
6
7use crate::fragment_tree::BoxFragment;
8
9/// A data structure used to track the containing block when recursing
10/// through the Fragment tree. It tracks the three types of containing
11/// blocks (for all descendants, for absolute and fixed position
12/// descendants, and for fixed position descendants).
13pub(crate) struct ContainingBlockManager<'a, T> {
14 /// The containing block for all non-absolute descendants. "...if the element's
15 /// position is 'relative' or 'static', the containing block is formed by the
16 /// content edge of the nearest block container ancestor box." This is also
17 /// the case for 'position: sticky' elements.
18 /// <https://www.w3.org/TR/CSS2/visudet.html#containing-block-details>
19 pub for_non_absolute_descendants: &'a T,
20
21 /// The containing block for absolute descendants. "If the element has
22 /// 'position: absolute', the containing block is
23 /// established by the nearest ancestor with a 'position' of 'absolute',
24 /// 'relative' or 'fixed', in the following way:
25 /// 1. In the case that the ancestor is an inline element, the containing
26 /// block is the bounding box around the padding boxes of the first and the
27 /// last inline boxes generated for that element. In CSS 2.1, if the inline
28 /// element is split across multiple lines, the containing block is
29 /// undefined.
30 /// 2. Otherwise, the containing block is formed by the padding edge of the
31 /// ancestor.
32 ///
33 /// <https://www.w3.org/TR/CSS2/visudet.html#containing-block-details>
34 /// If the ancestor forms a containing block for all descendants (see below),
35 /// this value will be None and absolute descendants will use the containing
36 /// block for fixed descendants.
37 pub for_absolute_descendants: Option<&'a T>,
38
39 /// The containing block for fixed and absolute descendants.
40 /// "For elements whose layout is governed by the CSS box model, any value
41 /// other than none for the transform property also causes the element to
42 /// establish a containing block for all descendants. Its padding box will be
43 /// used to layout for all of its absolute-position descendants,
44 /// fixed-position descendants, and descendant fixed background attachments."
45 /// <https://w3c.github.io/csswg-drafts/css-transforms-1/#containing-block-for-all-descendants>
46 /// See `ComputedValues::establishes_containing_block_for_all_descendants`
47 /// for a list of conditions where an element forms a containing block for
48 /// all descendants.
49 pub for_absolute_and_fixed_descendants: &'a T,
50}
51
52impl<'a, T> ContainingBlockManager<'a, T> {
53 pub(crate) fn containing_block_for_box(&self, fragment: &BoxFragment) -> &T {
54 match fragment.style().get_box().position {
55 ComputedPosition::Fixed => self.for_absolute_and_fixed_descendants,
56 ComputedPosition::Absolute => self
57 .for_absolute_descendants
58 .unwrap_or(self.for_absolute_and_fixed_descendants),
59 _ => self.for_non_absolute_descendants,
60 }
61 }
62
63 pub(crate) fn new_for_non_absolute_descendants(&self, containing_block: &'a T) -> Self {
64 ContainingBlockManager {
65 for_non_absolute_descendants: containing_block,
66 for_absolute_descendants: self.for_absolute_descendants,
67 for_absolute_and_fixed_descendants: self.for_absolute_and_fixed_descendants,
68 }
69 }
70
71 pub(crate) fn new_for_absolute_descendants(&self, containing_block: &'a T) -> Self {
72 ContainingBlockManager {
73 for_non_absolute_descendants: containing_block,
74 for_absolute_descendants: Some(containing_block),
75 for_absolute_and_fixed_descendants: self.for_absolute_and_fixed_descendants,
76 }
77 }
78
79 pub(crate) fn new_for_absolute_and_fixed_descendants(&self, containing_block: &'a T) -> Self {
80 ContainingBlockManager {
81 for_non_absolute_descendants: containing_block,
82 for_absolute_descendants: None,
83 for_absolute_and_fixed_descendants: containing_block,
84 }
85 }
86}