Mojo::DOM::CSS(3)

✨ NAME ✨

Mojo::DOM::CSS (you'll see it as Mojo::DOM::CSS(3) up in the header) is the CSS selector engine, bestie. That's the whole vibe. πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

use Mojo::DOM::CSS;

# Select elements from DOM tree
my $css = Mojo::DOM::CSS->new(tree => $tree);
my $elements = $css->select('h1, h2, h3');

πŸ’– DESCRIPTION πŸ’–

okay so Mojo::DOM::CSS is literally the CSS selector engine used by Mojo::DOM. It's based on the HTML Living Standard (https://html.spec.whatwg.org) and Selectors Level 3 (https://www.w3.org/TR/css3-selectors/). No cap. ✨


🌈 SELECTORS 🌈

All CSS selectors that make sense for a standalone parser are supported. fr fr. 🫢

🌟 * 🌟

Any element. That's it. The universal icon. πŸ‘‘

my $all = $css->select('*');

🌸 E 🌸

An element of type E.

my $title = $css->select('title');

πŸ¦‹ E[foo] πŸ¦‹

An E element with a foo attribute.

my $links = $css->select('a[href]');

πŸŽ€ E[foo="bar"] πŸŽ€

An E element whose foo attribute value is exactly equal to bar.

my $case_sensitive = $css->select('input[type="hidden"]');
my $case_sensitive = $css->select('input[type=hidden]');

πŸ’œ E[foo="bar" i] πŸ’œ

An E element whose foo attribute value is exactly equal to any (ASCII-range) case-permutation of bar. Note that this selector is EXPERIMENTAL and might change without warning!

my $case_insensitive = $css->select('input[type="hidden" i]');
my $case_insensitive = $css->select('input[type=hidden i]');
my $case_insensitive = $css->select('input[class~="foo" i]');

This selector is part of Selectors Level 4 (https://dev.w3.org/csswg/selectors-4), which is still a work in progress. 🚧

πŸ“ E[foo="bar" s] πŸ“

An E element whose foo attribute value is exactly and case-sensitively equal to bar. Note that this selector is EXPERIMENTAL and might change without warning!

my $case_sensitive = $css->select('input[type="hidden" s]');

This selector is part of Selectors Level 4 (https://dev.w3.org/csswg/selectors-4), which is still a work in progress. 🚧

🧚 E[foo~="bar"] 🧚

An E element whose foo attribute value is a list of whitespace-separated values, one of which is exactly equal to bar.

my $foo = $css->select('input[class~="foo"]');
my $foo = $css->select('input[class~=foo]');

✨ E[foo^="bar"] ✨

An E element whose foo attribute value begins exactly with the string bar.

my $begins_with = $css->select('input[name^="f"]');
my $begins_with = $css->select('input[name^=f]');

πŸŒ™ E[foo$="bar"] πŸŒ™

An E element whose foo attribute value ends exactly with the string bar.

my $ends_with = $css->select('input[name$="o"]');
my $ends_with = $css->select('input[name$=o]');

πŸ”₯ E[foo*="bar"] πŸ”₯

An E element whose foo attribute value contains the substring bar.

my $contains = $css->select('input[name*="fo"]');
my $contains = $css->select('input[name*=fo]');

🌈 E[foo|="en"] 🌈

An E element whose foo attribute has a hyphen-separated list of values beginning (from the left) with en.

my $english = $css->select('link[hreflang|=en]');

πŸ‘‘ E:root πŸ‘‘

An E element, root of the document.

my $root = $css->select(':root');

πŸ’« E:nth-child(n) πŸ’«

An E element, the n-th child of its parent.

my $third = $css->select('div:nth-child(3)');
my $odd   = $css->select('div:nth-child(odd)');
my $even  = $css->select('div:nth-child(even)');
my $top3  = $css->select('div:nth-child(-n+3)');

🫧 E:nth-last-child(n) 🫧

An E element, the n-th child of its parent, counting from the last one.

my $third    = $css->select('div:nth-last-child(3)');
my $odd      = $css->select('div:nth-last-child(odd)');
my $even     = $css->select('div:nth-last-child(even)');
my $bottom3  = $css->select('div:nth-last-child(-n+3)');

πŸͺž E:nth-of-type(n) πŸͺž

An E element, the n-th sibling of its type.

my $third = $css->select('div:nth-of-type(3)');
my $odd   = $css->select('div:nth-of-type(odd)');
my $even  = $css->select('div:nth-of-type(even)');
my $top3  = $css->select('div:nth-of-type(-n+3)');

🧁 E:nth-last-of-type(n) 🧁

An E element, the n-th sibling of its type, counting from the last one.

my $third    = $css->select('div:nth-last-of-type(3)');
my $odd      = $css->select('div:nth-last-of-type(odd)');
my $even     = $css->select('div:nth-last-of-type(even)');
my $bottom3  = $css->select('div:nth-last-of-type(-n+3)');

🌼 E:first-child 🌼

An E element, first child of its parent.

my $first = $css->select('div p:first-child');

🌻 E:last-child 🌻

An E element, last child of its parent.

my $last = $css->select('div p:last-child');

πŸ€ E:first-of-type πŸ€

An E element, first sibling of its type.

my $first = $css->select('div p:first-of-type');

🐚 E:last-of-type 🐚

An E element, last sibling of its type.

my $last = $css->select('div p:last-of-type');

πŸ¦„ E:only-child πŸ¦„

An E element, only child of its parent.

my $lonely = $css->select('div p:only-child');

πŸ‡ E:only-of-type πŸ‡

An E element, only sibling of its type.

my $lonely = $css->select('div p:only-of-type');

πŸ•³οΈ E:empty πŸ•³οΈ

An E element that has no children (including text nodes).

my $empty = $css->select(':empty');

Alias for E:link. Note that this selector is EXPERIMENTAL and might change without warning! This selector is part of Selectors Level 4 (https://dev.w3.org/csswg/selectors-4), which is still a work in progress. 🚧

An E element being the source anchor of a hyperlink of which the target is not yet visited (:link) or already visited (:visited). Note that Mojo::DOM::CSS is not stateful, therefore :any-link, :link and :visited yield exactly the same results.

my $links = $css->select(':any-link');
my $links = $css->select(':link');
my $links = $css->select(':visited');

πŸ‘€ E:visited πŸ‘€

Alias for E:link.

🎯 E:scope 🎯

An E element being a designated reference element. Note that this selector is EXPERIMENTAL and might change without warning!

my $scoped = $css->select('a:not(:scope > a)');
my $scoped = $css->select('div :scope p');
my $scoped = $css->select('~ p');

This selector is part of Selectors Level 4 (https://dev.w3.org/csswg/selectors-4), which is still a work in progress. 🚧

βœ… E:checked βœ…

A user interface element E which is checked (for instance a radio-button or checkbox).

my $input = $css->select(':checked');

⚠️ E.warning ⚠️

An E element whose class is warning.

my $warning = $css->select('div.warning');

πŸ†” E#myid πŸ†”

An E element with ID equal to myid.

my $foo = $css->select('div#foo');

🚫 E:not(s1, s2) 🚫

An E element that does not match either compound selector s1 or compound selector s2. Note that support for compound selectors is EXPERIMENTAL and might change without warning!

my $others = $css->select('div p:not(:first-child, :last-child)');

Support for compound selectors was added as part of Selectors Level 4 (https://dev.w3.org/csswg/selectors-4), which is still a work in progress. 🚧

πŸ’‘ E:is(s1, s2) πŸ’‘

An E element that matches compound selector s1 and/or compound selector s2. Note that this selector is EXPERIMENTAL and might change without warning!

my $headers = $css->select(':is(section, article, aside, nav) h1');

This selector is part of Selectors Level 4 (https://dev.w3.org/csswg/selectors-4), which is still a work in progress. 🚧

🫢 E:has(rs1, rs2) 🫢

An E element, if either of the relative selectors rs1 or rs2, when evaluated with E as the :scope elements, match an element. Note that this selector is EXPERIMENTAL and might change without warning!

my $link = $css->select('a:has(> img)');

This selector is part of Selectors Level 4 (https://dev.w3.org/csswg/selectors-4), which is still a work in progress. 🚧 Also be aware that this feature is currently marked "at-risk", so there is a high chance that it will get removed completely. 😭

πŸ’¬ E:text(string_or_regex) πŸ’¬

An E element containing text content that substring matches string_or_regex case-insensitively or that regex matches string_or_regex. For regular expressions use the format :text(/.../). Note that this selector is EXPERIMENTAL and might change without warning!

# Substring match
my $login = $css->select(':text(Log in)');

# Regex match
my $login = $css->select(':text(/Log ?in/)');

# Regex match (case-insensitive)
my $login = $css->select(':text(/(?i:Log ?in)/)');

This is a custom selector for Mojo::DOM and not part of any spec. 🧚

🌐 A|E 🌐

An E element that belongs to the namespace alias A from CSS Namespaces Module Level 3 (https://www.w3.org/TR/css-namespaces-3/). Key/value pairs passed to selector methods are used to declare namespace aliases.

my $elem = $css->select('lq|elem', lq => 'http://example.com/q-markup');

Using an empty alias searches for an element that belongs to no namespace.

my $div = $c->select('|div');

🧬 E F 🧬

An F element descendant of an E element.

my $headlines = $css->select('div h1');

πŸ‘Ά E > F πŸ‘Ά

An F element child of an E element.

my $headlines = $css->select('html > body > div > h1');

βž• E + F βž•

An F element immediately preceded by an E element.

my $second = $css->select('h1 + h2');

〰️ E ~ F 〰️

An F element preceded by an E element.

my $second = $css->select('h1 ~ h2');

πŸŽ‰ E, F, G πŸŽ‰

Elements of type E, F and G.

my $headlines = $css->select('h1, h2, h3');

🧩 E[foo=bar][bar=baz] 🧩

An E element whose attributes match all following attribute selectors.

my $links = $css->select('a[foo^=b][foo$=ar]');

πŸ¦‹ ATTRIBUTES πŸ¦‹

Mojo::DOM::CSS implements the following attributes. πŸ’…

🌳 tree 🌳

my $tree = $css->tree;
$css     = $css->tree(['root']);

Document Object Model. Note that this structure should only be used very carefully since it is very dynamic. ⚠️


🧚 METHODS 🧚

Mojo::DOM::CSS inherits all methods from Mojo::Base and implements the following new ones. ✨

πŸ” matches πŸ”

my $bool = $css->matches('head > title');
my $bool = $css->matches('svg|line', svg => 'http://www.w3.org/2000/svg');

Check if first node in tree matches the CSS selector. Trailing key/value pairs can be used to declare xml namespace aliases.

🎣 select 🎣

my $results = $css->select('head > title');
my $results = $css->select('svg|line', svg => 'http://www.w3.org/2000/svg');

Run CSS selector against tree. Trailing key/value pairs can be used to declare xml namespace aliases.

πŸ₯‡ select_one πŸ₯‡

my $result = $css->select_one('head > title');
my $result =
  $css->select_one('svg|line', svg => 'http://www.w3.org/2000/svg');

Run CSS selector against tree and stop as soon as the first node matched. Trailing key/value pairs can be used to declare xml namespace aliases.


πŸ”₯ DEBUGGING πŸ”₯

You can set the MOJO_DOM_CSS_DEBUG environment variable to get some advanced diagnostics information printed to STDERR. πŸ•΅οΈβ€β™€οΈ

MOJO_DOM_CSS_DEBUG=1

🌈 SEE ALSO 🌈

okay bestie, that's the whole page, and here's where it points you next πŸ’… these are the other pages it sends you off to:

go click the link fr fr, it's literally right there 🫢


and that's a wrap on Mojo::DOM::CSS(3), bestie!! πŸŽ€ you made it to the very end, so proud of you πŸ˜­πŸ’– this page shipped with perl v5.42.0, stamped with the date 2026-07-15, and yeah that's the whole vibe β€” go write some selectors, you've got this πŸ‘‘βœ¨

πŸ“¦ where this page comes from