LibWeb: Resolve container-relative length units

Add cqw/cqh/cqi/cqb/cqmin/cqmax to the unit tables and generated
helpers, then thread them through the shared length resolution path.

Length::ResolutionContext now carries the subject element and whether
its inline axis is horizontal. Container units need that extra context:
the nearest eligible query container is selected from the subject
element's flat-tree ancestors, and cqi/cqb/cqmin/cqmax map logical axes
through the subject's writing mode before resolving to a physical width
or height.

Teach Length to resolve each axis against the selected container's
content box, fall back to viewport lengths when no eligible container
exists, and mark size-container dependencies so post-layout
recomputation can happen when layout is not up to date.

Also expose the new units through Typed OM, reject them for
computationally independent `@property` initial values, and add focused
font-size coverage.
This commit is contained in:
Sam Atkins 2026-05-28 15:23:26 +01:00
parent bf2c799aee
commit 693517daa0
46 changed files with 500 additions and 236 deletions

View file

@ -1,27 +1,81 @@
/*
* Copyright (c) 2020-2024, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2022-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2026, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/NonnullOwnPtr.h>
#include <AK/Variant.h>
#include <LibGC/Cell.h>
#include <LibGfx/Font/Font.h>
#include <LibGfx/Rect.h>
#include <LibWeb/CSS/ComputedProperties.h>
#include <LibWeb/CSS/FontComputer.h>
#include <LibWeb/CSS/Length.h>
#include <LibWeb/CSS/Percentage.h>
#include <LibWeb/DOM/AbstractElement.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/DOM/Element.h>
#include <LibWeb/HTML/Navigable.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Layout/Node.h>
#include <LibWeb/Painting/PaintableBox.h>
namespace Web::CSS {
void Length::ResolutionContext::visit_edges(GC::Cell::Visitor& visitor) const
{
visitor.visit(subject_element);
}
enum class ContainerRelativeAxis {
Width,
Height,
};
static bool inline_axis_is_horizontal(WritingMode writing_mode)
{
return writing_mode == WritingMode::HorizontalTb;
}
static ContainerRelativeAxis logical_axis_to_physical_axis(bool inline_axis_is_horizontal, ContainerRelativeAxis logical_axis)
{
if (inline_axis_is_horizontal)
return logical_axis;
return logical_axis == ContainerRelativeAxis::Width ? ContainerRelativeAxis::Height : ContainerRelativeAxis::Width;
}
static bool query_container_is_eligible_for_axis(DOM::Element const& container, ContainerRelativeAxis axis)
{
auto style = container.computed_properties();
if (!style)
return false;
auto container_type = style->container_type();
auto container_inline_axis_is_horizontal = inline_axis_is_horizontal(style->writing_mode());
if (axis == ContainerRelativeAxis::Width) {
if (container_inline_axis_is_horizontal)
return container_type.is_size_container || container_type.is_inline_size_container;
return container_type.is_size_container;
}
if (container_inline_axis_is_horizontal)
return container_type.is_size_container;
return container_type.is_size_container || container_type.is_inline_size_container;
}
static DOM::Element const* nearest_query_container_for_axis(DOM::Element const& subject, ContainerRelativeAxis axis)
{
for (auto const* container = subject.flat_tree_parent_element(); container; container = container->flat_tree_parent_element()) {
if (query_container_is_eligible_for_axis(*container, axis))
return container;
}
return nullptr;
}
Length::FontMetrics::FontMetrics(CSSPixels font_size, Gfx::FontPixelMetrics const& pixel_metrics, CSSPixels line_height)
: font_size(font_size)
, x_height(pixel_metrics.x_height)
@ -122,6 +176,69 @@ double Length::viewport_relative_length_to_px_without_rounding(CSSPixelRect cons
}
}
double Length::container_relative_length_to_px_without_rounding(ResolutionContext const& context) const
{
// https://drafts.csswg.org/css-conditional-5/#container-lengths
auto resolve_physical_axis_basis_length = [&](ContainerRelativeAxis physical_axis) {
// The query container for each axis is the nearest ancestor container that accepts container size queries on
// that axis. If no eligible query container is available, then use the small viewport size for that axis.
if (!context.subject_element) {
context.record_viewport_relative_length_resolution();
auto viewport_length = physical_axis == ContainerRelativeAxis::Width ? context.viewport_rect.width() : context.viewport_rect.height();
return viewport_length.to_double();
}
auto& subject = *context.subject_element;
const_cast<DOM::Element&>(subject).set_style_depends_on_size_container_query();
auto query_container = nearest_query_container_for_axis(subject, physical_axis);
if (!query_container) {
context.record_viewport_relative_length_resolution();
auto viewport_length = physical_axis == ContainerRelativeAxis::Width ? context.viewport_rect.width() : context.viewport_rect.height();
return viewport_length.to_double();
}
auto paintable_box = query_container->unsafe_paintable_box();
if (!paintable_box) {
if (!subject.document().layout_is_up_to_date())
const_cast<DOM::Document&>(subject.document()).set_needs_container_query_evaluation_after_layout(*query_container);
return 0.0;
}
auto container_length = physical_axis == ContainerRelativeAxis::Width ? paintable_box->content_width() : paintable_box->content_height();
return container_length.to_double();
};
auto resolve_physical_axis_length = [&](ContainerRelativeAxis physical_axis) {
return resolve_physical_axis_basis_length(physical_axis) * m_value / 100;
};
auto resolve_logical_axis_basis_length = [&](ContainerRelativeAxis logical_axis) {
return resolve_physical_axis_basis_length(logical_axis_to_physical_axis(context.subject_inline_axis_is_horizontal, logical_axis));
};
auto resolve_logical_axis_length = [&](ContainerRelativeAxis logical_axis) {
return resolve_logical_axis_basis_length(logical_axis) * m_value / 100;
};
switch (m_unit) {
case LengthUnit::Cqw:
return resolve_physical_axis_length(ContainerRelativeAxis::Width);
case LengthUnit::Cqh:
return resolve_physical_axis_length(ContainerRelativeAxis::Height);
case LengthUnit::Cqi:
return resolve_logical_axis_length(ContainerRelativeAxis::Width);
case LengthUnit::Cqb:
return resolve_logical_axis_length(ContainerRelativeAxis::Height);
case LengthUnit::Cqmin:
return min(resolve_logical_axis_basis_length(ContainerRelativeAxis::Width), resolve_logical_axis_basis_length(ContainerRelativeAxis::Height)) * m_value / 100;
case LengthUnit::Cqmax:
return max(resolve_logical_axis_basis_length(ContainerRelativeAxis::Width), resolve_logical_axis_basis_length(ContainerRelativeAxis::Height)) * m_value / 100;
default:
VERIFY_NOT_REACHED();
}
}
Length::ResolutionContext Length::ResolutionContext::for_element(DOM::AbstractElement const& element)
{
auto const* root_element = element.element().document().document_element();
@ -136,6 +253,8 @@ Length::ResolutionContext Length::ResolutionContext::for_element(DOM::AbstractEl
.root_font_metrics = { root_element->computed_properties()->font_size(), root_element->computed_properties()->first_available_computed_font(element.document().font_computer())->pixel_metrics(), element.computed_properties()->line_height() },
.font_metrics_depend_on_viewport_metrics = element.computed_properties()->font_metrics_depend_on_viewport_metrics(),
.root_font_metrics_depend_on_viewport_metrics = root_element->computed_properties()->font_metrics_depend_on_viewport_metrics(),
.subject_inline_axis_is_horizontal = inline_axis_is_horizontal(element.computed_properties()->writing_mode()),
.subject_element = &element.element(),
};
}
@ -153,12 +272,14 @@ Length::ResolutionContext Length::ResolutionContext::for_document(DOM::Document
.viewport_rect = viewport_rect,
.font_metrics = font_metrics,
.root_font_metrics = font_metrics,
.subject_inline_axis_is_horizontal = true,
};
}
Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Node const& node)
{
Layout::Node const* root_layout_node;
DOM::Element const* subject_element = nullptr;
if (is<DOM::Document>(node.dom_node())) {
root_layout_node = &node;
@ -170,10 +291,15 @@ Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Nod
root_layout_node = root_element->unsafe_layout_node();
}
if (auto const* dom_node = node.dom_node(); dom_node && is<DOM::Element>(*dom_node))
subject_element = &as<DOM::Element>(*dom_node);
return Length::ResolutionContext {
.viewport_rect = node.navigable()->viewport_rect(),
.font_metrics = { node.computed_values().font_size(), node.first_available_font().pixel_metrics(), node.computed_values().line_height() },
.root_font_metrics = { root_layout_node->computed_values().font_size(), root_layout_node->first_available_font().pixel_metrics(), node.computed_values().line_height() },
.subject_inline_axis_is_horizontal = inline_axis_is_horizontal(node.computed_values().writing_mode()),
.subject_element = subject_element,
};
}
@ -186,30 +312,7 @@ CSSPixels Length::to_px_slow_case(Layout::Node const& layout_node) const
{
if (!layout_node.document().browsing_context())
return 0;
if (is_font_relative()) {
auto* root_element = layout_node.document().document_element();
// NB: Called during CSS length resolution, which may happen during style recalculation.
if (!root_element || !root_element->unsafe_layout_node())
return 0;
FontMetrics font_metrics {
layout_node.computed_values().font_size(),
layout_node.first_available_font().pixel_metrics(),
layout_node.computed_values().line_height()
};
FontMetrics root_font_metrics {
root_element->unsafe_layout_node()->computed_values().font_size(),
root_element->unsafe_layout_node()->first_available_font().pixel_metrics(),
layout_node.computed_values().line_height()
};
return font_relative_length_to_px(font_metrics, root_font_metrics);
}
VERIFY(is_viewport_relative());
auto const& viewport_rect = layout_node.document().viewport_rect();
return viewport_relative_length_to_px(viewport_rect);
return to_px(ResolutionContext::for_layout_node(layout_node));
}
void Length::serialize(StringBuilder& builder, SerializationMode serialization_mode) const

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2021-2026, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -9,6 +9,8 @@
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <LibGC/Cell.h>
#include <LibGC/Ptr.h>
#include <LibGfx/Forward.h>
#include <LibGfx/Rect.h>
#include <LibWeb/CSS/SerializationMode.h>
@ -48,10 +50,10 @@ public:
bool is_absolute() const { return CSS::is_absolute(m_unit); }
bool is_font_relative() const { return CSS::is_font_relative(m_unit); }
bool is_container_relative() const { return CSS::is_container_relative(m_unit); }
bool is_viewport_relative() const { return CSS::is_viewport_relative(m_unit); }
bool is_relative() const { return CSS::is_relative(m_unit); }
// FIXME: Mark container query units as not computationally independent once we support them
bool is_computationally_independent() const { return !is_font_relative(); }
bool is_computationally_independent() const { return !is_font_relative() && !is_container_relative(); }
double raw_value() const { return m_value; }
LengthUnit unit() const { return m_unit; }
@ -67,6 +69,8 @@ public:
FontMetrics root_font_metrics;
bool font_metrics_depend_on_viewport_metrics { false };
bool root_font_metrics_depend_on_viewport_metrics { false };
bool subject_inline_axis_is_horizontal { true };
GC::Ptr<DOM::Element const> subject_element { nullptr };
void set_did_resolve_viewport_relative_length(bool& did_resolve_viewport_relative_length) const
{
@ -114,9 +118,13 @@ public:
&& font_metrics == other.font_metrics
&& root_font_metrics == other.root_font_metrics
&& font_metrics_depend_on_viewport_metrics == other.font_metrics_depend_on_viewport_metrics
&& root_font_metrics_depend_on_viewport_metrics == other.root_font_metrics_depend_on_viewport_metrics;
&& root_font_metrics_depend_on_viewport_metrics == other.root_font_metrics_depend_on_viewport_metrics
&& subject_inline_axis_is_horizontal == other.subject_inline_axis_is_horizontal
&& subject_element == other.subject_element;
}
void visit_edges(GC::Cell::Visitor&) const;
mutable bool* m_did_resolve_viewport_relative_length { nullptr };
};
@ -141,6 +149,8 @@ public:
context.record_viewport_relative_length_resolution();
return viewport_relative_length_to_px_without_rounding(context.viewport_rect);
}
if (is_container_relative())
return container_relative_length_to_px_without_rounding(context);
VERIFY_NOT_REACHED();
}
@ -153,6 +163,14 @@ public:
return font_relative_length_to_px(font_metrics, root_font_metrics);
if (is_viewport_relative())
return viewport_relative_length_to_px(viewport_rect);
if (is_container_relative()) {
ResolutionContext context {
.viewport_rect = viewport_rect,
.font_metrics = font_metrics,
.root_font_metrics = root_font_metrics,
};
return CSSPixels::nearest_value_for(container_relative_length_to_px_without_rounding(context));
}
VERIFY_NOT_REACHED();
}
@ -179,6 +197,7 @@ public:
double font_relative_length_to_px_without_rounding(FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const;
CSSPixels viewport_relative_length_to_px(CSSPixelRect const& viewport_rect) const;
double viewport_relative_length_to_px_without_rounding(CSSPixelRect const& viewport_rect) const;
double container_relative_length_to_px_without_rounding(ResolutionContext const&) const;
// Returns empty optional if it's already absolute.
Optional<Length> absolutize(ResolutionContext const&) const;

View file

@ -1705,6 +1705,16 @@ void StyleComputer::compute_property_values(ComputedProperties& style, Optional<
ComputationContext const& StyleComputer::get_computation_context_for_property(PropertyID property_id, ComputedProperties const& style, Optional<DOM::AbstractElement> abstract_element) const
{
auto subject_inline_axis_is_horizontal = [&]() {
if (!abstract_element.has_value())
return true;
if (auto computed_properties = abstract_element->computed_properties(); computed_properties)
return computed_properties->writing_mode() == WritingMode::HorizontalTb;
if (auto inheritance_parent = abstract_element->element_to_inherit_style_from(); inheritance_parent.has_value() && inheritance_parent->computed_properties())
return inheritance_parent->computed_properties()->writing_mode() == WritingMode::HorizontalTb;
return true;
}();
switch (property_id) {
// FIXME: While `color-scheme` doesn't actually require a computation context (since it only takes keyword values)
// we still try to generate one in `compute_property_values()` and since we need `color-scheme` to be
@ -1730,11 +1740,14 @@ ComputationContext const& StyleComputer::get_computation_context_for_property(Pr
case PropertyID::TextRendering: {
if (!m_cached_font_computation_context.has_value()) {
auto inheritance_parent = abstract_element.map([](auto& element) { return element.element_to_inherit_style_from(); }).value_or(OptionalNone {});
auto length_resolution_context = inheritance_parent.has_value()
? Length::ResolutionContext::for_element(inheritance_parent.value())
: Length::ResolutionContext::for_document(m_document);
length_resolution_context.subject_inline_axis_is_horizontal = subject_inline_axis_is_horizontal;
length_resolution_context.subject_element = abstract_element.has_value() ? &abstract_element->element() : nullptr;
m_cached_font_computation_context = {
.length_resolution_context = inheritance_parent.has_value()
? Length::ResolutionContext::for_element(inheritance_parent.value())
: Length::ResolutionContext::for_document(m_document),
.length_resolution_context = length_resolution_context,
.abstract_element = abstract_element
};
}
@ -1762,6 +1775,8 @@ ComputationContext const& StyleComputer::get_computation_context_for_property(Pr
.root_font_metrics_depend_on_viewport_metrics = abstract_element.has_value() && abstract_element->element().is_html_html_element()
? style.font_metrics_depend_on_viewport_metrics()
: m_root_element_font_metrics_depend_on_viewport_metrics,
.subject_inline_axis_is_horizontal = subject_inline_axis_is_horizontal,
.subject_element = abstract_element.has_value() ? &abstract_element->element() : nullptr,
},
.abstract_element = abstract_element
};
@ -1781,6 +1796,8 @@ ComputationContext const& StyleComputer::get_computation_context_for_property(Pr
.root_font_metrics = m_root_element_font_metrics,
.font_metrics_depend_on_viewport_metrics = style.font_metrics_depend_on_viewport_metrics(),
.root_font_metrics_depend_on_viewport_metrics = abstract_element.has_value() && abstract_element->element().is_html_html_element() ? style.font_metrics_depend_on_viewport_metrics() : m_root_element_font_metrics_depend_on_viewport_metrics,
.subject_inline_axis_is_horizontal = subject_inline_axis_is_horizontal,
.subject_element = abstract_element.has_value() ? &abstract_element->element() : nullptr,
},
.abstract_element = abstract_element,
.color_scheme = style.color_scheme(document().page().preferred_color_scheme(), document().supported_color_schemes())
@ -2293,6 +2310,8 @@ RefPtr<StyleValue const> StyleComputer::recascade_font_size_if_needed(DOM::Abstr
.root_font_metrics = m_root_element_font_metrics,
.font_metrics_depend_on_viewport_metrics = current_size_depends_on_viewport_metrics || inherited_font_metrics_depend_on_viewport_metrics,
.root_font_metrics_depend_on_viewport_metrics = m_root_element_font_metrics_depend_on_viewport_metrics,
.subject_inline_axis_is_horizontal = ancestor.computed_properties()->writing_mode() == WritingMode::HorizontalTb,
.subject_element = &ancestor.element(),
};
resolution_context.set_did_resolve_viewport_relative_length(did_resolve_viewport_relative_length);
current_size_in_px = font_size_value->as_length().length().to_px(resolution_context);

View file

@ -30,6 +30,7 @@ struct ComputationContext {
void visit_edges(GC::Cell::Visitor& visitor)
{
length_resolution_context.visit_edges(visitor);
if (abstract_element.has_value())
abstract_element->visit(visitor);
}

View file

@ -27,7 +27,7 @@ public:
virtual void serialize(StringBuilder& builder, SerializationMode mode) const override { m_length.serialize(builder, mode); }
virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(ComputationContext const&) const override;
virtual bool is_computationally_independent() const override { return !m_length.is_font_relative(); }
virtual bool is_computationally_independent() const override { return m_length.is_computationally_independent(); }
bool equals(StyleValue const& other) const override;

View file

@ -36,6 +36,24 @@
"cm": {
"number-of-canonical-unit": 37.7952755905511811023622047244094488188976377952755905511811023622047244094
},
"cqb": {
"relative-to": "container"
},
"cqh": {
"relative-to": "container"
},
"cqi": {
"relative-to": "container"
},
"cqmax": {
"relative-to": "container"
},
"cqmin": {
"relative-to": "container"
},
"cqw": {
"relative-to": "container"
},
"dvb": {
"relative-to": "viewport"
},

View file

@ -70,6 +70,7 @@ double ratio_between_units({name_titlecase}Unit, {name_titlecase}Unit);
out.write("""
bool is_absolute(LengthUnit);
bool is_font_relative(LengthUnit);
bool is_container_relative(LengthUnit);
bool is_viewport_relative(LengthUnit);
inline bool is_relative(LengthUnit unit) { return !is_absolute(unit); }
@ -234,6 +235,21 @@ bool is_font_relative(LengthUnit unit)
}
}
bool is_container_relative(LengthUnit unit)
{
switch (unit) {
""")
for unit_name, unit in length_units.items():
if unit.get("relative-to") != "container":
continue
out.write(f" case LengthUnit::{title_casify(unit_name)}:\n")
out.write("""
return true;
default:
return false;
}
}
bool is_viewport_relative(LengthUnit unit)
{
switch (unit) {

View file

@ -70,7 +70,7 @@ def json_is_valid(dimensions_data: dict[str, Any], json_path: str) -> bool:
canonical_unit = unit_name
if relative_to is not None:
if dimension_name == "length":
if relative_to not in ("font", "viewport"):
if relative_to not in ("font", "viewport", "container"):
print(
f"{json_path}: {dimension_name} unit `{unit_name}` is marked as relative to "
f"`{relative_to}`, which is unsupported.",

View file

@ -74,6 +74,36 @@ cm configurable: true
cm enumerable: true
cm value before: function cm() { [native code] }
cm value after: replaced
cqb writable: true
cqb configurable: true
cqb enumerable: true
cqb value before: function cqb() { [native code] }
cqb value after: replaced
cqh writable: true
cqh configurable: true
cqh enumerable: true
cqh value before: function cqh() { [native code] }
cqh value after: replaced
cqi writable: true
cqi configurable: true
cqi enumerable: true
cqi value before: function cqi() { [native code] }
cqi value after: replaced
cqmax writable: true
cqmax configurable: true
cqmax enumerable: true
cqmax value before: function cqmax() { [native code] }
cqmax value after: replaced
cqmin writable: true
cqmin configurable: true
cqmin enumerable: true
cqmin value before: function cqmin() { [native code] }
cqmin value after: replaced
cqw writable: true
cqw configurable: true
cqw enumerable: true
cqw value before: function cqw() { [native code] }
cqw value after: replaced
dvb writable: true
dvb configurable: true
dvb enumerable: true

View file

@ -2,9 +2,8 @@ Harness status: OK
Found 4 tests
3 Pass
1 Fail
4 Pass
Pass Property animation-delay value '-500ms'
Pass Property animation-delay value 'calc(2 * 3s)'
Pass Property animation-delay value '20s, 10s'
Fail Property animation-delay value 'calc(10s + (sign(2cqw - 10px) * 5s))'
Pass Property animation-delay value 'calc(10s + (sign(2cqw - 10px) * 5s))'

View file

@ -2,11 +2,10 @@ Harness status: OK
Found 15 tests
14 Pass
1 Fail
15 Pass
Pass Property animation-duration value '500ms'
Pass Property animation-duration value 'calc(2 * 3s)'
Fail Property animation-duration value 'calc(10s + (sign(2cqw - 10px) * 5s))'
Pass Property animation-duration value 'calc(10s + (sign(2cqw - 10px) * 5s))'
Pass Property animation-duration value '20s, 10s'
Pass Property animation-duration value 'auto'
Pass Property animation-duration value 'auto, auto'

View file

@ -2,7 +2,6 @@ Harness status: OK
Found 2 tests
1 Pass
1 Fail
2 Pass
Pass Property animation-iteration-count value '0, infinite, 3'
Fail Property animation-iteration-count value 'calc(10 + (sign(2cqw - 10px) * 5))'
Pass Property animation-iteration-count value 'calc(10 + (sign(2cqw - 10px) * 5))'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 468 tests
466 Pass
2 Fail
467 Pass
1 Fail
Pass Property color value 'color(srgb 0% 0% 0%)'
Pass Property color value 'color(srgb 10% 10% 10%)'
Pass Property color value 'color(srgb .2 .2 25%)'
@ -470,5 +470,5 @@ Pass Property color value 'color(display-p3 0.5 -199 0.75)' [Display P3 color wi
Pass Property color value 'color(display-p3 184 1.00001 1103)' [Display P3 color with component > 1 should not clamp]
Pass Property color value 'color(srgb 0.1 0.2 0.3 / 1.9)' [Alpha > 1 should clamp]
Pass Property color value 'color(srgb 1 1 1 / -0.2)' [Negative alpha should clamp]
Fail Property color value 'color(srgb calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0 0 / 0.51)'
Pass Property color value 'color(srgb calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0 0 / 0.51)'
Fail Property color value 'color(srgb calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0 0 / 0.52)'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 3753 tests
3751 Pass
2 Fail
3752 Pass
1 Fail
Pass Property color value 'hsl(120 30% 50%)'
Pass Property color value 'hsl(120 30% 50% / 0.5)'
Pass Property color value 'hsl(120 30% 50% / 50%)'
@ -3755,5 +3755,5 @@ Pass Property color value 'hsl(60deg 100% 37.5% / calc(50% + (sign(1em - 10px) *
Pass Property color value 'hsla(60deg 100% 37.5% / calc(50% + (sign(1em - 10px) * 10%)))'
Pass Property color value 'hsl(60 100 37.5 / calc(0.75 + (sign(1em - 10px) * 0.1)))'
Pass Property color value 'hsla(60 100 37.5 / calc(0.75 + (sign(1em - 10px) * 0.1)))'
Fail Property color value 'hsla(calc(50deg + (sign(2cqw - 10px) * 10deg)), 100%, 37.5%, 51%)'
Pass Property color value 'hsla(calc(50deg + (sign(2cqw - 10px) * 10deg)), 100%, 37.5%, 51%)'
Fail Property color value 'hsla(calc(50deg + (sign(2cqw - 10px) * 10deg)), 100%, 37.5%, 52%)'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 56 tests
54 Pass
2 Fail
55 Pass
1 Fail
Pass Property color value 'hwb(120 30% 50%)'
Pass Property color value 'hwb(120 30% 50% / 0.5)'
Pass Property color value 'hwb(120 30% 50% / 50%)'
@ -58,5 +58,5 @@ Pass Property color value 'hwb(calc(110deg + (sign(1em - 10px) * 10deg)) 30% 50%
Pass Property color value 'hwb(calc(110 + (sign(1em - 10px) * 10)) 30 50 / 0.5)'
Pass Property color value 'hwb(120deg 30% 50% / calc(50% + (sign(1em - 10px) * 10%)))'
Pass Property color value 'hwb(120 30 50 / calc(0.75 + (sign(1em - 10px) * 0.1)))'
Fail Property color value 'hwb(calc(110deg + (sign(2cqw - 10px) * 10deg)) 30 50 / 51%)'
Pass Property color value 'hwb(calc(110deg + (sign(2cqw - 10px) * 10deg)) 30 50 / 51%)'
Fail Property color value 'hwb(calc(110deg + (sign(2cqw - 10px) * 10deg)) 30 50 / 52%)'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 120 tests
112 Pass
8 Fail
119 Pass
1 Fail
Pass Property color value 'lab(0 0 0)'
Pass Property color value 'lab(0 0 0 / 1)'
Pass Property color value 'lab(0 0 0 / 0.5)'
@ -116,11 +116,11 @@ Pass Property color value 'lch(calc(50 + (sign(1em - 10px) * 10)) 30 50deg / 50%
Pass Property color value 'oklch(calc(0.5 + (sign(1em - 10px) * 0.1)) 0.3 50deg / 50%)'
Pass Property color value 'lch(60 30 50deg / calc(50% + (sign(1em - 10px) * 10%)))'
Pass Property color value 'oklch(0.6 0.3 50deg / calc(50% + (sign(1em - 10px) * 10%)))'
Fail Property color value 'lab(calc(50 + (sign(2cqw - 10px) * 10)) 30 50 / 0.51)'
Fail Property color value 'oklab(calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0.3 0.5 / 0.51)'
Fail Property color value 'lch(calc(50 + (sign(2cqw - 10px) * 10)) 30 50 / 0.51)'
Fail Property color value 'oklch(calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0.3 50 / 0.51)'
Pass Property color value 'lab(calc(50 + (sign(2cqw - 10px) * 10)) 30 50 / 0.51)'
Pass Property color value 'oklab(calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0.3 0.5 / 0.51)'
Pass Property color value 'lch(calc(50 + (sign(2cqw - 10px) * 10)) 30 50 / 0.51)'
Pass Property color value 'oklch(calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0.3 50 / 0.51)'
Fail Property color value 'lab(calc(50 + (sign(2cqw - 10px) * 10)) 30 50 / 0.52)'
Fail Property color value 'oklab(calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0.3 0.5 / 0.52)'
Fail Property color value 'lch(calc(50 + (sign(2cqw - 10px) * 10)) 30 50 / 0.52)'
Fail Property color value 'oklch(calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0.3 50 / 0.52)'
Pass Property color value 'oklab(calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0.3 0.5 / 0.52)'
Pass Property color value 'lch(calc(50 + (sign(2cqw - 10px) * 10)) 30 50 / 0.52)'
Pass Property color value 'oklch(calc(0.5 + (sign(2cqw - 10px) * 0.1)) 0.3 50 / 0.52)'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 99 tests
97 Pass
2 Fail
98 Pass
1 Fail
Pass Property color value 'rgb(none none none)'
Pass Property color value 'rgb(none none none / none)'
Pass Property color value 'rgb(128 none none)'
@ -101,5 +101,5 @@ Pass Property color value 'rgb(0 0 0 / calc(0.75 + (sign(1em - 10px) * 0.1)))'
Pass Property color value 'rgba(0 0 0 / calc(0.75 + (sign(1em - 10px) * 0.1)))'
Pass Property color value 'rgba(calc(50% + (sign(1em - 10px) * 10%)) 0 0% / 0.5)'
Pass Property color value 'rgba(0% 0 0% / calc(0.75 + (sign(1em - 10px) * 0.1)))'
Fail Property color value 'rgba(calc(50% + (sign(2cqw - 10px) * 10%)), 0%, 0%, 51%)'
Pass Property color value 'rgba(calc(50% + (sign(2cqw - 10px) * 10%)), 0%, 0%, 51%)'
Fail Property color value 'rgba(calc(50% + (sign(2cqw - 10px) * 10%)), 0%, 0%, 52%)'

View file

@ -2,8 +2,9 @@ Harness status: OK
Found 24 tests
24 Fail
Fail CSS Animation using cqw unit
4 Pass
20 Fail
Pass CSS Animation using cqw unit
Fail CSS Animation using cqw unit responds to changing container size
Fail CSS Animation using cqh unit
Fail CSS Animation using cqh unit responds to changing container size
@ -15,15 +16,15 @@ Fail CSS Animation using cqmin unit
Fail CSS Animation using cqmin unit responds to changing container size
Fail CSS Animation using cqmax unit
Fail CSS Animation using cqmax unit responds to changing container size
Fail Web Animation using cqw unit
Pass Web Animation using cqw unit
Fail Web Animation using cqw unit responds to changing container size
Fail Web Animation using cqh unit
Fail Web Animation using cqh unit responds to changing container size
Fail Web Animation using cqi unit
Pass Web Animation using cqi unit
Fail Web Animation using cqi unit responds to changing container size
Fail Web Animation using cqb unit
Fail Web Animation using cqb unit responds to changing container size
Fail Web Animation using cqmin unit
Pass Web Animation using cqmin unit
Fail Web Animation using cqmin unit responds to changing container size
Fail Web Animation using cqmax unit
Fail Web Animation using cqmax unit responds to changing container size

View file

@ -2,6 +2,6 @@ Harness status: OK
Found 2 tests
2 Fail
Fail Container relative units
Fail Container relative units in math functions
2 Pass
Pass Container relative units
Pass Container relative units in math functions

View file

@ -2,6 +2,6 @@ Harness status: OK
Found 2 tests
2 Fail
Fail Container units are relative to the content box of the container
Fail Container units are relative to the content box of the container (box-sizing: border-box)
2 Pass
Pass Container units are relative to the content box of the container
Pass Container units are relative to the content box of the container (box-sizing: border-box)

View file

@ -0,0 +1,8 @@
Harness status: OK
Found 3 tests
3 Pass
Pass font-size cqw uses the nearest eligible container
Pass font-size cqi uses the subject writing mode
Pass font-size cqw responds when the nearest container size changes

View file

@ -2,5 +2,5 @@ Harness status: OK
Found 1 tests
1 Fail
Fail Query with container-relative units are responsive to changes
1 Pass
Pass Query with container-relative units are responsive to changes

View file

@ -2,5 +2,5 @@ Harness status: OK
Found 1 tests
1 Fail
Fail Use small viewport size as fallback
1 Pass
Pass Use small viewport size as fallback

View file

@ -2,22 +2,22 @@ Harness status: OK
Found 18 tests
18 Fail
Fail cqw unit resolves against appropriate container
Fail cqh unit resolves against appropriate container
Fail cqi unit resolves against appropriate container
Fail cqb unit resolves against appropriate container
Fail cqmin unit resolves against appropriate container
Fail cqmax unit resolves against appropriate container
Fail cqw unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqh unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqi unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqb unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqmin unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqmax unit resolves against appropriate container (vertical writing-mode on subject)
Fail cqw unit resolves against appropriate container (vertical writing-mode on container)
Fail cqh unit resolves against appropriate container (vertical writing-mode on container)
Fail cqi unit resolves against appropriate container (vertical writing-mode on container)
Fail cqb unit resolves against appropriate container (vertical writing-mode on container)
Fail cqmin unit resolves against appropriate container (vertical writing-mode on container)
Fail cqmax unit resolves against appropriate container (vertical writing-mode on container)
18 Pass
Pass cqw unit resolves against appropriate container
Pass cqh unit resolves against appropriate container
Pass cqi unit resolves against appropriate container
Pass cqb unit resolves against appropriate container
Pass cqmin unit resolves against appropriate container
Pass cqmax unit resolves against appropriate container
Pass cqw unit resolves against appropriate container (vertical writing-mode on subject)
Pass cqh unit resolves against appropriate container (vertical writing-mode on subject)
Pass cqi unit resolves against appropriate container (vertical writing-mode on subject)
Pass cqb unit resolves against appropriate container (vertical writing-mode on subject)
Pass cqmin unit resolves against appropriate container (vertical writing-mode on subject)
Pass cqmax unit resolves against appropriate container (vertical writing-mode on subject)
Pass cqw unit resolves against appropriate container (vertical writing-mode on container)
Pass cqh unit resolves against appropriate container (vertical writing-mode on container)
Pass cqi unit resolves against appropriate container (vertical writing-mode on container)
Pass cqb unit resolves against appropriate container (vertical writing-mode on container)
Pass cqmin unit resolves against appropriate container (vertical writing-mode on container)
Pass cqmax unit resolves against appropriate container (vertical writing-mode on container)

View file

@ -2,13 +2,14 @@ Harness status: OK
Found 9 tests
9 Fail
Fail /* basic */
4 Pass
5 Fail
Pass /* basic */
Fail display: table
Fail display: table-cell
Fail display: inline
Fail display: contents
Fail display: none
Fail container-type: normal
Fail container-type: inline-size
Fail container-type: inline-size; writing-mode: vertical-lr
Pass container-type: normal
Pass container-type: inline-size
Pass container-type: inline-size; writing-mode: vertical-lr

View file

@ -2,9 +2,10 @@ Harness status: OK
Found 5 tests
5 Fail
Fail cqi respond when selected container changes type (inline-size -> normal)
Fail cqb respond when selected container changes type (size -> normal)
2 Pass
3 Fail
Pass cqi respond when selected container changes type (inline-size -> normal)
Pass cqb respond when selected container changes type (size -> normal)
Fail cqb respond when intermediate container changes type (inline-size -> size)
Fail cqi respond when selected container changes inline-size
Fail cqb respond when selected container changes block-size

View file

@ -2,13 +2,12 @@ Harness status: OK
Found 8 tests
2 Pass
6 Fail
Fail @media(width:100cqw) applies
Fail @media(width:100cqi) applies
Fail @media(width:100cqmax) applies
Fail @media(height:100cqh) applies
Fail @media(height:100cqb) applies
Fail @media(height:100cqmin) applies
8 Pass
Pass @media(width:100cqw) applies
Pass @media(width:100cqi) applies
Pass @media(width:100cqmax) applies
Pass @media(height:100cqh) applies
Pass @media(height:100cqb) applies
Pass @media(height:100cqmin) applies
Pass @media(width:90cqw) does not apply
Pass @media(height:90cqh) does not apply

View file

@ -2,6 +2,6 @@ Harness status: OK
Found 2 tests
2 Fail
Fail Container units select the proper container
Fail Units respond to the writing-mode of the element
2 Pass
Pass Container units select the proper container
Pass Units respond to the writing-mode of the element

View file

@ -2,5 +2,5 @@ Harness status: OK
Found 1 tests
1 Fail
Fail Use small viewport size as fallback
1 Pass
Pass Use small viewport size as fallback

View file

@ -2,28 +2,28 @@ Harness status: OK
Found 24 tests
24 Fail
Fail CSS.cqw function
Fail Reify value with cqw unit
Fail Set value with cqw unit (string)
Fail Set value with cqw unit (CSS.cqw)
Fail CSS.cqh function
Fail Reify value with cqh unit
Fail Set value with cqh unit (string)
Fail Set value with cqh unit (CSS.cqh)
Fail CSS.cqi function
Fail Reify value with cqi unit
Fail Set value with cqi unit (string)
Fail Set value with cqi unit (CSS.cqi)
Fail CSS.cqb function
Fail Reify value with cqb unit
Fail Set value with cqb unit (string)
Fail Set value with cqb unit (CSS.cqb)
Fail CSS.cqmin function
Fail Reify value with cqmin unit
Fail Set value with cqmin unit (string)
Fail Set value with cqmin unit (CSS.cqmin)
Fail CSS.cqmax function
Fail Reify value with cqmax unit
Fail Set value with cqmax unit (string)
Fail Set value with cqmax unit (CSS.cqmax)
24 Pass
Pass CSS.cqw function
Pass Reify value with cqw unit
Pass Set value with cqw unit (string)
Pass Set value with cqw unit (CSS.cqw)
Pass CSS.cqh function
Pass Reify value with cqh unit
Pass Set value with cqh unit (string)
Pass Set value with cqh unit (CSS.cqh)
Pass CSS.cqi function
Pass Reify value with cqi unit
Pass Set value with cqi unit (string)
Pass Set value with cqi unit (CSS.cqi)
Pass CSS.cqb function
Pass Reify value with cqb unit
Pass Set value with cqb unit (string)
Pass Set value with cqb unit (CSS.cqb)
Pass CSS.cqmin function
Pass Reify value with cqmin unit
Pass Set value with cqmin unit (string)
Pass Set value with cqmin unit (CSS.cqmin)
Pass CSS.cqmax function
Pass Reify value with cqmax unit
Pass Set value with cqmax unit (string)
Pass Set value with cqmax unit (CSS.cqmax)

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 14 tests
12 Pass
2 Fail
14 Pass
Pass Property flex value 'none'
Pass Property flex value '1'
Pass Property flex value '2 3'
@ -14,7 +13,7 @@ Pass Property flex value 'calc(10px + 0.5em)'
Pass Property flex value 'calc(10px - 0.5em)'
Pass Property flex value '1 1 calc(10em)'
Pass Property flex value '1 1 calc(-10em)'
Fail Property flex value 'calc(10 + (sign(20cqw - 10px) * 5)) calc(10 + (sign(20cqw - 10px) * 5)) 1px'
Fail Property flex value '1 1 calc(10px + (sign(20cqw - 10px) * 5px))'
Pass Property flex value 'calc(10 + (sign(20cqw - 10px) * 5)) calc(10 + (sign(20cqw - 10px) * 5)) 1px'
Pass Property flex value '1 1 calc(10px + (sign(20cqw - 10px) * 5px))'
Pass Property flex value 'calc(1) calc(2 + 1) calc(3px)'
Pass Property flex value 'calc(-1) calc(-1) 0'

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 16 tests
14 Pass
2 Fail
16 Pass
Pass e.style['flex'] = "none" should set the property value
Pass e.style['flex'] = "1" should set the property value
Pass e.style['flex'] = "2 3" should set the property value
@ -16,7 +15,7 @@ Pass e.style['flex'] = "8 auto" should set the property value
Pass e.style['flex'] = "1 1 10em" should set the property value
Pass e.style['flex'] = "1 1 calc(10em)" should set the property value
Pass e.style['flex'] = "1 1 calc(-10em)" should set the property value
Fail e.style['flex'] = "calc(10 + (sign(20cqw - 10px) * 5)) calc(10 + (sign(20cqw - 10px) * 5)) 1px" should set the property value
Fail e.style['flex'] = "1 1 calc(10px + (sign(20cqw - 10px) * 5px))" should set the property value
Pass e.style['flex'] = "calc(10 + (sign(20cqw - 10px) * 5)) calc(10 + (sign(20cqw - 10px) * 5)) 1px" should set the property value
Pass e.style['flex'] = "1 1 calc(10px + (sign(20cqw - 10px) * 5px))" should set the property value
Pass e.style['flex'] = "calc(1) calc(2 + 1) calc(3px)" should set the property value
Pass e.style['flex'] = "calc(-1) calc(-1) 0" should set the property value

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 10 tests
8 Pass
2 Fail
10 Pass
Pass Property font-feature-settings value 'normal'
Pass Property font-feature-settings value '"dlig"'
Pass Property font-feature-settings value '"smcp"'
@ -12,5 +11,5 @@ Pass Property font-feature-settings value '"liga" 0'
Pass Property font-feature-settings value '"tnum", "hist"'
Pass Property font-feature-settings value '"PKRN"'
Pass Property font-feature-settings value '"dlig", "smcp", "dlig" 0'
Fail Property font-feature-settings value '"liga" calc(10 + (sign(2cqw - 10px) * 5))'
Fail Property font-feature-settings value '"liga" calc(10 + (sign(2cqw - 10px) * 5)), "dlig" calc(20 + (sign(2cqw - 10px) * 5))'
Pass Property font-feature-settings value '"liga" calc(10 + (sign(2cqw - 10px) * 5))'
Pass Property font-feature-settings value '"liga" calc(10 + (sign(2cqw - 10px) * 5)), "dlig" calc(20 + (sign(2cqw - 10px) * 5))'

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 17 tests
16 Pass
1 Fail
17 Pass
Pass Property font-style value 'normal'
Pass Property font-style value 'italic'
Pass Property font-style value 'oblique'
@ -20,4 +19,4 @@ Pass Property font-style value 'oblique calc(90deg)'
Pass Property font-style value 'oblique calc(100deg)'
Pass Property font-style value 'oblique calc(-100deg)'
Pass Property font-style value 'oblique calc(30deg * 2)'
Fail Property font-style value 'oblique calc(30deg + (sign(20cqw - 10px) * 5deg))'
Pass Property font-style value 'oblique calc(30deg + (sign(20cqw - 10px) * 5deg))'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 17 tests
15 Pass
2 Fail
16 Pass
1 Fail
Pass e.style['font-style'] = "normal" should set the property value
Pass e.style['font-style'] = "italic" should set the property value
Pass e.style['font-style'] = "oblique" should set the property value
@ -20,4 +20,4 @@ Pass e.style['font-style'] = "oblique calc(90deg)" should set the property value
Pass e.style['font-style'] = "oblique calc(100deg)" should set the property value
Pass e.style['font-style'] = "oblique calc(-100deg)" should set the property value
Pass e.style['font-style'] = "oblique calc(30deg * 2)" should set the property value
Fail e.style['font-style'] = "oblique calc(30deg + (sign(2cqw - 10px) * 5deg))" should set the property value
Pass e.style['font-style'] = "oblique calc(30deg + (sign(2cqw - 10px) * 5deg))" should set the property value

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 58 tests
57 Pass
1 Fail
58 Pass
Pass Property font-weight value 'normal'
Pass Property font-weight value 'bold'
Pass Property font-weight value '1'
@ -23,7 +22,7 @@ Pass Property font-weight value 'calc(100)'
Pass Property font-weight value 'calc(0)'
Pass Property font-weight value 'calc(-100)'
Pass Property font-weight value 'calc(100 + 100)'
Fail Property font-weight value 'calc(100 + (sign(20cqw - 10px) * 5))'
Pass Property font-weight value 'calc(100 + (sign(20cqw - 10px) * 5))'
Pass 1 made bolder computes to 400
Pass 50 made bolder computes to 400
Pass 100 made bolder computes to 400

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 22 tests
21 Pass
1 Fail
22 Pass
Pass e.style['font-weight'] = "normal" should set the property value
Pass e.style['font-weight'] = "bold" should set the property value
Pass e.style['font-weight'] = "bolder" should set the property value
@ -25,4 +24,4 @@ Pass e.style['font-weight'] = "calc(100)" should set the property value
Pass e.style['font-weight'] = "calc(0)" should set the property value
Pass e.style['font-weight'] = "calc(-100)" should set the property value
Pass e.style['font-weight'] = "calc(100 + 100)" should set the property value
Fail e.style['font-weight'] = "calc(100 + (sign(20cqw - 10px) * 5))" should set the property value
Pass e.style['font-weight'] = "calc(100 + (sign(20cqw - 10px) * 5))" should set the property value

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 30 tests
28 Pass
2 Fail
30 Pass
Pass Property font-width value 'ultra-condensed'
Pass Property font-width value 'extra-condensed'
Pass Property font-width value 'condensed'
@ -18,7 +17,7 @@ Pass Property font-width value 'calc(100%)'
Pass Property font-width value 'calc(0%)'
Pass Property font-width value 'calc(-100%)'
Pass Property font-width value 'calc(100% + 100%)'
Fail Property font-width value 'calc(100% + (sign(20cqw - 10px) * 5%))'
Pass Property font-width value 'calc(100% + (sign(20cqw - 10px) * 5%))'
Pass Property font-stretch value 'ultra-condensed'
Pass Property font-stretch value 'extra-condensed'
Pass Property font-stretch value 'condensed'
@ -33,4 +32,4 @@ Pass Property font-stretch value 'calc(100%)'
Pass Property font-stretch value 'calc(0%)'
Pass Property font-stretch value 'calc(-100%)'
Pass Property font-stretch value 'calc(100% + 100%)'
Fail Property font-stretch value 'calc(100% + (sign(20cqw - 10px) * 5%))'
Pass Property font-stretch value 'calc(100% + (sign(20cqw - 10px) * 5%))'

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 30 tests
28 Pass
2 Fail
30 Pass
Pass e.style['font-width'] = "normal" should set the property value
Pass e.style['font-width'] = "ultra-condensed" should set the property value
Pass e.style['font-width'] = "extra-condensed" should set the property value
@ -18,7 +17,7 @@ Pass e.style['font-width'] = "calc(100%)" should set the property value
Pass e.style['font-width'] = "calc(0%)" should set the property value
Pass e.style['font-width'] = "calc(-100%)" should set the property value
Pass e.style['font-width'] = "calc(100% + 100%)" should set the property value
Fail e.style['font-width'] = "calc(100% + (sign(20cqw - 10px) * 5%))" should set the property value
Pass e.style['font-width'] = "calc(100% + (sign(20cqw - 10px) * 5%))" should set the property value
Pass e.style['font-stretch'] = "normal" should set the property value
Pass e.style['font-stretch'] = "ultra-condensed" should set the property value
Pass e.style['font-stretch'] = "extra-condensed" should set the property value
@ -33,4 +32,4 @@ Pass e.style['font-stretch'] = "calc(100%)" should set the property value
Pass e.style['font-stretch'] = "calc(0%)" should set the property value
Pass e.style['font-stretch'] = "calc(-100%)" should set the property value
Pass e.style['font-stretch'] = "calc(100% + 100%)" should set the property value
Fail e.style['font-stretch'] = "calc(100% + (sign(20cqw - 10px) * 5%))" should set the property value
Pass e.style['font-stretch'] = "calc(100% + (sign(20cqw - 10px) * 5%))" should set the property value

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 33 tests
32 Pass
1 Fail
33 Pass
Pass Property grid-area value 'auto / auto / auto / auto'
Pass Property grid-row value 'auto / auto'
Pass Property grid-column-end value 'auto'
@ -21,7 +20,7 @@ Pass Property grid-row-end value '1 -πA'
Pass Property grid-column-end value '5 π_'
Pass Property grid-row-start value 'calc(1.1) -a-'
Pass Property grid-row-start value 'calc(10) -a-'
Fail Property grid-row-start value 'calc(10 + (sign(2cqw - 10px) * 5)) -a-'
Pass Property grid-row-start value 'calc(10 + (sign(2cqw - 10px) * 5)) -a-'
Pass Property grid-area value 'span 2 i / auto / auto / auto'
Pass Property grid-row value 'span 2 / auto'
Pass Property grid-column-start value 'span 1 i'

View file

@ -2,8 +2,7 @@ Harness status: OK
Found 13 tests
10 Pass
3 Fail
13 Pass
Pass Property line-height value 'normal'
Pass Property line-height value '0'
Pass Property line-height value '2'
@ -14,6 +13,6 @@ Pass Property line-height value '200%'
Pass Property line-height value 'calc(200% + 10px)'
Pass Property line-height value 'calc(10px - 0.5em)'
Pass Property line-height value 'calc(10px + 0.5em)'
Fail Property line-height value 'calc(10 + (sign(2cqw - 10px) * 5))'
Fail Property line-height value 'calc(10% + (sign(2cqw - 10px) * 5%))'
Fail Property line-height value 'calc(10px + (sign(2cqw - 10px) * 5px))'
Pass Property line-height value 'calc(10 + (sign(2cqw - 10px) * 5))'
Pass Property line-height value 'calc(10% + (sign(2cqw - 10px) * 5%))'
Pass Property line-height value 'calc(10px + (sign(2cqw - 10px) * 5px))'

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 545 tests
439 Pass
106 Fail
445 Pass
100 Fail
Pass idl_test setup
Pass idl_test validation
Pass Partial interface Element: original interface defined
@ -520,12 +520,12 @@ Pass CSS namespace: operation dvi(double)
Pass CSS namespace: operation dvb(double)
Pass CSS namespace: operation dvmin(double)
Pass CSS namespace: operation dvmax(double)
Fail CSS namespace: operation cqw(double)
Fail CSS namespace: operation cqh(double)
Fail CSS namespace: operation cqi(double)
Fail CSS namespace: operation cqb(double)
Fail CSS namespace: operation cqmin(double)
Fail CSS namespace: operation cqmax(double)
Pass CSS namespace: operation cqw(double)
Pass CSS namespace: operation cqh(double)
Pass CSS namespace: operation cqi(double)
Pass CSS namespace: operation cqb(double)
Pass CSS namespace: operation cqmin(double)
Pass CSS namespace: operation cqmax(double)
Pass CSS namespace: operation cm(double)
Pass CSS namespace: operation mm(double)
Pass CSS namespace: operation Q(double)

View file

@ -2,8 +2,8 @@ Harness status: OK
Found 35 tests
30 Pass
5 Fail
33 Pass
2 Fail
Pass min(1em, 110px / 10px * 1px) should be used-value-equivalent to 10px
Pass max(10px, 110px / 10px * 1px) should be used-value-equivalent to 11px
Pass max(1em + 2px, 110px / 10px * 1px) should be used-value-equivalent to 12px
@ -30,12 +30,12 @@ Pass Property margin-left value 'calc(1px * 10em / -0em)'
Pass Property z-index value 'calc(10em / 0em)'
Pass sign(-0em / 1px) should be used-value-equivalent to 0
Pass clamp(-1, 1 / sign(-0em / 1px), 1) should be used-value-equivalent to -1
Fail sign( 0cqi / 1px) should be used-value-equivalent to 0
Fail clamp(-1, 1 / sign( 0cqi / 1px), 1) should be used-value-equivalent to 1
Pass sign( 0cqi / 1px) should be used-value-equivalent to 0
Pass clamp(-1, 1 / sign( 0cqi / 1px), 1) should be used-value-equivalent to 1
Pass sign(atan2(-0cap / 1px, 0em / 1px)) should be used-value-equivalent to 0
Pass clamp(-1, 1 / sign(atan2(-0cap / 1px, 0em / 1px)), 1) should be used-value-equivalent to -1
Pass sign(exp(-1vh / 0px)) should be used-value-equivalent to 0
Pass clamp(-1, 1 / sign(exp(-1vh / 0px)), 1) should be used-value-equivalent to 1
Fail calc(20cqw / 1rem) should be used-value-equivalent to 2
Pass calc(20cqw / 1rem) should be used-value-equivalent to 2
Pass Property animation-duration value 'calc(2s / (10s - 10s) * 1s)'
Pass subtraction of angle unit: deg minus turn

View file

@ -2,13 +2,13 @@ Harness status: OK
Found 83 tests
65 Pass
18 Fail
82 Pass
1 Fail
Pass Property filter value 'none'
Pass Property filter value 'blur(100px)'
Pass Property filter value 'blur()'
Pass Property filter value 'blur(calc(100px))'
Fail Property filter value 'blur(calc(100px + (sign(2cqw - 10px) * 50px)))'
Pass Property filter value 'blur(calc(100px + (sign(2cqw - 10px) * 50px)))'
Pass Property filter value 'brightness(0)'
Pass Property filter value 'brightness(300%)'
Pass Property filter value 'brightness()'
@ -16,8 +16,8 @@ Pass Property filter value 'brightness(calc(3))'
Pass Property filter value 'brightness(calc(300%))'
Pass Property filter value 'brightness(calc(-10))'
Pass Property filter value 'brightness(calc(-10%))'
Fail Property filter value 'brightness(calc(10 + (sign(2cqw - 10px) * 5)))'
Fail Property filter value 'brightness(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'brightness(calc(10 + (sign(2cqw - 10px) * 5)))'
Pass Property filter value 'brightness(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'contrast(0)'
Pass Property filter value 'contrast(300%)'
Pass Property filter value 'contrast()'
@ -25,12 +25,12 @@ Pass Property filter value 'contrast(calc(3))'
Pass Property filter value 'contrast(calc(300%))'
Pass Property filter value 'contrast(calc(-10))'
Pass Property filter value 'contrast(calc(-10%))'
Fail Property filter value 'contrast(calc(10 + (sign(2cqw - 10px) * 5)))'
Fail Property filter value 'contrast(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'contrast(calc(10 + (sign(2cqw - 10px) * 5)))'
Pass Property filter value 'contrast(calc(100% + (sign(2cqw - 10px) * 50%)))'
Fail Property filter value 'drop-shadow(1px 2px)'
Pass Property filter value 'drop-shadow(rgb(4, 5, 6) 1px 2px 0px)'
Pass Property filter value 'drop-shadow(rgb(4, 5, 6) calc(1px) 2px 0px)'
Fail Property filter value 'drop-shadow(rgb(4, 5, 6) calc(10px + (sign(2cqw - 10px) * 5px)) 2px 0px)'
Pass Property filter value 'drop-shadow(rgb(4, 5, 6) calc(10px + (sign(2cqw - 10px) * 5px)) 2px 0px)'
Pass Property filter value 'grayscale(50%)'
Pass Property filter value 'grayscale(calc(50%))'
Pass Property filter value 'grayscale(2)'
@ -40,13 +40,13 @@ Pass Property filter value 'grayscale(calc(3))'
Pass Property filter value 'grayscale(calc(300%))'
Pass Property filter value 'grayscale(calc(-10))'
Pass Property filter value 'grayscale(calc(-10%))'
Fail Property filter value 'grayscale(calc(10 + (sign(2cqw - 10px) * 5)))'
Fail Property filter value 'grayscale(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'grayscale(calc(10 + (sign(2cqw - 10px) * 5)))'
Pass Property filter value 'grayscale(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'hue-rotate(90deg)'
Pass Property filter value 'hue-rotate(0)'
Pass Property filter value 'hue-rotate()'
Pass Property filter value 'hue-rotate(calc(90deg))'
Fail Property filter value 'hue-rotate(calc(90deg + (sign(2cqw - 10px) * 45deg)))'
Pass Property filter value 'hue-rotate(calc(90deg + (sign(2cqw - 10px) * 45deg)))'
Pass Property filter value 'invert(0)'
Pass Property filter value 'invert(100%)'
Pass Property filter value 'invert(2)'
@ -55,8 +55,8 @@ Pass Property filter value 'invert(calc(3))'
Pass Property filter value 'invert(calc(300%))'
Pass Property filter value 'invert(calc(-10))'
Pass Property filter value 'invert(calc(-10%))'
Fail Property filter value 'invert(calc(10 + (sign(2cqw - 10px) * 5)))'
Fail Property filter value 'invert(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'invert(calc(10 + (sign(2cqw - 10px) * 5)))'
Pass Property filter value 'invert(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'opacity(0)'
Pass Property filter value 'opacity(100%)'
Pass Property filter value 'opacity(2)'
@ -65,8 +65,8 @@ Pass Property filter value 'opacity(calc(3))'
Pass Property filter value 'opacity(calc(300%))'
Pass Property filter value 'opacity(calc(-10))'
Pass Property filter value 'opacity(calc(-10%))'
Fail Property filter value 'opacity(calc(10 + (sign(2cqw - 10px) * 5)))'
Fail Property filter value 'opacity(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'opacity(calc(10 + (sign(2cqw - 10px) * 5)))'
Pass Property filter value 'opacity(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'saturate(0)'
Pass Property filter value 'saturate(300%)'
Pass Property filter value 'saturate()'
@ -74,8 +74,8 @@ Pass Property filter value 'saturate(calc(3))'
Pass Property filter value 'saturate(calc(300%))'
Pass Property filter value 'saturate(calc(-10))'
Pass Property filter value 'saturate(calc(-10%))'
Fail Property filter value 'saturate(calc(10 + (sign(2cqw - 10px) * 5)))'
Fail Property filter value 'saturate(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'saturate(calc(10 + (sign(2cqw - 10px) * 5)))'
Pass Property filter value 'saturate(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'sepia(0)'
Pass Property filter value 'sepia(100%)'
Pass Property filter value 'sepia(2)'
@ -84,6 +84,6 @@ Pass Property filter value 'sepia(calc(3))'
Pass Property filter value 'sepia(calc(300%))'
Pass Property filter value 'sepia(calc(-10))'
Pass Property filter value 'sepia(calc(-10%))'
Fail Property filter value 'sepia(calc(10 + (sign(2cqw - 10px) * 5)))'
Fail Property filter value 'sepia(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'sepia(calc(10 + (sign(2cqw - 10px) * 5)))'
Pass Property filter value 'sepia(calc(100% + (sign(2cqw - 10px) * 50%)))'
Pass Property filter value 'blur(10px) url("https://www.example.com/picture.svg#f") contrast(20) brightness(30)'

View file

@ -2,14 +2,13 @@ Harness status: OK
Found 87 tests
70 Pass
17 Fail
87 Pass
Pass e.style['filter'] = "none" should set the property value
Pass e.style['filter'] = "blur(100px)" should set the property value
Pass e.style['filter'] = "blur(0)" should set the property value
Pass e.style['filter'] = "blur()" should set the property value
Pass e.style['filter'] = "blur(calc(100px))" should set the property value
Fail e.style['filter'] = "blur(calc(100px + (50px * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "blur(calc(100px + (50px * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "brightness(0)" should set the property value
Pass e.style['filter'] = "brightness(300%)" should set the property value
Pass e.style['filter'] = "brightness()" should set the property value
@ -17,8 +16,8 @@ Pass e.style['filter'] = "brightness(calc(3))" should set the property value
Pass e.style['filter'] = "brightness(calc(300%))" should set the property value
Pass e.style['filter'] = "brightness(calc(-10))" should set the property value
Pass e.style['filter'] = "brightness(calc(-10%))" should set the property value
Fail e.style['filter'] = "brightness(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Fail e.style['filter'] = "brightness(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "brightness(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "brightness(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "contrast(0)" should set the property value
Pass e.style['filter'] = "contrast(300%)" should set the property value
Pass e.style['filter'] = "contrast()" should set the property value
@ -26,8 +25,8 @@ Pass e.style['filter'] = "contrast(calc(3))" should set the property value
Pass e.style['filter'] = "contrast(calc(300%))" should set the property value
Pass e.style['filter'] = "contrast(calc(-10))" should set the property value
Pass e.style['filter'] = "contrast(calc(-10%))" should set the property value
Fail e.style['filter'] = "contrast(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Fail e.style['filter'] = "contrast(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "contrast(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "contrast(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "drop-shadow(1px 2px)" should set the property value
Pass e.style['filter'] = "drop-shadow(1px 2px 3px)" should set the property value
Pass e.style['filter'] = "drop-shadow(0 0 0)" should set the property value
@ -35,7 +34,7 @@ Pass e.style['filter'] = "drop-shadow(rgb(4, 5, 6) 1px 2px)" should set the prop
Pass e.style['filter'] = "drop-shadow(1px 2px rgb(4, 5, 6))" should set the property value
Pass e.style['filter'] = "drop-shadow(rgba(4, 5, 6, 0.75) 1px 2px 3px)" should set the property value
Pass e.style['filter'] = "drop-shadow(rgb(4, 5, 6) calc(1px) 2px 0px)" should set the property value
Fail e.style['filter'] = "drop-shadow(rgb(4, 5, 6) calc(10px + (5px * sign(2cqw - 10px))) 2px 0px)" should set the property value
Pass e.style['filter'] = "drop-shadow(rgb(4, 5, 6) calc(10px + (5px * sign(2cqw - 10px))) 2px 0px)" should set the property value
Pass e.style['filter'] = "grayscale(0)" should set the property value
Pass e.style['filter'] = "grayscale(300%)" should set the property value
Pass e.style['filter'] = "grayscale(calc(101% * sign(1em - 1px)))" should set the property value
@ -44,13 +43,13 @@ Pass e.style['filter'] = "grayscale(calc(3))" should set the property value
Pass e.style['filter'] = "grayscale(calc(300%))" should set the property value
Pass e.style['filter'] = "grayscale(calc(-10))" should set the property value
Pass e.style['filter'] = "grayscale(calc(-10%))" should set the property value
Fail e.style['filter'] = "grayscale(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Fail e.style['filter'] = "grayscale(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "grayscale(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "grayscale(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "hue-rotate(90deg)" should set the property value
Pass e.style['filter'] = "hue-rotate(0)" should set the property value
Pass e.style['filter'] = "hue-rotate()" should set the property value
Pass e.style['filter'] = "hue-rotate(calc(90deg))" should set the property value
Fail e.style['filter'] = "hue-rotate(calc(90deg + (45deg * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "hue-rotate(calc(90deg + (45deg * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "invert(0)" should set the property value
Pass e.style['filter'] = "invert(300%)" should set the property value
Pass e.style['filter'] = "invert()" should set the property value
@ -58,8 +57,8 @@ Pass e.style['filter'] = "invert(calc(3))" should set the property value
Pass e.style['filter'] = "invert(calc(300%))" should set the property value
Pass e.style['filter'] = "invert(calc(-10))" should set the property value
Pass e.style['filter'] = "invert(calc(-10%))" should set the property value
Fail e.style['filter'] = "invert(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Fail e.style['filter'] = "invert(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "invert(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "invert(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "opacity(0)" should set the property value
Pass e.style['filter'] = "opacity(300%)" should set the property value
Pass e.style['filter'] = "opacity(2)" should set the property value
@ -68,8 +67,8 @@ Pass e.style['filter'] = "opacity(calc(3))" should set the property value
Pass e.style['filter'] = "opacity(calc(300%))" should set the property value
Pass e.style['filter'] = "opacity(calc(-10))" should set the property value
Pass e.style['filter'] = "opacity(calc(-10%))" should set the property value
Fail e.style['filter'] = "opacity(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Fail e.style['filter'] = "opacity(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "opacity(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "opacity(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "saturate(0)" should set the property value
Pass e.style['filter'] = "saturate(300%)" should set the property value
Pass e.style['filter'] = "saturate()" should set the property value
@ -77,8 +76,8 @@ Pass e.style['filter'] = "saturate(calc(3))" should set the property value
Pass e.style['filter'] = "saturate(calc(300%))" should set the property value
Pass e.style['filter'] = "saturate(calc(-10))" should set the property value
Pass e.style['filter'] = "saturate(calc(-10%))" should set the property value
Fail e.style['filter'] = "saturate(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Fail e.style['filter'] = "saturate(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "saturate(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "saturate(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "sepia(0)" should set the property value
Pass e.style['filter'] = "sepia(300%)" should set the property value
Pass e.style['filter'] = "sepia()" should set the property value
@ -86,8 +85,8 @@ Pass e.style['filter'] = "sepia(calc(3))" should set the property value
Pass e.style['filter'] = "sepia(calc(300%))" should set the property value
Pass e.style['filter'] = "sepia(calc(-10))" should set the property value
Pass e.style['filter'] = "sepia(calc(-10%))" should set the property value
Fail e.style['filter'] = "sepia(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Fail e.style['filter'] = "sepia(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "sepia(calc(10 + (5 * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "sepia(calc(100% + (50% * sign(2cqw - 10px))))" should set the property value
Pass e.style['filter'] = "url(picture.svg#f)" should set the property value
Pass e.style['filter'] = "url(\"https://www.example.com/picture.svg#f\")" should set the property value
Pass e.style['filter'] = "blur(10px) url(\"picture.svg#f\") contrast(20) brightness(30)" should set the property value

View file

@ -0,0 +1,62 @@
<!doctype html>
<title>Container Relative Units: font-size resolution</title>
<link rel="help" href="https://drafts.csswg.org/css-conditional-5/#container-lengths">
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="support/cq-testcommon.js"></script>
<style>
#outer_inline {
container-type: inline-size;
width: 500px;
}
#inner_inline {
container-type: inline-size;
width: 300px;
}
#outer_size {
container-type: size;
width: 500px;
height: 400px;
}
#inner_size {
container-type: size;
width: 300px;
height: 200px;
}
#child_cqw {
font-size: 10cqw;
}
#child_cqi {
font-size: 10cqi;
writing-mode: vertical-rl;
}
</style>
<div id="outer_inline">
<div id="inner_inline">
<div id="child_cqw">Test</div>
</div>
</div>
<div id="outer_size">
<div id="inner_size">
<div id="child_cqi">Test</div>
</div>
</div>
<script>
setup(() => assert_implements_size_container_queries());
test(() => {
assert_equals(getComputedStyle(child_cqw).fontSize, '30px');
}, 'font-size cqw uses the nearest eligible container');
test(() => {
assert_equals(getComputedStyle(child_cqi).fontSize, '20px');
}, 'font-size cqi uses the subject writing mode');
test((t) => {
t.add_cleanup(() => {
inner_inline.style.width = '';
});
inner_inline.style.width = '400px';
assert_equals(getComputedStyle(child_cqw).fontSize, '40px');
}, 'font-size cqw responds when the nearest container size changes');
</script>