diff --git a/Base/home/anon/www/first-child.html b/Base/home/anon/www/first-child.html
new file mode 100644
index 0000000000..553d814668
--- /dev/null
+++ b/Base/home/anon/www/first-child.html
@@ -0,0 +1,24 @@
+
+
+:first-child test
+
+
+
+
+
This text is selected!
+
This text isn't selected.
+
+
+
+
This text isn't selected: it's not a `p`.
+
This text isn't selected.
+
+
+
+
diff --git a/Base/home/anon/www/last-child.html b/Base/home/anon/www/last-child.html
new file mode 100644
index 0000000000..562d85aac4
--- /dev/null
+++ b/Base/home/anon/www/last-child.html
@@ -0,0 +1,23 @@
+
+
+:last-child test
+
+
+
+
+
This text isn't selected.
+
This text is selected!
+
+
+
+
This text isn't selected.
+
This text isn't selected: it's not a `p`.
+
+
+
diff --git a/Base/home/anon/www/welcome.html b/Base/home/anon/www/welcome.html
index d11541fc1c..1fbecdd0ca 100644
--- a/Base/home/anon/www/welcome.html
+++ b/Base/home/anon/www/welcome.html
@@ -24,6 +24,8 @@ h1 {
Some small test pages:
- small
+ - :first-child
+ - :last-child
- form
- borders
- css
diff --git a/Libraries/LibHTML/CSS/Selector.h b/Libraries/LibHTML/CSS/Selector.h
index 288f16a9a5..e0e68e2be6 100644
--- a/Libraries/LibHTML/CSS/Selector.h
+++ b/Libraries/LibHTML/CSS/Selector.h
@@ -20,6 +20,8 @@ public:
None,
Link,
Hover,
+ FirstChild,
+ LastChild,
};
PseudoClass pseudo_class { PseudoClass::None };
diff --git a/Libraries/LibHTML/CSS/SelectorEngine.cpp b/Libraries/LibHTML/CSS/SelectorEngine.cpp
index f33018607d..affedd2128 100644
--- a/Libraries/LibHTML/CSS/SelectorEngine.cpp
+++ b/Libraries/LibHTML/CSS/SelectorEngine.cpp
@@ -27,6 +27,14 @@ bool matches(const Selector::SimpleSelector& component, const Element& element)
if (!matches_hover_pseudo_class(element))
return false;
break;
+ case Selector::SimpleSelector::PseudoClass::FirstChild:
+ if (element.previous_element_sibling())
+ return false;
+ break;
+ case Selector::SimpleSelector::PseudoClass::LastChild:
+ if (element.next_element_sibling())
+ return false;
+ break;
}
switch (component.attribute_match_type) {
diff --git a/Libraries/LibHTML/Parser/CSSParser.cpp b/Libraries/LibHTML/Parser/CSSParser.cpp
index 786c713591..6cfc93c75a 100644
--- a/Libraries/LibHTML/Parser/CSSParser.cpp
+++ b/Libraries/LibHTML/Parser/CSSParser.cpp
@@ -321,6 +321,10 @@ public:
simple_selector.pseudo_class = Selector::SimpleSelector::PseudoClass::Link;
else if (pseudo_name == "hover")
simple_selector.pseudo_class = Selector::SimpleSelector::PseudoClass::Hover;
+ else if (pseudo_name == "first-child")
+ simple_selector.pseudo_class = Selector::SimpleSelector::PseudoClass::FirstChild;
+ else if (pseudo_name == "last-child")
+ simple_selector.pseudo_class = Selector::SimpleSelector::PseudoClass::LastChild;
}
return simple_selector;