diff --git a/Base/home/anon/www/root.html b/Base/home/anon/www/root.html
new file mode 100644
index 0000000000..331ee74880
--- /dev/null
+++ b/Base/home/anon/www/root.html
@@ -0,0 +1,14 @@
+
+
+
+ :root test
+
+
+
+ Background will be red.
+
+
diff --git a/Base/home/anon/www/welcome.html b/Base/home/anon/www/welcome.html
index 9ee1bac2c9..48f42c30df 100644
--- a/Base/home/anon/www/welcome.html
+++ b/Base/home/anon/www/welcome.html
@@ -50,6 +50,7 @@ span#ua {
:last-child
:only-child
:empty
+ :root
form
borders
css
diff --git a/Libraries/LibWeb/CSS/Selector.h b/Libraries/LibWeb/CSS/Selector.h
index 3b6f7c1552..f1ff146582 100644
--- a/Libraries/LibWeb/CSS/Selector.h
+++ b/Libraries/LibWeb/CSS/Selector.h
@@ -53,6 +53,7 @@ public:
LastChild,
OnlyChild,
Empty,
+ Root,
};
PseudoClass pseudo_class { PseudoClass::None };
diff --git a/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Libraries/LibWeb/CSS/SelectorEngine.cpp
index e250896784..8b26beff74 100644
--- a/Libraries/LibWeb/CSS/SelectorEngine.cpp
+++ b/Libraries/LibWeb/CSS/SelectorEngine.cpp
@@ -75,6 +75,10 @@ bool matches(const Selector::SimpleSelector& component, const Element& element)
if (element.first_child_of_type() || element.first_child_of_type())
return false;
break;
+ case Selector::SimpleSelector::PseudoClass::Root:
+ if (!element.is_html_element())
+ return false;
+ break;
}
switch (component.attribute_match_type) {
diff --git a/Libraries/LibWeb/Parser/CSSParser.cpp b/Libraries/LibWeb/Parser/CSSParser.cpp
index 5af4284381..84d7160520 100644
--- a/Libraries/LibWeb/Parser/CSSParser.cpp
+++ b/Libraries/LibWeb/Parser/CSSParser.cpp
@@ -414,6 +414,8 @@ public:
simple_selector.pseudo_class = Selector::SimpleSelector::PseudoClass::OnlyChild;
else if (pseudo_name.equals_ignoring_case("empty"))
simple_selector.pseudo_class = Selector::SimpleSelector::PseudoClass::Empty;
+ else if (pseudo_name.equals_ignoring_case("root"))
+ simple_selector.pseudo_class = Selector::SimpleSelector::PseudoClass::Root;
}
if (index == index_at_start) {