aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/fragment_tree/containing_block.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/fragment_tree/containing_block.rs')
-rw-r--r--components/layout/fragment_tree/containing_block.rs101
1 files changed, 101 insertions, 0 deletions
diff --git a/components/layout/fragment_tree/containing_block.rs b/components/layout/fragment_tree/containing_block.rs
new file mode 100644
index 00000000000..6edd9bb379b
--- /dev/null
+++ b/components/layout/fragment_tree/containing_block.rs
@@ -0,0 +1,101 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use style::computed_values::position::T as ComputedPosition;
+
+use crate::fragment_tree::Fragment;
+
+/// A data structure used to track the containing block when recursing
+/// through the Fragment tree. It tracks the three types of containing
+/// blocks (for all descendants, for absolute and fixed position
+/// descendants, and for fixed position descendants).
+pub(crate) struct ContainingBlockManager<'a, T> {
+ /// The containing block for all non-absolute descendants. "...if the element's
+ /// position is 'relative' or 'static', the containing block is formed by the
+ /// content edge of the nearest block container ancestor box." This is also
+ /// the case for 'position: sticky' elements.
+ /// <https://www.w3.org/TR/CSS2/visudet.html#containing-block-details>
+ pub for_non_absolute_descendants: &'a T,
+
+ /// The containing block for absolute descendants. "If the element has
+ /// 'position: absolute', the containing block is
+ /// established by the nearest ancestor with a 'position' of 'absolute',
+ /// 'relative' or 'fixed', in the following way:
+ /// 1. In the case that the ancestor is an inline element, the containing
+ /// block is the bounding box around the padding boxes of the first and the
+ /// last inline boxes generated for that element. In CSS 2.1, if the inline
+ /// element is split across multiple lines, the containing block is
+ /// undefined.
+ /// 2. Otherwise, the containing block is formed by the padding edge of the
+ /// ancestor.
+ ///
+ /// <https://www.w3.org/TR/CSS2/visudet.html#containing-block-details>
+ /// If the ancestor forms a containing block for all descendants (see below),
+ /// this value will be None and absolute descendants will use the containing
+ /// block for fixed descendants.
+ pub for_absolute_descendants: Option<&'a T>,
+
+ /// The containing block for fixed and absolute descendants.
+ /// "For elements whose layout is governed by the CSS box model, any value
+ /// other than none for the transform property also causes the element to
+ /// establish a containing block for all descendants. Its padding box will be
+ /// used to layout for all of its absolute-position descendants,
+ /// fixed-position descendants, and descendant fixed background attachments."
+ /// <https://w3c.github.io/csswg-drafts/css-transforms-1/#containing-block-for-all-descendants>
+ /// See `ComputedValues::establishes_containing_block_for_all_descendants`
+ /// for a list of conditions where an element forms a containing block for
+ /// all descendants.
+ pub for_absolute_and_fixed_descendants: &'a T,
+}
+
+impl<'a, T> ContainingBlockManager<'a, T> {
+ pub(crate) fn get_containing_block_for_fragment(&self, fragment: &Fragment) -> &T {
+ if let Fragment::Box(box_fragment) = fragment {
+ match box_fragment.borrow().style.clone_position() {
+ ComputedPosition::Fixed => self.for_absolute_and_fixed_descendants,
+ ComputedPosition::Absolute => self
+ .for_absolute_descendants
+ .unwrap_or(self.for_absolute_and_fixed_descendants),
+ _ => self.for_non_absolute_descendants,
+ }
+ } else {
+ self.for_non_absolute_descendants
+ }
+ }
+
+ pub(crate) fn new_for_non_absolute_descendants(
+ &self,
+ for_non_absolute_descendants: &'a T,
+ ) -> Self {
+ ContainingBlockManager {
+ for_non_absolute_descendants,
+ for_absolute_descendants: self.for_absolute_descendants,
+ for_absolute_and_fixed_descendants: self.for_absolute_and_fixed_descendants,
+ }
+ }
+
+ pub(crate) fn new_for_absolute_descendants(
+ &self,
+ for_non_absolute_descendants: &'a T,
+ for_absolute_descendants: &'a T,
+ ) -> Self {
+ ContainingBlockManager {
+ for_non_absolute_descendants,
+ for_absolute_descendants: Some(for_absolute_descendants),
+ for_absolute_and_fixed_descendants: self.for_absolute_and_fixed_descendants,
+ }
+ }
+
+ pub(crate) fn new_for_absolute_and_fixed_descendants(
+ &self,
+ for_non_absolute_descendants: &'a T,
+ for_absolute_and_fixed_descendants: &'a T,
+ ) -> Self {
+ ContainingBlockManager {
+ for_non_absolute_descendants,
+ for_absolute_descendants: None,
+ for_absolute_and_fixed_descendants,
+ }
+ }
+}