ladybird/Libraries/LibWeb/CSS/CSSContainerRule.h
Sam Atkins 585849fcf0 LibWeb: Parse and evaluate @container <size-feature>s
e.g., `@container (width >= 300px) {}` and similar.

During style computation, flag any elements whose style depends on a
size container. Then re-evaluate their style after the initial layout
has been computed and size containers have a size. This may take
multiple passes, as these may have further descendants that depend on
their size, etc. We limit this to 8 passes currently.

SizeFeature itself is very similar to MediaFeature, but queries the
container element instead. There are only 6 size features specified, so
they're hard-coded instead of generated from JSON.

Also add a counter test for the narrower restyle path.
2026-05-20 13:00:50 +01:00

68 lines
2.1 KiB
C++

/*
* Copyright (c) 2026, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/FlyString.h>
#include <AK/Optional.h>
#include <LibWeb/CSS/CSSConditionRule.h>
#include <LibWeb/Forward.h>
namespace Web::CSS {
// https://drafts.csswg.org/css-conditional-5/#dictdef-csscontainercondition
struct CSSContainerCondition {
String name;
String query;
};
// https://drafts.csswg.org/css-conditional-5/#the-csscontainerrule-interface
class CSSContainerRule final : public CSSConditionRule {
WEB_PLATFORM_OBJECT(CSSContainerRule, CSSConditionRule);
GC_DECLARE_ALLOCATOR(CSSContainerRule);
public:
struct Condition {
Optional<FlyString> container_name;
RefPtr<ContainerQuery> container_query;
};
[[nodiscard]] static GC::Ref<CSSContainerRule> create(JS::Realm&, Vector<Condition>&&, CSSRuleList&);
virtual ~CSSContainerRule() override;
virtual String condition_text() const override;
virtual bool condition_matches() const override;
bool matches(DOM::AbstractElement const&) const;
bool contains_size_feature() const;
String container_name() const;
String container_query() const;
// FIXME: Should be FrozenArray
Vector<CSSContainerCondition> conditions() const;
virtual void for_each_effective_rule(TraversalOrder, Function<void(CSSRule const&)> const& callback) const override;
private:
CSSContainerRule(JS::Realm&, Vector<Condition>&&, CSSRuleList&);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
virtual void clear_caches() override;
virtual String serialized() const override;
CSSContainerRule const* find_parent_container_rule() const;
bool conditions_match(DOM::AbstractElement const&) const;
Vector<Condition> m_conditions;
mutable GC::Ptr<CSSContainerRule const> m_cached_parent_container_rule;
mutable bool m_parent_container_rule_cache_valid { false };
};
template<>
inline bool CSSRule::fast_is<CSSContainerRule>() const { return type() == CSSRule::Type::Container; }
}