Skip to content

blitz-dom / blitz-html: quirks mode from the doctype is never applied

Generated from repros/blitz-dom-quirks-mode-ignored/README.md when the site was built at 7aa23e2.

No workaround; niso always creates no-quirks documents (crates/niso-core/src/lib.rs:168-172). Recorded because it is the other half of the doctype problem: pages without a standards doctype lay out differently in browsers.

html5ever computes the quirks mode from the doctype and calls TreeSink::set_quirks_mode; blitz-html stores it in DocumentHtmlParser::quirks_mode (packages/blitz-html/src/html_sink.rs:55,296-297) and nothing reads it. Everything else hardcodes QuirksMode::NoQuirks: the stylist (document.rs:504), TDocument::quirks_mode (stylo.rs:282-284, used by query_selector), and style attribute parsing (node/element.rs:707).

An HTML 4.01 Transitional doctype without a system identifier puts the document in quirks mode, where class selectors match ASCII case-insensitively and width: 100 (unitless) is 100px in a style attribute:

quirks-mode document (HTML 4.01 Transitional doctype, no system id)
query_selector(".FOO") on class="foo": expected Some(NodeId(5v1)), actual None
width of style="width:100": expected 100, actual 800
Terminal window
CARGO_TARGET_DIR=~/.capy/work/repro-target cargo run

Exit status 1 while the bug reproduces, 0 once fixed. On Ubuntu, blitz needs sudo apt-get install -y libfontconfig-dev pkg-config.

Reproduces. Blitz main was at be60597f67b3cece0456d26e8d7ff5a88600bbc5 when tested (2026-11-08, git ls-remote https://github.com/DioxusLabs/blitz HEAD), the same commit niso pins, so the pinned result is also the main result.

None found in DioxusLabs/blitz (searched quirks, QuirksMode, quirks mode). Stylo already supports quirks (servo/stylo#333 adopted the “tables inherit color from body” quirk); blitz just never passes the mode in.

Title: Quirks mode is computed by the parser but never applied (always NoQuirks)

Body:

DocumentHtmlParser::set_quirks_mode stores html5ever’s quirks mode, but nothing reads it: the stylist, TDocument::quirks_mode, query_selector and style attribute parsing all use QuirksMode::NoQuirks. Legacy pages (no doctype, or HTML 4.01 Transitional without a system id) get standards-mode style and selector matching.

use blitz_dom::DocumentConfig;
use blitz_html::HtmlDocument;
use blitz_traits::shell::{ColorScheme, Viewport};
const HTML: &str = r#"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><body style="margin:0"><div id="box" class="foo" style="width:100"></div></body></html>"#;
fn main() {
let config = DocumentConfig { viewport: Some(Viewport::new(800, 600, 1.0, ColorScheme::Light)), ..Default::default() };
let mut doc = HtmlDocument::from_html(HTML, config);
doc.resolve(0.0);
let id = doc.get_element_by_id("box").unwrap();
println!("{:?}", doc.query_selector(".FOO").unwrap()); // expected Some(box), actual None
println!("{}", doc.get_client_bounding_rect(id).unwrap().width); // expected 100, actual 800
}

Tested at be60597f67b3cece0456d26e8d7ff5a88600bbc5. A fix: store the quirks mode on BaseDocument (set from the sink), create/update the Stylist with it, and pass it to TDocument::quirks_mode, selector matching and parse_style_attribute.