From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- dom/flex/Flex.cpp | 67 ++++ dom/flex/Flex.h | 49 +++ dom/flex/FlexItemValues.cpp | 96 ++++++ dom/flex/FlexItemValues.h | 67 ++++ dom/flex/FlexLineValues.cpp | 73 +++++ dom/flex/FlexLineValues.h | 58 ++++ dom/flex/moz.build | 28 ++ dom/flex/test/chrome.toml | 15 + .../test/chrome/test_flex_axis_directions.html | 204 +++++++++++++ dom/flex/test/chrome/test_flex_item_clamp.html | 169 +++++++++++ dom/flex/test/chrome/test_flex_item_rect.html | 124 ++++++++ dom/flex/test/chrome/test_flex_items.html | 316 +++++++++++++++++++ dom/flex/test/chrome/test_flex_lines.html | 336 +++++++++++++++++++++ dom/flex/test/chrome/test_flex_object.html | 132 ++++++++ dom/flex/test/chrome/test_flex_parent.html | 133 ++++++++ 15 files changed, 1867 insertions(+) create mode 100644 dom/flex/Flex.cpp create mode 100644 dom/flex/Flex.h create mode 100644 dom/flex/FlexItemValues.cpp create mode 100644 dom/flex/FlexItemValues.h create mode 100644 dom/flex/FlexLineValues.cpp create mode 100644 dom/flex/FlexLineValues.h create mode 100644 dom/flex/moz.build create mode 100644 dom/flex/test/chrome.toml create mode 100644 dom/flex/test/chrome/test_flex_axis_directions.html create mode 100644 dom/flex/test/chrome/test_flex_item_clamp.html create mode 100644 dom/flex/test/chrome/test_flex_item_rect.html create mode 100644 dom/flex/test/chrome/test_flex_items.html create mode 100644 dom/flex/test/chrome/test_flex_lines.html create mode 100644 dom/flex/test/chrome/test_flex_object.html create mode 100644 dom/flex/test/chrome/test_flex_parent.html (limited to 'dom/flex') diff --git a/dom/flex/Flex.cpp b/dom/flex/Flex.cpp new file mode 100644 index 0000000000..898e81d4f5 --- /dev/null +++ b/dom/flex/Flex.cpp @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#include "Flex.h" + +#include "FlexLineValues.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/FlexBinding.h" +#include "nsFlexContainerFrame.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Flex, mParent, mLines) +NS_IMPL_CYCLE_COLLECTING_ADDREF(Flex) +NS_IMPL_CYCLE_COLLECTING_RELEASE(Flex) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Flex) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +Flex::Flex(Element* aParent, nsFlexContainerFrame* aFrame) : mParent(aParent) { + MOZ_ASSERT(aFrame, + "Should never be instantiated with a null nsFlexContainerFrame"); + + // Eagerly create property values from aFrame, because we're not + // going to keep it around. + const ComputedFlexContainerInfo* containerInfo = + aFrame->GetFlexContainerInfo(); + if (!containerInfo) { + // It's weird but possible to fail to get a ComputedFlexContainerInfo + // structure. Assign sensible default values. + mMainAxisDirection = FlexPhysicalDirection::Horizontal_lr; + mCrossAxisDirection = FlexPhysicalDirection::Vertical_tb; + return; + } + mLines.SetLength(containerInfo->mLines.Length()); + uint32_t index = 0; + for (auto&& l : containerInfo->mLines) { + FlexLineValues* line = new FlexLineValues(this, &l); + mLines.ElementAt(index) = line; + index++; + } + + mMainAxisDirection = containerInfo->mMainAxisDirection; + mCrossAxisDirection = containerInfo->mCrossAxisDirection; +} + +JSObject* Flex::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { + return Flex_Binding::Wrap(aCx, this, aGivenProto); +} + +void Flex::GetLines(nsTArray>& aResult) { + aResult.AppendElements(mLines); +} + +FlexPhysicalDirection Flex::MainAxisDirection() const { + return mMainAxisDirection; +} + +FlexPhysicalDirection Flex::CrossAxisDirection() const { + return mCrossAxisDirection; +} + +} // namespace mozilla::dom diff --git a/dom/flex/Flex.h b/dom/flex/Flex.h new file mode 100644 index 0000000000..7476585a3c --- /dev/null +++ b/dom/flex/Flex.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_Flex_h +#define mozilla_dom_Flex_h + +#include "mozilla/dom/FlexBinding.h" +#include "nsISupports.h" +#include "nsWrapperCache.h" + +class nsFlexContainerFrame; + +namespace mozilla::dom { + +class Element; +class FlexLineValues; + +class Flex : public nsISupports, public nsWrapperCache { + public: + explicit Flex(Element* aParent, nsFlexContainerFrame* aFrame); + + protected: + virtual ~Flex() = default; + + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Flex) + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + Element* GetParentObject() { return mParent; } + + void GetLines(nsTArray>& aResult); + FlexPhysicalDirection MainAxisDirection() const; + FlexPhysicalDirection CrossAxisDirection() const; + + protected: + nsCOMPtr mParent; + nsTArray> mLines; + FlexPhysicalDirection mMainAxisDirection; + FlexPhysicalDirection mCrossAxisDirection; +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_Flex_h */ diff --git a/dom/flex/FlexItemValues.cpp b/dom/flex/FlexItemValues.cpp new file mode 100644 index 0000000000..9a9be8412f --- /dev/null +++ b/dom/flex/FlexItemValues.cpp @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#include "FlexItemValues.h" + +#include "mozilla/dom/DOMRect.h" +#include "mozilla/dom/FlexBinding.h" +#include "mozilla/dom/FlexLineValues.h" +#include "nsFlexContainerFrame.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FlexItemValues, mParent, mNode, + mFrameRect) +NS_IMPL_CYCLE_COLLECTING_ADDREF(FlexItemValues) +NS_IMPL_CYCLE_COLLECTING_RELEASE(FlexItemValues) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FlexItemValues) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +/** + * Utility function to convert a nscoord size to CSS pixel values, with + * graceful treatment of NS_UNCONSTRAINEDSIZE (which this function converts to + * the double "positive infinity" value). + * + * This function is suitable for converting quantities that are expected to + * sometimes legitimately (rather than arbitrarily/accidentally) contain the + * sentinel value NS_UNCONSTRAINEDSIZE -- e.g. to handle "max-width: none". + */ +static double ToPossiblyUnconstrainedPixels(nscoord aSize) { + if (aSize == NS_UNCONSTRAINEDSIZE) { + return std::numeric_limits::infinity(); + } + return nsPresContext::AppUnitsToDoubleCSSPixels(aSize); +} + +FlexItemValues::FlexItemValues(FlexLineValues* aParent, + const ComputedFlexItemInfo* aItem) + : mParent(aParent) { + MOZ_ASSERT(aItem, + "Should never be instantiated with a null ComputedFlexLineInfo."); + + // Eagerly copy values from aItem, because we're not + // going to keep it around. + mNode = aItem->mNode; + + // Since mNode might be null, we associate the mFrameRect with + // our parent. + mFrameRect = new DOMRectReadOnly( + mParent, nsPresContext::AppUnitsToDoubleCSSPixels(aItem->mFrameRect.X()), + nsPresContext::AppUnitsToDoubleCSSPixels(aItem->mFrameRect.Y()), + nsPresContext::AppUnitsToDoubleCSSPixels(aItem->mFrameRect.Width()), + nsPresContext::AppUnitsToDoubleCSSPixels(aItem->mFrameRect.Height())); + + // Convert app unit sizes to css pixel sizes. + mMainBaseSize = + nsPresContext::AppUnitsToDoubleCSSPixels(aItem->mMainBaseSize); + mMainDeltaSize = + nsPresContext::AppUnitsToDoubleCSSPixels(aItem->mMainDeltaSize); + mMainMinSize = nsPresContext::AppUnitsToDoubleCSSPixels(aItem->mMainMinSize); + mMainMaxSize = ToPossiblyUnconstrainedPixels(aItem->mMainMaxSize); + mCrossMinSize = + nsPresContext::AppUnitsToDoubleCSSPixels(aItem->mCrossMinSize); + mCrossMaxSize = ToPossiblyUnconstrainedPixels(aItem->mCrossMaxSize); + + mClampState = aItem->mClampState; +} + +JSObject* FlexItemValues::WrapObject(JSContext* aCx, + JS::Handle aGivenProto) { + return FlexItemValues_Binding::Wrap(aCx, this, aGivenProto); +} + +nsINode* FlexItemValues::GetNode() const { return mNode; } + +DOMRectReadOnly* FlexItemValues::FrameRect() const { return mFrameRect; } + +double FlexItemValues::MainBaseSize() const { return mMainBaseSize; } + +double FlexItemValues::MainDeltaSize() const { return mMainDeltaSize; } + +double FlexItemValues::MainMinSize() const { return mMainMinSize; } + +double FlexItemValues::MainMaxSize() const { return mMainMaxSize; } + +double FlexItemValues::CrossMinSize() const { return mCrossMinSize; } + +double FlexItemValues::CrossMaxSize() const { return mCrossMaxSize; } + +FlexItemClampState FlexItemValues::ClampState() const { return mClampState; } + +} // namespace mozilla::dom diff --git a/dom/flex/FlexItemValues.h b/dom/flex/FlexItemValues.h new file mode 100644 index 0000000000..2853a922bb --- /dev/null +++ b/dom/flex/FlexItemValues.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FlexItemValues_h +#define mozilla_dom_FlexItemValues_h + +#include "mozilla/dom/FlexBinding.h" +#include "nsISupports.h" +#include "nsWrapperCache.h" + +struct ComputedFlexItemInfo; + +class nsINode; + +namespace mozilla::dom { + +class DOMRectReadOnly; + +class FlexLineValues; + +class FlexItemValues : public nsISupports, public nsWrapperCache { + public: + explicit FlexItemValues(FlexLineValues* aParent, + const ComputedFlexItemInfo* aItem); + + protected: + virtual ~FlexItemValues() = default; + + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(FlexItemValues) + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + FlexLineValues* GetParentObject() { return mParent; } + + nsINode* GetNode() const; + DOMRectReadOnly* FrameRect() const; + double MainBaseSize() const; + double MainDeltaSize() const; + double MainMinSize() const; + double MainMaxSize() const; + double CrossMinSize() const; + double CrossMaxSize() const; + FlexItemClampState ClampState() const; + + protected: + RefPtr mParent; + RefPtr mNode; + RefPtr mFrameRect; + + // These sizes are all CSS pixel units. + double mMainBaseSize; + double mMainDeltaSize; + double mMainMinSize; + double mMainMaxSize; + double mCrossMinSize; + double mCrossMaxSize; + FlexItemClampState mClampState; +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_FlexItemValues_h */ diff --git a/dom/flex/FlexLineValues.cpp b/dom/flex/FlexLineValues.cpp new file mode 100644 index 0000000000..aac403d58a --- /dev/null +++ b/dom/flex/FlexLineValues.cpp @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#include "FlexLineValues.h" + +#include "Flex.h" +#include "FlexItemValues.h" +#include "mozilla/dom/FlexBinding.h" +#include "nsFlexContainerFrame.h" + +namespace mozilla::dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FlexLineValues, mParent, mItems) +NS_IMPL_CYCLE_COLLECTING_ADDREF(FlexLineValues) +NS_IMPL_CYCLE_COLLECTING_RELEASE(FlexLineValues) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FlexLineValues) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +FlexLineValues::FlexLineValues(Flex* aParent, const ComputedFlexLineInfo* aLine) + : mParent(aParent) { + MOZ_ASSERT(aLine, + "Should never be instantiated with a null ComputedFlexLineInfo."); + + // Eagerly copy values from aLine, because we're not + // going to keep it around. + mGrowthState = aLine->mGrowthState; + + // Convert all the app unit values into css pixels. + mCrossStart = nsPresContext::AppUnitsToDoubleCSSPixels(aLine->mCrossStart); + mCrossSize = nsPresContext::AppUnitsToDoubleCSSPixels(aLine->mCrossSize); + mFirstBaselineOffset = + nsPresContext::AppUnitsToDoubleCSSPixels(aLine->mFirstBaselineOffset); + mLastBaselineOffset = + nsPresContext::AppUnitsToDoubleCSSPixels(aLine->mLastBaselineOffset); + + mItems.SetLength(aLine->mItems.Length()); + uint32_t index = 0; + for (auto&& i : aLine->mItems) { + FlexItemValues* item = new FlexItemValues(this, &i); + mItems.ElementAt(index) = item; + index++; + } +} + +JSObject* FlexLineValues::WrapObject(JSContext* aCx, + JS::Handle aGivenProto) { + return FlexLineValues_Binding::Wrap(aCx, this, aGivenProto); +} + +FlexLineGrowthState FlexLineValues::GrowthState() const { return mGrowthState; } + +double FlexLineValues::CrossStart() const { return mCrossStart; } + +double FlexLineValues::CrossSize() const { return mCrossSize; } + +double FlexLineValues::FirstBaselineOffset() const { + return mFirstBaselineOffset; +} + +double FlexLineValues::LastBaselineOffset() const { + return mLastBaselineOffset; +} + +void FlexLineValues::GetItems(nsTArray>& aResult) { + aResult.AppendElements(mItems); +} + +} // namespace mozilla::dom diff --git a/dom/flex/FlexLineValues.h b/dom/flex/FlexLineValues.h new file mode 100644 index 0000000000..340af2e7e5 --- /dev/null +++ b/dom/flex/FlexLineValues.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FlexLineValues_h +#define mozilla_dom_FlexLineValues_h + +#include "mozilla/dom/FlexBinding.h" +#include "nsISupports.h" +#include "nsWrapperCache.h" + +struct ComputedFlexLineInfo; + +namespace mozilla::dom { + +class Flex; +class FlexItemValues; + +class FlexLineValues : public nsISupports, public nsWrapperCache { + public: + explicit FlexLineValues(Flex* aParent, const ComputedFlexLineInfo* aLine); + + protected: + virtual ~FlexLineValues() = default; + + public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(FlexLineValues) + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; + Flex* GetParentObject() { return mParent; } + + FlexLineGrowthState GrowthState() const; + double CrossStart() const; + double CrossSize() const; + double FirstBaselineOffset() const; + double LastBaselineOffset() const; + + void GetItems(nsTArray>& aResult); + + protected: + RefPtr mParent; + + FlexLineGrowthState mGrowthState; + double mCrossStart; + double mCrossSize; + double mFirstBaselineOffset; + double mLastBaselineOffset; + + nsTArray> mItems; +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_FlexLineValues_h */ diff --git a/dom/flex/moz.build b/dom/flex/moz.build new file mode 100644 index 0000000000..073fa269da --- /dev/null +++ b/dom/flex/moz.build @@ -0,0 +1,28 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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 http://mozilla.org/MPL/2.0/. + +with Files("**"): + BUG_COMPONENT = ("Core", "CSS Parsing and Computation") + +MOCHITEST_CHROME_MANIFESTS += ["test/chrome.toml"] + +EXPORTS.mozilla.dom += [ + "Flex.h", + "FlexItemValues.h", + "FlexLineValues.h", +] + +UNIFIED_SOURCES += [ + "Flex.cpp", + "FlexItemValues.cpp", + "FlexLineValues.cpp", +] + +LOCAL_INCLUDES += [ + "/layout/generic", +] + +FINAL_LIBRARY = "xul" diff --git a/dom/flex/test/chrome.toml b/dom/flex/test/chrome.toml new file mode 100644 index 0000000000..477f9d2476 --- /dev/null +++ b/dom/flex/test/chrome.toml @@ -0,0 +1,15 @@ +[DEFAULT] + +["chrome/test_flex_axis_directions.html"] + +["chrome/test_flex_item_clamp.html"] + +["chrome/test_flex_item_rect.html"] + +["chrome/test_flex_items.html"] + +["chrome/test_flex_lines.html"] + +["chrome/test_flex_object.html"] + +["chrome/test_flex_parent.html"] diff --git a/dom/flex/test/chrome/test_flex_axis_directions.html b/dom/flex/test/chrome/test_flex_axis_directions.html new file mode 100644 index 0000000000..cc9f85eaf6 --- /dev/null +++ b/dom/flex/test/chrome/test_flex_axis_directions.html @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/flex/test/chrome/test_flex_item_clamp.html b/dom/flex/test/chrome/test_flex_item_clamp.html new file mode 100644 index 0000000000..6624b3ee20 --- /dev/null +++ b/dom/flex/test/chrome/test_flex_item_clamp.html @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/flex/test/chrome/test_flex_item_rect.html b/dom/flex/test/chrome/test_flex_item_rect.html new file mode 100644 index 0000000000..c535ea756b --- /dev/null +++ b/dom/flex/test/chrome/test_flex_item_rect.html @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + anonymous + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/flex/test/chrome/test_flex_items.html b/dom/flex/test/chrome/test_flex_items.html new file mode 100644 index 0000000000..0bed577ae7 --- /dev/null +++ b/dom/flex/test/chrome/test_flex_items.html @@ -0,0 +1,316 @@ + + + + + + + + + + + + + +
+
one line (first)
+
one line (last)
+
two
lines and offset (last)
+
offset (first)
+ +
+
+
+ +
+ +
+ +
+
+
+
replaced
+
+ anon item for text +
+ + +
+
+
+
+
+
+ + diff --git a/dom/flex/test/chrome/test_flex_lines.html b/dom/flex/test/chrome/test_flex_lines.html new file mode 100644 index 0000000000..aef5a5394b --- /dev/null +++ b/dom/flex/test/chrome/test_flex_lines.html @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dom/flex/test/chrome/test_flex_object.html b/dom/flex/test/chrome/test_flex_object.html new file mode 100644 index 0000000000..c984663fdf --- /dev/null +++ b/dom/flex/test/chrome/test_flex_object.html @@ -0,0 +1,132 @@ + + + + + + + + + + + + +
+
A
+
+ +
+
A
+
+ +
+ a fieldset + + +
+ +
+
+ +
+ a fieldset + + +
+ + + + + +
+ a fieldset + + +
+ +
+ a fieldset + + +
+ + + + + + + diff --git a/dom/flex/test/chrome/test_flex_parent.html b/dom/flex/test/chrome/test_flex_parent.html new file mode 100644 index 0000000000..6ab050e735 --- /dev/null +++ b/dom/flex/test/chrome/test_flex_parent.html @@ -0,0 +1,133 @@ + + + + + + + + + + + + + +
+
first item
+
+ +
+
first item
+
second item
+
+ +
+
+
display-contents-child item
+
+
+ +
+ A middle item surrounded by anonymous text items
+ + +
+
display: table-cell item
+
+ +
+ Text that gets wrapped in anonymous flex item +
+ + + + + +
+
+
child element of an item
+
+
+ +
+
+
position: absolute element
+
+
+ +
+
+
+ position: absolute element, with flex as containing block +
+
+
+ + -- cgit v1.2.3