whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.18k stars 2.69k forks source link

Allow DOM manipulation scripts when JavaScript is disabled #10313

Open NickGard opened 6 months ago

NickGard commented 6 months ago

What problem are you trying to solve?

To build a site that is truly resilient, web developers are often encouraged to treat JavaScript as a "progressive enhancement." This is because JS could fail for a few reasons and leave the user with a broken site. This is not practical for most websites or web apps, though. JavaScript powered user interactions are prevalent in most websites, and even simple UI elements that are not yet native to HTML need JS to be accessible.

There are a number of reasons JavaScript could not work: 1) Failure to load JS resources 2) A scripting error prevents subsequent JS from running 3) User has turned off JS for (a sense of) security or to reduce data use

The first two reasons can be worked around, by making JS files small, using a CDN, inlining scripts, using defensive programming, isolating 3rd party JS to web workers or just their own script tag. The last reason is out of web developers' hands. If users turn off JS for any reason, the most the web developer can do is add a <noscript> tag to show a modal or banner informing the user that the site won't work without JS and requesting they turn it back on.

When users turn off JavaScript, it is nearly impossible to provide a rich UI or even a functional and accessible website.

Rich and accessible UI can be built without relying on network or client data (cookies, history) access, and the ability for scripting to access these is a key reason that users disable JavaScript.

What solutions exist today?

When users disable JavaScript, web developers can only rely on HTML and CSS to provide all of the behavior expected on the site. Often, this creates a very different experience than a JS-enabled version of the site. Single Page Apps (SPAs) degrade into Multi-Page Apps (MPAs) with actions like button clicks submitting forms that may be hidden and showing the results on a subsequent page. Menu or tab buttons might change into links that take the user to a new page with the menu or tab "open." Infinite scrolling experiences fall back into paginated experiences. Rich interactions like swiping or drag/dropping elements are lost entirely.

Some sites do not provide a non-JavaScript fallback at all and use <noscript> tags (or a class on <body> or <html> that would have been removed by JS) to provide a banner or modal that informs the user that the site will be unusable or not as usable without JavaScript enabled. This is effectively pleading with users to enable JavaScript without providing any guarantees for how it will be used.

How would you solve it?

Offering a middle ground between "no JS" and "all JS" would help users feel more in control of their security and privacy. JavaScript itself would not be limited in this middle ground, but some Web APIs would be unavailable. Primarily, network activity (fetch(), form.submit(), link.click()) and access to client data (history, cookies, and sources of entropy used for fingerprinting) should be restricted. User-initiated network activity like clicking links and submitting forms would still work, but sites should not be able to hijack the interaction, such as calling event.preventDefault() on a link click event and then setting window.location to some value other than the link's href.

Even without access to APIs like navigator, history, or document.cookie, websites could offer a much richer experience where dialogs, tabs, maps, and interactive UIs work as expected and do not fall back to some poorer experience. Scripts that rely only on this limited set of APIs could be annotated by something like <script type="restricted"> and the browser could either always run these scripts, even when the user disables JS, or it could offer the users a third option of running restricted scripts vs all or none. Though, I suppose the browser could choose to just run scripts as currently authored with the APIs restricted and emit errors when those APIs are called. It would be up to the author to code defensively around the possibly missing APIs in that scenario.

Having the ability to use JavaScript that either cannot be turned off, or is less likely to be turned off, would make using Web Components more reliable. One common point of contention with Web Components is that they are not as "web native" as HTML since they rely on JavaScript that can be disabled or might fail to load or parse. It would also ease the tension between making a site that can degrade gracefully and a site that breaks entirely without JavaScript. It takes a lot of extra work to progressively enhance MPAs into SPAs and basic HTML-available interactions into complex UIs.

Anything else?

From my experience and informal survey of people I know who prefer to browse the web with JavaScript disabled, their reasons are: 1) They don't want the sites they visit to gather data on them via background network activity 2) They don't want tracking cookies to be set (this isn't usually affected by disabling JavaScript but it came up as a reason) 3) They don't want to be "fingerprinted" 4) They don't want excessive data usage 5) They don't want an "infinite scrolling" experience and disabling JavaScript often triggers websites to fall back to paginated experiences 6) They don't want native web elements to be broken by JavaScript: a) scroll-jacking b) links that act like buttons and don't navigate anywhere, but instead does something on the current page c) buttons that act like links and unexpectedly navigate the user to a new page d) links that don't open in a new tab when ctrl + clicking them e) timed pop-ups that also move the scroll position of the page f) dynamically added content that moves existing content and loses the scroll position of the page g) keypress listeners swallowing events, preventing assistive tech like screen readers from working

flashymittens commented 6 months ago

(random commenter)

Having the ability to use JavaScript that either cannot be turned off…

This one specifically turns the proposal into “do not allow users disable JS”, which is hostile to users.

NickGard commented 6 months ago

Having the ability to use JavaScript that either cannot be turned off…

This one specifically turns the proposal into “do not allow users disable JS”, which is hostile to users.

This whole proposal is about not being hostile to users. Users turn off JS to protect their privacy, and I'm proposing that JS could be ran with a restricted set of APIs so that the users do not have their privacy violated. Right now, users' choice is limited to either allowing all network and client info access or not being able to use a site. This is especially true for client-side-only single page apps, which ship only a <div id="react-root"></div> and a JS file with the actual code needed to render the site.