Specification notes and quirks
This repository aims to stay very close to the DOM specification, but server-side PHP is not a browser, and PHP’s own DOM extension has some constraints of its own.
These are the main points worth keeping in mind.
1. Some browser functionality is intentionally unavailable
Anything that depends on browser runtime state, rendering, media playback, user input devices, or browsing context cannot be implemented faithfully on the server.
When code reaches one of those areas, the library throws ClientSideOnlyFunctionalityException.
That is expected behaviour, not an incomplete edge case.
2. Element typing is specification-shaped, but still PHP-friendly
The library exposes HTML element types through ElementType, rather than through a huge inheritance tree of concrete PHP element subclasses that you would check with instanceof.
In practice that means we often write:
if($element->elementType === GT\Dom\ElementType::HTMLInputElement) {
// ...
}
instead of depending on a separate PHP class per HTML tag.
3. tagName casing needs care
One of the long-standing unavoidable differences documented in the project is element name casing.
In normal HTML usage, the library creates HTML elements in lowercase and works consistently with that form. The broader point is that tag-name casing should not be treated as a portability boundary in application logic. Prefer selectors, element type checks, and DOM structure over casing assumptions.
4. HTMLDocument normalises the document shape
If the incoming HTML does not contain full document structure, the constructor ensures the document still has:
<html><head><body>
That is helpful for server-side work, but it also means serialised output may be more complete than the input string you started with.
5. Some collections are live
This catches people out more in PHP than in JavaScript because we are often less used to keeping long-lived collection objects around.
HTMLCollectionis livequerySelectorAll()returns a staticNodeListgetElementsByName()returns a liveNodeList
If a collection appears to change “by itself”, that is usually just the expected DOM behaviour, and completely consistent with using the document in a browser with JavaScript.
6. Invalid selectors fail explicitly
Selector methods are translated internally to XPath. If the selector string is malformed, the library throws XPathQueryException.
That is usually preferable to silent failure because it makes bad selectors obvious during development.
7. Writing to documents is not a general replacement for DOM manipulation
Document::open() and write() exist, but in this implementation they are mainly stream-oriented helpers for HTML documents.
For most application code, direct DOM calls such as append, replaceWith, innerText, innerHTML, and createElement are clearer and less surprising.
8. MDN remains the reference for DOM semantics
This guide deliberately does not duplicate the whole DOM API surface.
When you need exact behaviour for a property or method, use MDN: