Tags to make HTML work like you expect

(blog.jim-nielsen.com)

Comments

aragonite 27 October 2025
Fun fact: both HN and (no doubt not coincidentally) paulgraham.com ship no DOCTYPE and are rendered in Quirks Mode. You can see this in devtools by evaluating `document.compatMode`.

I ran into this because I have a little userscript I inject everywhere that helps me copy text in hovered elements (not just links). It does:

[...document.querySelectorAll(":hover")].at(-1)

to grab the innermost hovered element. It works fine on standards-mode pages, but it's flaky on quirks-mode pages.

Question: is there any straightforward & clean way as a user to force a quirks-mode page to render in standards mode? I know you can do something like:

document.write("<!DOCTYPE html>" + document.documentElement.innerHTML);

but that blows away the entire document & introduces a ton of problems. Is there a cleaner trick?

dugmartin 27 October 2025
I know this was a joke:

   <div id="root"></div>
   <script src="bundle.js"></script>
but I feel there is a last tag missing:

   <main>...</main>
that will ensure screenreaders skip all your page "chrome" and make life much easier for a lot of folks. As a bonus mark any navigation elements inside main using <nav> (or role="navigation").
dinkelberg 27 October 2025
TFA itself has an incorrect DOCTYPE. It’s missing the whitespace between "DOCTYPE" and "html". Also, all spaces between HTML attributes where removed, although the HTML spec says: "If an attribute using the double-quoted attribute syntax is to be followed by another attribute, then there must be ASCII whitespace separating the two." (https://html.spec.whatwg.org/multipage/syntax.html#attribute...) I guess the browser gets it anyway. This was probably automatically done by an HTML minifier. Actually the minifier could have generated less bytes by using the unquoted attribute value syntax (`lang=en-us id=top` rather than `lang="en-us"id="top"`).

Edit: In the `minify-html` Rust crate you can specify "enable_possibly_noncompliant", which leads to such things. They are exploiting the fact that HTML parsers have to accept this per the (parsing) spec even though it's not valid HTML according to the (authoring) spec.

theandrewbailey 27 October 2025
I often reach for the HTML5 boilerplate for things like this:

https://github.com/h5bp/html5-boilerplate/blob/main/dist/ind...

ilaksh 27 October 2025
Anyone else prefer to use web components without bundling?

I probably should not admit this, but I have been using Lit Elements with raw JavaScript code. Because I stopped using autocomplete awhile ago.

I guess not using TypeScript at this point is basically the equivalent for many people these days of saying that I use punch cards.

notepad0x90 27 October 2025
I'm not a web developer, so if someone can please enlighten me: Why does this site, and so many "modern" sites like it have it so that the actual content of the site takes up only 20% of my screen?

My browser window is 2560x1487. 80% of the screen is blank. I have to zoom in 170% to read the content. With older blogs, I don't have this issue, it just works. Is it on purpose or it is it bad css? Given the title of the post, i think this is somewhat relevant.

chroma_zone 20 hours ago
I usually add:

  <meta name="color-scheme" content="light dark">
which gives you a nice automatic dark theme "for free"
daneel_w 27 October 2025
For clarity and conformity, while optional these days, I insist on placing meta information within <head>.
chrismorgan 27 October 2025
> <html lange="en">

s/lange/lang/

> <meta name="viewport" content="width=device-width,initial-scale=1.0">

Don’t need the “.0”. In fact, the atrocious incomplete spec of this stuff <https://www.w3.org/TR/css-viewport-1/> specifies using strtod to parse the number, which is locale dependent, so in theory on a locale that uses a different decimal separator (e.g. French), the “.0” will be ignored.

I have yet to test whether <meta name="viewport" content="width=device-width,initial-scale=1.5"> misbehaves (parsing as 1 instead of 1½) with LC_NUMERIC=fr_FR.UTF-8 on any user agents.

brianzelip 27 October 2025
> `<html lang="en">`

The author might consider instead:

`<html lang="en-US">`

Aransentin 27 October 2025
Note that <html> and <body> auto-close and don't need to be terminated.

Also, wrapping the <head> tags in an actual <head></head> is optional.

You also don't need the quotes as long the attribute doesn't have spaces or the like; <html lang=en> is OK.

(kind of pointless as the average website fetches a bazillion bytes of javascript for every page load nowadays, but sometimes slimming things down as much as possible can be fun and satisfying)

reconnecting 27 October 2025
I wish I could use this one day again to make my HTML work as expected.

<bgsound src="test.mid" loop=3>

wpollock 27 October 2025
I appreciate this post! I was hoping you would add an inline CSS style sheet to take care of the broken defaults. I only remember one off the top of my head, the rule for monospace font size. You need something like:

   code, pre, tt, kbd, samp {
     font-family: monospace, monospace;
   }
But I vaguely remember there are other broken CSS defaults for links, img tags, and other stuff. An HTML 5 boilerplate guide should include that too, but I don't know of any that do.
orliesaurus 27 October 2025
Quirks quirks aside there are other ways to tame old markup...

If a site won't update itself you can... use a user stylesheet or extension to fix things like font sizes and colors without waiting for the maintainer...

BUT for scripts that rely on CSS behaviors there is a simple check... test document.compatMode and bail when it's not what you expect... sometimes adding a wrapper element and extracting the contents with a Range keeps the page intact...

ALSO adding semantic elements and ARIA roles goes a long way for accessibility... it costs little and helps screen readers navigate...

Would love to see more community hacks that improve usability without rewriting the whole thing...

chrisofspades 19 hours ago
If your IDE supports Emmet (supported by VS Code out of the box) then you can use "!"-tab to get the same tags.
jraph 27 October 2025
> <!doctype html> is what you want for consistent rendering. Or <!DOCTYPE HTML> if you prefer writing markup like it’s 1998. Or even <!doCTypE HTml> if you eschew all societal norms. It’s case-insensitive so they’ll all work.

And <!DOCTYPE html> if you want polyglot (X)HTML.

lapcat 27 October 2025

  <meta name="viewport" content="width=device-width,initial-scale=1.0">
width=device-width is actually redundant and cargo culting. All you need is initial-scale. I explain in a bit more detail here: https://news.ycombinator.com/item?id=36112889
isolay 27 October 2025
The "without meta utf-8" part of course depends on your browser's default encoding.
Grom_PE 27 October 2025
I hate how because of iPhone and subsequent mobile phones we have bad defaults for webpages so we're stuck with that viewport meta forever.

If only we had UTF-8 as a default encoding in HTML5 specs too.

extraduder_ire 18 hours ago
I thought <!doctype html> automatically implied utf-8, or have things changed since html5 was the new hotness?
est 16 hours ago
the lang="en" always irritates me.

What if the page has mixed language content?

e.g. on the /r/france/ reddit. The page says lang="en" because every subreddit shares the same template. But actual content were generated by French speaking users.

cluckindan 22 hours ago
CSS rules to make styling work like you expect:

    *, *:before, *:after {
        box-sizing: border-box;
    }
flymasterv 27 October 2025
I still don’t understand what people think they’re accomplishing with the lang attribute. It’s trivial to determine the language, and in the cases where it isn’t, it’s not trivial for the reader, either.
teekert 27 October 2025
Nice, the basics again, very good to see. But then:

I know what you’re thinking, I forgot the most important snippet of them all for writing HTML:

<div id="root"></div> <script src="bundle.js"></script>

Lol.

-> Ok, thanx, now I do feel like I'm missing an inside joke.

hlava 27 October 2025
It's 2025, the end of it. Is this really necessary to share?