diff --git a/Base/res/html/misc/overflow.html b/Base/res/html/misc/overflow.html
new file mode 100644
index 0000000000..60a8e99a16
--- /dev/null
+++ b/Base/res/html/misc/overflow.html
@@ -0,0 +1,180 @@
+
+
+
+
+ CSS Overflow Test
+
+
+
+ Single-value 'overflow' property
+
+ Overflow: inherit
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: initial
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: auto
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: clip
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: hidden
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: scroll
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: visible
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Two-value 'overflow' property
+
+ Overflow: auto hidden
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: hidden auto
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: scroll clip
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: clip scroll
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Overflow: visible hidden
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ Separate 'overflow-x' / 'overflow-y' property
+
+ overflow-x: auto, overflow-y: hidden
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ overflow-x: hidden, overflow-y: auto
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ overflow-x: scroll, overflow-y: clip
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ overflow-y: scroll
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+ overflow-x: visible
+
+
Heading extends outside the box!
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
Hello this is some text
+
+
+
diff --git a/Base/res/html/misc/welcome.html b/Base/res/html/misc/welcome.html
index d958d22bc2..50f717bc8e 100644
--- a/Base/res/html/misc/welcome.html
+++ b/Base/res/html/misc/welcome.html
@@ -105,6 +105,7 @@
Floating boxes
Floating boxes with overflow=hidden
Float clearing
+ Overflow
Features
Basic functionality
css colors
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
index 0240cfc322..6f82f9755b 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
@@ -2503,6 +2503,47 @@ RefPtr Parser::parse_list_style_value(ParsingContext const& context,
return ListStyleStyleValue::create(list_position.release_nonnull(), list_image.release_nonnull(), list_type.release_nonnull());
}
+RefPtr Parser::parse_overflow_value(ParsingContext const& context, Vector const& component_values)
+{
+ auto is_overflow = [](StyleValue const& value) -> bool {
+ switch (value.to_identifier()) {
+ case ValueID::Auto:
+ case ValueID::Clip:
+ case ValueID::Hidden:
+ case ValueID::Scroll:
+ case ValueID::Visible:
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ if (component_values.size() == 1) {
+ auto maybe_value = parse_css_value(context, PropertyID::Overflow, component_values.first());
+ if (!maybe_value)
+ return nullptr;
+ auto value = maybe_value.release_nonnull();
+ if (is_overflow(*value))
+ return OverflowStyleValue::create(value, value);
+ return nullptr;
+ }
+
+ if (component_values.size() == 2) {
+ auto maybe_x_value = parse_css_value(context, PropertyID::OverflowX, component_values[0]);
+ auto maybe_y_value = parse_css_value(context, PropertyID::OverflowY, component_values[1]);
+
+ if (!maybe_x_value || !maybe_y_value)
+ return nullptr;
+ auto x_value = maybe_x_value.release_nonnull();
+ auto y_value = maybe_y_value.release_nonnull();
+ if (!is_overflow(x_value) || !is_overflow(y_value))
+ return nullptr;
+ return OverflowStyleValue::create(x_value, y_value);
+ }
+
+ return nullptr;
+}
+
RefPtr Parser::parse_text_decoration_value(ParsingContext const& context, Vector const& component_values)
{
auto is_text_decoration_line = [](StyleValue const& value) -> bool {
@@ -2650,6 +2691,10 @@ RefPtr Parser::parse_css_value(PropertyID property_id, TokenStream parse_flex_flow_value(ParsingContext const&, Vector const&);
static RefPtr parse_font_value(ParsingContext const&, Vector const&);
static RefPtr parse_list_style_value(ParsingContext const&, Vector const&);
+ static RefPtr parse_overflow_value(ParsingContext const&, Vector const&);
static RefPtr parse_text_decoration_value(ParsingContext const&, Vector const&);
// calc() parsing, according to https://www.w3.org/TR/css-values-3/#calc-syntax
diff --git a/Userland/Libraries/LibWeb/CSS/StyleResolver.cpp b/Userland/Libraries/LibWeb/CSS/StyleResolver.cpp
index 669f6842b7..3d6181741f 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleResolver.cpp
+++ b/Userland/Libraries/LibWeb/CSS/StyleResolver.cpp
@@ -220,8 +220,17 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
}
if (property_id == CSS::PropertyID::Overflow) {
- style.set_property(CSS::PropertyID::OverflowX, value);
- style.set_property(CSS::PropertyID::OverflowY, value);
+ if (value.is_overflow()) {
+ auto& overflow = static_cast(value);
+ style.set_property(CSS::PropertyID::OverflowX, overflow.overflow_x());
+ style.set_property(CSS::PropertyID::OverflowY, overflow.overflow_y());
+ return;
+ }
+ if (value.is_builtin()) {
+ style.set_property(CSS::PropertyID::OverflowX, value);
+ style.set_property(CSS::PropertyID::OverflowY, value);
+ return;
+ }
return;
}
diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h
index 66e1dd3f09..4a190f5e76 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleValue.h
+++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h
@@ -237,6 +237,7 @@ public:
FlexFlow,
Font,
ListStyle,
+ Overflow,
TextDecoration,
};
@@ -262,6 +263,7 @@ public:
bool is_flex_flow() const { return type() == Type::FlexFlow; }
bool is_font() const { return type() == Type::Font; }
bool is_list_style() const { return type() == Type::ListStyle; }
+ bool is_overflow() const { return type() == Type::Overflow; }
bool is_text_decoration() const { return type() == Type::TextDecoration; }
bool is_builtin() const { return is_inherit() || is_initial(); }
@@ -902,6 +904,34 @@ private:
NonnullRefPtr m_style_type;
};
+class OverflowStyleValue final : public StyleValue {
+public:
+ static NonnullRefPtr create(NonnullRefPtr overflow_x, NonnullRefPtr overflow_y)
+ {
+ return adopt_ref(*new OverflowStyleValue(overflow_x, overflow_y));
+ }
+ virtual ~OverflowStyleValue() override { }
+
+ NonnullRefPtr overflow_x() const { return m_overflow_x; }
+ NonnullRefPtr overflow_y() const { return m_overflow_y; }
+
+ virtual String to_string() const override
+ {
+ return String::formatted("{} {}", m_overflow_x->to_string(), m_overflow_y->to_string());
+ }
+
+private:
+ OverflowStyleValue(NonnullRefPtr overflow_x, NonnullRefPtr overflow_y)
+ : StyleValue(Type::Overflow)
+ , m_overflow_x(overflow_x)
+ , m_overflow_y(overflow_y)
+ {
+ }
+
+ NonnullRefPtr m_overflow_x;
+ NonnullRefPtr m_overflow_y;
+};
+
class TextDecorationStyleValue final : public StyleValue {
public:
static NonnullRefPtr create(