{
  "@context": "https://schema.org",
  "@id": "https://aggr.aymericbeaumet.com/items/lobste-rs/2026-10-23-please-don-t-mess-with-links/#webpage",
  "@type": [
    "WebPage",
    "ArchiveComponent"
  ],
  "articleBody": "**2026-05-31**\n\nA link is just a button that takes you somewhere when you click it right?\n\n```\n<style>\nspan {\n  text-decoration: underline;\n  color: #44EEEE;\n}\n</style>\n<span onclick=\"window.location='https://xkcd.com/'\">100% legit link</span>\n```\n\n100% legit link\n\nExcept that's a pale, shallow imitation of a link. A real link can be:\n\n- Opened in a new tab. (ctrl)\n- ... or a fresh window. (shift)\n- ... or saved as a file (alt).\n- Copied as a URL (right click)\n- Used with the keyboard (tab + enter)\n- Seen by tools like search engines and screen readers.\n- Hovered over to see the URL.\n\n... none of which work with a button.\n\n*Another common offense* is to use a real link, but hook the click event to open a popup. However, with a real \\<a target=\"\\_blank\"> link, I can:\n\n- See the loading progress...\n- ... or/and cancel it.\n- ... see descriptive error pages and retry if needed.\n- Open multiple at once.\n- Read the original page while it loads.\n- Use my browser's tabs or/and window manager to organize them.\n- Bookmark the page.\n- Copy the URL and send it to a friend.\n\n... and above all, they are consistent:\n\nI've long lost count of how many times I've accidentally closed the whole site while trying to close a popup that was a little too convincing.\n\nIt's also extremely common to click a link with a slow connection, only to be greeted with perpetual spinner. I have no idea if anything is actually happening or how long it will take. Worse, it usually covers up the original page so I can't even read that!\n\n*Browsers are good at links and loading pages: It's the whole point.*\n\n- Don't use javascript buttons as links.\n- Don't build your own loading animations.\n- Link previews should open and close on hover, not on click.\n- Don't open links in javascript popups: Use target=\"\\_blank\" instead.\n\n## *Other common problems*:\n\nInfinite scrolling breaks ctrl-f, bookmarks, the home/end keys and often the back button.\n\nYou can have a 100k of text on a page: Browsers will render partially downloaded HTML and the user won't even notice. Using a 5 MB javascript framework just do a worse job of downloading text is dumb.\n\nTo optimize speed, it's best to minimize the total number of round trips. Just putting everything in a single TCP connection will always be better than breaking it up because of TCP's slow start algorithm.\n\n*Don't reimplement \\<details>* which will break search tools and screen readers.\n\n... but using fancy CSS to make it look nice is fine.\n\n*Don't roll your own date picker* (or any other built-in form inputs)\n\nThis will always used the user's preferred date format, covert it to the standard yyyy-mm-dd, and works with the keyboard... also, it's one line of code that works with dark mode by default.\n\n## *Related*:\n\nReal links!\n\n- [https://susam.net/do-not-roll-your-own.html](https://susam.net/do-not-roll-your-own.html): Don't Roll Your Own ...\n- [/misc/13kb/](https://maurycyz.com/misc/13kb/): Why using a single big page can actually improve performance.\n",
  "authors": [
    "maurycyz.com via gavinmorrow"
  ],
  "captured_at": "2026-10-23T18:40:08.262074691+00:00",
  "category": "news",
  "content_html": "<p><strong>2026-05-31</strong></p>\n<p>A link is just a button that takes you somewhere when you click it right?</p>\n<pre><code><span class=\"code-snippet\" data-language=\"CSS\"><span class=\"syntax-source syntax-css\">&lt;<span class=\"syntax-meta syntax-selector syntax-css\"><span class=\"syntax-entity syntax-name syntax-tag syntax-css\">style</span><span class=\"syntax-punctuation syntax-separator syntax-combinator syntax-css\">&gt;</span>\n<span class=\"syntax-entity syntax-name syntax-tag syntax-css\">span</span> </span><span class=\"syntax-meta syntax-property-list syntax-css\"><span class=\"syntax-punctuation syntax-section syntax-property-list syntax-css\">{</span>\n  <span class=\"syntax-meta syntax-property-name syntax-css\"><span class=\"syntax-support syntax-type syntax-property-name syntax-css\">text-decoration</span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-css\">:</span><span class=\"syntax-meta syntax-property-value syntax-css\"> </span><span class=\"syntax-meta syntax-property-value syntax-css\"><span class=\"syntax-support syntax-constant syntax-property-value syntax-css\">underline</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rule syntax-css\">;</span>\n  <span class=\"syntax-meta syntax-property-name syntax-css\"><span class=\"syntax-support syntax-type syntax-property-name syntax-css\">color</span></span><span class=\"syntax-punctuation syntax-separator syntax-key-value syntax-css\">:</span><span class=\"syntax-meta syntax-property-value syntax-css\"> </span><span class=\"syntax-meta syntax-property-value syntax-css\"><span class=\"syntax-constant syntax-other syntax-color syntax-rgb-value syntax-css\"><span class=\"syntax-punctuation syntax-definition syntax-constant syntax-css\">#</span>44EEEE</span></span><span class=\"syntax-punctuation syntax-terminator syntax-rule syntax-css\">;</span>\n</span><span class=\"syntax-punctuation syntax-section syntax-property-list syntax-css\">}</span>\n&lt;/<span class=\"syntax-meta syntax-selector syntax-css\"><span class=\"syntax-entity syntax-name syntax-tag syntax-css\">style</span><span class=\"syntax-punctuation syntax-separator syntax-combinator syntax-css\">&gt;</span>\n&lt;<span class=\"syntax-entity syntax-name syntax-tag syntax-css\">span</span> onclick=&quot;window<span class=\"syntax-entity syntax-other syntax-attribute-name syntax-class syntax-css\"><span class=\"syntax-punctuation syntax-definition syntax-entity syntax-css\">.</span>location</span>=&#39;https:</span>//<span class=\"syntax-meta syntax-selector syntax-css\">xkcd<span class=\"syntax-entity syntax-other syntax-attribute-name syntax-class syntax-css\"><span class=\"syntax-punctuation syntax-definition syntax-entity syntax-css\">.</span>com</span></span>/&#39;&quot;&gt;100%<span class=\"syntax-meta syntax-selector syntax-css\"> legit <span class=\"syntax-entity syntax-name syntax-tag syntax-css\">link</span>&lt;</span>/<span class=\"syntax-meta syntax-selector syntax-css\"><span class=\"syntax-entity syntax-name syntax-tag syntax-css\">span</span><span class=\"syntax-punctuation syntax-separator syntax-combinator syntax-css\">&gt;</span>\n</span></span></span></code></pre>\n<p>100% legit link</p>\n<p>Except that's a pale, shallow imitation of a link. A real link can be:</p>\n<ul>\n<li>Opened in a new tab. (ctrl)</li>\n<li>... or a fresh window. (shift)</li>\n<li>... or saved as a file (alt).</li>\n<li>Copied as a URL (right click)</li>\n<li>Used with the keyboard (tab + enter)</li>\n<li>Seen by tools like search engines and screen readers.</li>\n<li>Hovered over to see the URL.</li>\n</ul>\n<p>... none of which work with a button.</p>\n<p><em>Another common offense</em> is to use a real link, but hook the click event to open a popup. However, with a real &lt;a target=&quot;_blank&quot;&gt; link, I can:</p>\n<ul>\n<li>See the loading progress...</li>\n<li>... or/and cancel it.</li>\n<li>... see descriptive error pages and retry if needed.</li>\n<li>Open multiple at once.</li>\n<li>Read the original page while it loads.</li>\n<li>Use my browser's tabs or/and window manager to organize them.</li>\n<li>Bookmark the page.</li>\n<li>Copy the URL and send it to a friend.</li>\n</ul>\n<p>... and above all, they are consistent:</p>\n<p>I've long lost count of how many times I've accidentally closed the whole site while trying to close a popup that was a little too convincing.</p>\n<p>It's also extremely common to click a link with a slow connection, only to be greeted with perpetual spinner. I have no idea if anything is actually happening or how long it will take. Worse, it usually covers up the original page so I can't even read that!</p>\n<p><em>Browsers are good at links and loading pages: It's the whole point.</em></p>\n<ul>\n<li>Don't use javascript buttons as links.</li>\n<li>Don't build your own loading animations.</li>\n<li>Link previews should open and close on hover, not on click.</li>\n<li>Don't open links in javascript popups: Use target=&quot;_blank&quot; instead.</li>\n</ul>\n<h2><em>Other common problems</em>:</h2>\n<p>Infinite scrolling breaks ctrl-f, bookmarks, the home/end keys and often the back button.</p>\n<p>You can have a 100k of text on a page: Browsers will render partially downloaded HTML and the user won't even notice. Using a 5 MB javascript framework just do a worse job of downloading text is dumb.</p>\n<p>To optimize speed, it's best to minimize the total number of round trips. Just putting everything in a single TCP connection will always be better than breaking it up because of TCP's slow start algorithm.</p>\n<p><em>Don't reimplement &lt;details&gt;</em> which will break search tools and screen readers.</p>\n<p>... but using fancy CSS to make it look nice is fine.</p>\n<p><em>Don't roll your own date picker</em> (or any other built-in form inputs)</p>\n<p>This will always used the user's preferred date format, covert it to the standard yyyy-mm-dd, and works with the keyboard... also, it's one line of code that works with dark mode by default.</p>\n<h2><em>Related</em>:</h2>\n<p>Real links!</p>\n<ul>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://susam.net/do-not-roll-your-own.html\">https://susam.net/do-not-roll-your-own.html</a>: Don't Roll Your Own ...</li>\n<li><a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://maurycyz.com/misc/13kb/\">/misc/13kb/</a>: Why using a single big page can actually improve performance.</li>\n</ul>\n",
  "content_markdown": "**2026-05-31**\n\nA link is just a button that takes you somewhere when you click it right?\n\n```\n<style>\nspan {\n  text-decoration: underline;\n  color: #44EEEE;\n}\n</style>\n<span onclick=\"window.location='https://xkcd.com/'\">100% legit link</span>\n```\n\n100% legit link\n\nExcept that's a pale, shallow imitation of a link. A real link can be:\n\n- Opened in a new tab. (ctrl)\n- ... or a fresh window. (shift)\n- ... or saved as a file (alt).\n- Copied as a URL (right click)\n- Used with the keyboard (tab + enter)\n- Seen by tools like search engines and screen readers.\n- Hovered over to see the URL.\n\n... none of which work with a button.\n\n*Another common offense* is to use a real link, but hook the click event to open a popup. However, with a real \\<a target=\"\\_blank\"> link, I can:\n\n- See the loading progress...\n- ... or/and cancel it.\n- ... see descriptive error pages and retry if needed.\n- Open multiple at once.\n- Read the original page while it loads.\n- Use my browser's tabs or/and window manager to organize them.\n- Bookmark the page.\n- Copy the URL and send it to a friend.\n\n... and above all, they are consistent:\n\nI've long lost count of how many times I've accidentally closed the whole site while trying to close a popup that was a little too convincing.\n\nIt's also extremely common to click a link with a slow connection, only to be greeted with perpetual spinner. I have no idea if anything is actually happening or how long it will take. Worse, it usually covers up the original page so I can't even read that!\n\n*Browsers are good at links and loading pages: It's the whole point.*\n\n- Don't use javascript buttons as links.\n- Don't build your own loading animations.\n- Link previews should open and close on hover, not on click.\n- Don't open links in javascript popups: Use target=\"\\_blank\" instead.\n\n## *Other common problems*:\n\nInfinite scrolling breaks ctrl-f, bookmarks, the home/end keys and often the back button.\n\nYou can have a 100k of text on a page: Browsers will render partially downloaded HTML and the user won't even notice. Using a 5 MB javascript framework just do a worse job of downloading text is dumb.\n\nTo optimize speed, it's best to minimize the total number of round trips. Just putting everything in a single TCP connection will always be better than breaking it up because of TCP's slow start algorithm.\n\n*Don't reimplement \\<details>* which will break search tools and screen readers.\n\n... but using fancy CSS to make it look nice is fine.\n\n*Don't roll your own date picker* (or any other built-in form inputs)\n\nThis will always used the user's preferred date format, covert it to the standard yyyy-mm-dd, and works with the keyboard... also, it's one line of code that works with dark mode by default.\n\n## *Related*:\n\nReal links!\n\n- [https://susam.net/do-not-roll-your-own.html](https://susam.net/do-not-roll-your-own.html): Don't Roll Your Own ...\n- [/misc/13kb/](https://maurycyz.com/misc/13kb/): Why using a single big page can actually improve performance.\n",
  "dateCreated": "2026-10-23T18:40:08.262074691+00:00",
  "date_created": "2026-10-23T00:37:10+00:00",
  "date_modified": "2026-10-23T00:37:10+00:00",
  "date_published": "2026-10-23T00:37:10+00:00",
  "description": "Comments",
  "external_url": "https://maurycyz.com/misc/real_links/",
  "git": {
    "commit": "20068632b65d2830a2d54f25ca1d90d697bea2c0",
    "path": "items/lobste-rs/2026/10/2026-10-23-please-don-t-mess-with-links.md",
    "permalink": "https://github.com/aymericbeaumet/aggr-instance/blob/20068632b65d2830a2d54f25ca1d90d697bea2c0/items/lobste-rs/2026/10/2026-10-23-please-don-t-mess-with-links.md"
  },
  "id": "urn:aggr:item:cefb5e1e936b7782e43cd64a03bac1c9d7904096",
  "isBasedOn": {
    "@id": "https://maurycyz.com/misc/real_links/"
  },
  "mainEntity": {
    "@id": "https://maurycyz.com/misc/real_links/",
    "@type": "CreativeWork",
    "archivedAt": {
      "@id": "https://aggr.aymericbeaumet.com/items/lobste-rs/2026-10-23-please-don-t-mess-with-links/#webpage"
    },
    "author": [
      {
        "@type": "Person",
        "name": "maurycyz.com via gavinmorrow"
      }
    ],
    "dateModified": "2026-10-23T00:37:10+00:00",
    "datePublished": "2026-10-23T00:37:10+00:00",
    "headline": "Please don't mess with links",
    "timeRequired": "PT3M",
    "url": "https://maurycyz.com/misc/real_links/",
    "wordCount": 493
  },
  "name": "Archived snapshot: Please don't mess with links",
  "preview": null,
  "reading_minutes": 3,
  "replicated_at": null,
  "source": "lobste-rs",
  "source_name": "Lobsters: Top Stories of the Past Week",
  "summary": "Comments",
  "tags": [
    "web"
  ],
  "temporalCoverage": "2026-10-23T18:40:08.262074691+00:00",
  "title": "Please don't mess with links",
  "url": "https://aggr.aymericbeaumet.com/items/lobste-rs/2026-10-23-please-don-t-mess-with-links/",
  "word_count": 493
}