54 comments

[ 4.9 ms ] story [ 68.0 ms ] thread
> <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.

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)

I'm not sure I'd call keeping the <body> tag open satisfying but it is a fun fact.
> Note that <html> and <body> auto-close and don't need to be terminated.

You monster.

If I don't close something I opened, I feel weird.
It's 2025, the end of it. Is this really necessary to share?
Feels even more important to share honestly. It's unexamined boilerplate at this point.
When sharing this post on his social media accounts, Jim prefixed the link with: 'Sometimes its cathartic to just blog about really basic, (probably?) obvious stuff'
The "without meta utf-8" part of course depends on your browser's default encoding.
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.

Can't say I generally agree with dropping TS for JS but I suppose it's easier to argue when you are working on smaller projects. But here is someone that agrees with you with less qualification than that https://world.hey.com/dhh/turbo-8-is-dropping-typescript-701...

I was introduced to this decision from the Lex Fridman/DHH podcast. He talked a lot about typescript making meta programming very hard. I can see how that would be the case but I don't really understand what sort of meta programming you can do with JS. The general dynamic-ness of it I get.

> Anyone else prefer to use web components without bundling?

Yes! not only that but without ShadowDOM as well.

(comment deleted)
Even with TS, if I’m doing web components rather than a full framework I prefer not bundling. That way I can have each page load the exact components it needs. And with http/2 I’m happy to have each file separate. Just hash them and set an immutable cache header so it even when I make changes the users only have to pull the new version of things that actually changed.
God yes, as little tool chain as I can get away with.
I've been leaning that direction more and more every year. ESM loading in browsers is really good at this point (with and without HTTP/2+). Bundle-free living is nice now.

Even frameworks with more dependencies bundling/vendoring just your dependencies at package upgrade time and using an importmap to load them is a good experience.

I'm not giving up Typescript at this point, but Typescript configured to modern `"target"` options where it is doing mostly just type stripping is a good experience, especially in a simple `--watch` loop.

Stopped using autocomplete ? I want to hear more about this.

I could never.

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

I very much enjoy writing no-build, plain vanilla JS for the sake of simplicity and ability to simply launch a project by dragging HTML file onto a browser. Not to mention the power of making changes with notepad instead of needing whole toolchain on your system.

Definitely team #noBundler for most websites. But I didn't wanna give up TypeScript. With Deno and even Node.js supporting type-stripping now natively, all I had to do for https://mastrojs.github.io was to use ts-blank-space to transform client-components on the fly.

  <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
outerHTML is an attribute of Element and DocumentFragment is not an Element.

Where do the standards say it ought to work?

I've read your post. I'm going to test this on some crappy devices this week to confirm and then update my boilerplate.
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?

I wish `dang` would take some time to go through the website and make some usability updates. HN still uses a font-size value that usually renders to 12px by default as well, making it look insanely small on most modern devices, etc.

At quick glance, it looks like they're still using the same CSS that was made public ~13 years ago:

https://github.com/wting/hackernews/blob/5a3296417d23d1ecc90...

I hesitate to want any changes, but I could maybe get behind dynamic font sizing. Maybe.

On mobile it’s fine, on Mac with a Retina display it’s fine; the only one where it isn’t is a 4K display rendering at native resolution - for that, I have my browser set to 110% zoom, which is perfect for me.

So I have a workaround that’s trivial, but I can see the benefit of not needing to do that.

There is a better option, but generally the answer is "no"; the best solution would be for WHATWG to define document.compatMode to be writable property instead of readonly.

The better option is to create and hold a reference to the old nodes (as easy as `var old = document.documentElement`) and then after blowing everything away with document.write (with an empty* html element; don't serialize the whole tree), re-insert them under the new document.documentElement.

* Note that your approach doesn't preserve the attributes on the html element; you can fix this by either pro-actively removing the child nodes before the document.write call and rely on document.documentElement.outerHTML to serialize the attributes just as in the original, or you can iterate through the old element's attributes and re-set them one-by-one.

A uBlock filter can do it: `||news.ycombinator.com/*$replace=/<html/<!DOCTYPE html><html/`
On that subject I would be fine if the browser always rendered in standard mode. or offered a user configuration option to do so.

No need to have the default be compatible with a dead browser.

further thoughts: I just read the mdn quirks page and perhaps I will start shipping Content-Type: application/xhtml+xml as I don't really like putting the doctype in. It is the one screwball tag and requires special casing in my otherwise elegant html output engine.

> <!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.

We need HTML Sophisticated - <!Dr. Type, HtML, PhD>
I tend to lower-case all my HTML because it has less entropy and therefore can be compressed more effectively.

But in case of modern compression algorithms, some of them come with a pre-defined dictionary for websites. These usually contain the common stuff like <!DOCTYPE html> in its most used form. So doing it like everybody else might even make the compression even more effective.

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").
I’m not a blind person but I was curious about once when I tried to make a hyper-optimized website. It seemed like the best way to please screen readers was to have the navigation HTML come last, but style it so it visually comes first (top nav bar on phones, left nav menu on wider screens).
>I know this was a joke

I'm…missing the joke – could someone explain, please? Thank you.

> `<html lang="en">`

The author might consider instead:

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

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...

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

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

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.

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.

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.

For clarity and conformity, while optional these days, I insist on placing meta information within <head>.
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.
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.

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.
(comment deleted)
CSS rules to make styling work like you expect:

    *, *:before, *:after {
        box-sizing: border-box;
    }
can you explain why you add this please?
I usually add:

  <meta name="color-scheme" content="light dark">
which gives you a nice automatic dark theme "for free"
If your IDE supports Emmet (supported by VS Code out of the box) then you can use "!"-tab to get the same tags.