Hacker News new | past | comments | ask | show | jobs | submit login
Things you don't need JavaScript for (lexoral.com)
501 points by StevenWaterman on March 1, 2022 | hide | past | favorite | 243 comments

6) Sending data but staying on the current page.

You can make links or forms submit but not cause browser navigation by having your server respond with a 204 No Content.

I feel like this is a completely forgotten technique, but we used this a ton pre-AJAX for little one off things to shoot a message to the server without interruption.

That's really cool! I didn't know about this. Thanks for sharing.

How do you handle reflecting the new state in the UI though? Do you just use JavaScript anyway?

I have a form which looks like a toggle, and interacting with the toggle initiates a POST request. If the server responds with a 204, the UI doesn't actually update to reflect the new toggled state. I'm not sure how to work around this.

Could you do something like "<form action="#sent">" and use the ":target" CSS pseudo-class on an element with a message?

I don't think so. I think the form needs to still point to the URI which is expecting the POST request. Maybe I'm not imagining hard enough, but I don't think this approach will work.

Furthermore, according to this article[0], the `:target` approach is viable when it's acceptable to change the browser history, whereas in my case that is exactly what I'm trying to avoid.

[0]: https://css-tricks.com/css-target/

> Maybe I'm not imagining hard enough, but I don't think this approach will work.

I've never heard this turn of phrase before, but I really like it.

In my general use, often it was cases where you either didn’t need to or just some minor `:active` styling was enough.

We also did just use some JS to for instance hide the button. Our goal wasn't to avoid JS perse, just AJAX wasn't really a thing yet.

I can't think of a solution to this either, but there are also other ways of doing non-refreshing requests sending by toggling background-images, loading=lazy <img> and so on

There is the risk however of getting a bit too clever with this, and violating the principle of least astonishment.

From memory there was a time years ago when that's how voting on HN worked, the arrows where just links and returned a 204 no content response. I can't remember exactly but there may not even have been any feedback on the ui (vote count increase or arrows disappearing), although maybe that was done with JS (you could do it with just css now). Have distinct memories of the 204 responses when looking at how HN was made. It's no longer done like that though.

I wonder if that's because of "Show HN: This up votes itself" https://news.ycombinator.com/item?id=3742902

That’s the one, I remember that!

While neat, browser navigation isn't a bad thing on forms considering it is good to notify the user that the form was submitted. Otherwise, they will likely just keep hitting submit.

I actually really like using forms to submit to an iframe on the page. You can set the target attribute on a form to an id of iframe so on form submission, iframe gets reloaded.

Top-level-commenter here - I've actually got a little toy I wrote a while ago that uses motion-jpeg on an <input type="image"> to allow multiple users to draw on the video without using any JS.

It used to use HTTP 204's, but submitting the 204 made Firefox stop steaming the motion jpeg!? When I showed it off on HN in 2020, a PR was submitted that switched it to your iframe method which works smoothly in all browsers without JS.


The problem with that is that the client isn't in control of the experience. What if there is a network error? What if there is a validation error? What if the request times out? What if the load balancer/proxy returns 5xx? In all these cases the browser will navigate away from the current page. It is trivial to handle all of this in a fetch() call.

Is that good, though? I can't count the number of times where the failure mode of a JS submit was an endless spinner, a confusing or ambiguous message that doesn't delineate between "invalid input" and ""unexpected server error", or worse, no indication of the failure at all.

As rough as the experience of being taken to an error page is, I think it's often both more obvious (for users) and easier to get right without thinking too hard about it (for developers).

When would you ever want this? There’s no feedback provided to the user that their submission was in progress or completed successfully.

You said it yourself. When you don't need feedback that their submission was in progress or completed successfully.

To be fair, on the second point, on an error, you can not return a 204, and take them somewhere telling them what went wrong.

This is useful! How does one learn "you can make links or forms submit but not cause browser navigation by having your server respond with a 204" without reading it in an offhand comment on HN?

I mean the status code can be looked up easily, but where would we have read about the "submit but don't cause nav" feature?

The http spec outlines that this was the intended behavior and MDN elaborates on implementation.



Wow! I like that.

What happens with a 40x or 50x? I guess with 40x there's potential to bring the user to a sign in page if that's the problem, but if there's a server error then it seems like the user may lose their form data and end up on a useless error page.

Using 204 seems like a good default, though, because it means I can still use forms with JS turned off but I can choose for the site to be progressively enhanced by JS if I turn it on.

That may be a stupid question, but how would the user know that the form was actually submitted?

As a user, I block such requests.

Why would I have any interest in making requests for "No Content". Perhaps this is why web developers use Javascript to trigger them, without any input from the user. How many users knowingly make such requests for no content, or otherwise send data, while expecting no visual acknowledgment/feedback that data is being or has been sent to a server.

There could be legitimate uses for this perhaps but the uses to "avoid detection by the user" outweigh the benefit of allowing it.

Wouldn't those requests be unblockable, as you don't know if it'll be a 204 until you get the response?

On the first time, I agree.

However once a 204 response is discovered in the logs the domain or URL can be blocked going forward.

I generally do not use a Javascript-capable browser nor enable Javascript when I am using a popular browser so JS-triggered requests for no content fail on account of no JS engine available. In cases outside the browser, e.g., checks to detect captive portals, I block them with a proxy.

How is this fooling the user? And why would you block something that's performing a desired action simply because of a certain response? That would be like saying that a server returning a 404 tricked you into thinking that a page existed, so the URL that returned it should be blocked.

It is not performing a desired action. For example, I have no need for making a request to https://www.youtube.com/generate_204 because I search, browse and download from YouTube via the command line, without using youtube_dl. Making that request, repeatedly, for no content does not benefit me in the slightest. Thus I do not make it. Why would I.

Other users may operate the computer using popular software running under default settings where, e.g., visiting a website automatically runs a number of Javascripts unseen by the user and the user implicitly trusts that, whatever these scripts are doing, it is necessary and for the user's benefit. We know that is not always true. (This blog post shows us a number of instances where JS is used unncessarily.)

There could certainly be legitimate uses for the non-JS 204 no content data sending technique. If I was using a website where this was useful, of course I would not block it. I am not yet aware of any such website among the ones I visit. Every use of requests for no content I have seen has been unnecessary. Usually it is some form of telemetry, sending data about user behaviour to a server without any prior user consent or affirmative action. I suffer no loss of benefits by not making or blocking these requests. For me, this is the most sensible approach. YMMV.

It sounds like your main problem is with telemetry, which you may be misidentifying solely based on the response, rather than with that particular response itself

The indicated use case is for non-JavaScript pages...

You can still use a form with 204 and have some js change some UI state based on the 204 status code...

I assumed the goal is to avoid use of Javascript, as suggested by the title.

Right, I think you don't need to have your whole form controlled by Javascript is already less JS

As a user, you're a silly goose.

There are thousands of reasons things would return a 204. Blocking that is just being obtuse.

There are lots of requests that return a 200 with no body as well. Do you block all AJAX requests? The user doesn't see those happening, but it's not abuse.

I am using a text-only browser with no Javascript engine. I also make HTTP requests with non-browser clients. Without Javascript, most if not all of those "thousands of reasons" do not work and in a text-only environment they accomplish nothing for me.

I do not block all AJAX-triggered HTTP requests. For the ones I might need to make in order to retrieve content, I make them without using Javasscript, outside the browser.

Being called names without repercussion always proves that HN policies do not apply to everyone. It also indicates there is no cogent counter argument to make. More name-calling please. :)

lol I called you a silly goose because it rhymed. Note the end of the three stanzas. Genuinely no insult intended.

None taken. I missed the poetic though. Nice work. :)

If HN commenters want to protest over when and how one user uses her own computers and her own network, I welcome the entertainment. I'm bored today so foolishly responding to every comment, no matter how stupid.

You block requests based on their response code? How's that work?

Works well.

Does it? What problems do you solve by doing it?

Yes. For me, it solves the problem of more annoying, superfluous HTTP requests on the local network.

There is often a privacy benefit, too, if the request are being used to send data to an entity that supports online advertising. In some cases, not making these requests avoids supporting the practice of unconsented user data collection, telemetry and online advertising.

I can but only imagine what kind of life derives annoyance from "annoying, superfluous HTTP requests on the local network".

1–4 are good, but 5 is not. The checkbox hack is decent in a few places (though I’d say <details> is normally a better choice now, and the checkbox hack should be accompanied by certain ARIA properties and augmented with some JavaScript to twiddle properties as it’s used), but dark mode is not one of them. The checkbox hack is only suitable for transient state that you actively don’t want to persist over page loads. Probably the most popular historical application of it is hamburger menus (but <details> or `:hover, :focus-within` are better for that now). I think a more reasonable solution for dark mode is the media query (prefers-color-scheme: dark), following the browser preference by default and augmented by JavaScript to allow overriding that. https://chrismorgan.info/blog/dark-theme-implementation/ describes my own implementation, which is the most comprehensive and efficient client-side-only implementation that I know of, as perfect as it’s possible to be while being client-side-only and without getting into service workers.

Something I don't see talked about often is a variation on the "checkbox hack": using radio groups. The checkbox hack gives you a nice binary piece of state without JS, but using radio buttons gives you any number of options that you need.

For a light-mode/dark-mode toggle that doesn't use JS, I would suggest using radio buttons. It's really a situation that calls for 3 distinct states: follow the system preferences, override to force light mode, and override to force dark mode.


I totally agree though that JS should be used to augment, especially to save the state across page loads. At best, Firefox will autofill radio buttons across page reloads within a session, but that's not sufficient enough.

I was recently considering the approach of keeping this transient state in the URL somehow: the only place that makes sense (for CSS to access it) is in the fragment. Rather than toggling a checkbox or radio group, link to a fragment of the page. This gets tricky with multiple pieces of state though; you have to permute all of the state on the page into increasingly long (or unreadable) fragments (eg. `example.com/my-page.html#color-scheme-override-dark-and-sort-by-title-asc`). However on the plus side, you get state for free _and_ can share your set of state with other people (which makes sense for page state like sorting and filtering, but not so much color scheme overrides).

I use 5 for the hamburger menu on one of my sites. It works really effectively too, means I could build the entire site without writing a single line of Javascript (I've got nothing against Javascript but given it's ostensibly just a collection of man pages I did question the worth of adding any Javascript)

Wouldn't details and summary be better for a hamburger menu, assuming you can style them the way you want? Using a checkbox seems problematic for accessibility; a screen reader user certainly wouldn't expect to open a hamburger menu by checking a checkbox.

The hamburger is only needed for the mobile view (to show/hide navigation that is always present on the desktop view) so there shouldn't be any issues for screen readers. But the site is open source (as it's part of an open source project) and I'm happy to accept any PRs to fix any accessibility issues I might have missed.

Blind people use mobile devices, too.

The checkbox hack can be replaced with :active in many cases.

:active is completely different and never a suitable replacement for the checkbox hack: it only ever matches while the primary mouse button is being held down, and is keyboard-inaccessible; the checkbox hack is about toggling state on click or key stroke.

Oops, I meant :target.

:target is dubious at best: it messes with your scroll position, and you can only use it for one thing in a document.

Historically it was also rather buggy in most browsers, though hopefully that’s sorted out now. (A decade ago, Firefox was fine, but IE and Chromium both had significant bugs, might have been to do with back/forward not recalculating :target or something like that. When I last seriously used :target in 2016 or so, on a multipage-in-one-document résumé, I think they were down to fairly minor bugs.)

2 (Sidebar) is not usable on mobile, because there is no good hover event. Since mobile-first is almost a necessity, it won't work this way.

Accordions make most sense as a table of contents, although they are often used in FAQs. But in FAQs, you can't use the browser's search on page to find collapsed words. So you trade better scrollability for searching on the page. Not sure how many people use "search on page" on mobile devices though.

1 + 3 are great though.

Yeah I agree that the sidebar isn't a very useful example given that it's not even close to something you'd implement in production. The same technique can definitely be made to work with mobile, which is how the burger menu at the top right of the page is implemented - ie just using `:focus-within` rather than `:hover` and using media queries to only display that menu on mobile.

I'm glad that you enjoyed 1 and 3 though - it's been really interesting seeing each person take something different away

Unfortunately the burger menu at the top right of the page also doesn’t work very well on mobile (iOS Firefox). One the menu appears, there’s no way to get it to hide again, permanently covering up any content underneath (in this case, your name).

Aside from that, something very weird is going on with the page. There’s a huge blank area to the right of the screen that you can easily scroll to accidentally. This also happens on Safari on macOS, where for some reason it doesn’t let you scroll back left (and persists the scroll position on page refresh?!).

I definitely agree with the blog post in general though - we should try to use HTML and CSS instead of always resorting to JavaScript.

You can tap on something else to hide the menu.

That works on my laptop, but not on my phone. Not sure what the difference is.

Did you try it on mobile? I was gonna comment the same thing, but I tried it and worked perfectly to my surprise. If you tried and it didn't work, mind sharing what mobile/browser?

It worked very poorly for me on iOS (Firefox, not that it matters). Trying to hover over the side bar made it immediately click on whichever link happened to be under my finger when the sidebar appeared.

That's just bad design. The point is that :hover works on mobile.

Even on desktop it doesn't feel natural because you don't want menus to disappear exactly the instant the mouse is no longer hovering them. You want them to remain for a (very) short time after you stop hovering to make them feel much more natural.

Then you can add a transition-delay to the CSS https://developer.mozilla.org/en-US/docs/Web/CSS/transition-...

Never had an issue with sidebars on mobile. I think this is really just implementing it correctly and not using broken examples that you find online.

Collapsable objects can be expanded by default as well, so not sure how relevant that is. I'd much rather a site use native techniques than load 100 JS frameworks in my browser to do something simple.

It can be done with a checkbox element instead, and then have the style changed (to translate it) based on whether it is clicked.

It works for me on Android Chrome. I just click the sidebar and it becomes visible, then I can choose a link.

This is a very good article: it explains each point clearly and also includes clear and appropriate code examples. I personally love using modern CSS as much as possible, as opposed to javascript, since it allows separating the visualization and functionality from each other. Of course using pure CSS can also offer noticeable performance benefits.

The thing the article seems to be missing is an explanation about when not to use CSS. In my experience there's a lot of scenarios which could be solved with pure CSS in theory but in the end will be implemented in javascript.

The first reason is browser compatibility. If older browsers need to be supported (unfortunately IE is not completely dead yet), many CSS based solutions are just not possible.

The second reason is changing requirements and future-proofing. Often only the simplest requirements can be fulfilled with a pure CSS solution. When more requirements are added or the feature needs to be extended in any way, the only possible solution is to just completely scrap the CSS solution and re-implement it in javascript. I feel this happens so often that most web developers just prefer implementing the feature in javascript straight away because they know it will be easier to change later if needed.

The second reason is changing requirements and future-proofing.

This is a great point. "how am I going to maintain this?" or "how will someone else maintain this?" are often the most important questions and are often overlooked.

> PSA: position: sticky; exists now.

I joined this company that has a 10 year old Dojo application as their UI. Before I joined they had a guy come over once a week for some maintenance work. They spent several days trying to solve an issue where a bar with a 'save / close' action would show up at the bottom of a dialog, making users scroll down. This was a complaint that users had for literal years.

I added position: sticky and had to figure out how it worked, but the issue was resolved with about ten minutes of work. Not to pat my own shoulder too much, but that was pretty cool. Plus it works gracefully, in that if the browser doesn't support it yet, it falls back to (or, should) to the old behaviour.

Just don’t try using it in combination with display: table-* or you will curse position: sticky’s name forever.

Is this still so? I know that in the earlier days of `position: sticky` it didn’t play well with tables (with I think the same limitations on non-tables using `display: table` et al.), but my understanding matches https://caniuse.com/css-sticky, that Firefox’s limitation in that area has been fixed for four years, and Chromium’s for ten months.

Or as part of display: grid which also has severe quirks with position: sticky despite it being a much newer API.

First there was position: sticky. Then it was removed and killed. Now it's back? Guh. It's always had problems. It was very hard to wrangle, especially if you have containers in other containers.

I know jQuery isn't cool these days, but if you have a site that uses it, sticky-kit is the way to go. It's very fast and handles a lot of corner cases (pun intended).

>falls back to the old behaviour

Showing up at the bottom?

I mean I hate JS as much as the next person. Also, for my blog I wanted to use as minimal JS as possible. But when it comes to a sidebar I don't think adding a few lines like this is soo bad.

    const button_close = document.querySelector('#menu-button- 
    const button_open = document.querySelector('#menu-button- 
    const menu = document.querySelector('#menu'); // Menu

    button_close.addEventListener('click', () => {
    button_open.addEventListener('click', () => {

Generalised reminder that if you're doing something like this you should set the appropriate ARIA roles and attributes so blind people can still use your website: https://www.w3.org/TR/wai-aria-practices/examples/menu-butto...

would not < details > tag[1] solve it?

[1]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/de...

I'd be a little concerned with using this in production, because it would make your menu completely unusable for anyone without JavaScript enabled.

As with most things, the ideal is somewhere in the middle - use these techniques to get a baseline, then embrace progressive enhancement and round off the rough edges with JavaScript

I love no-JS type hacks and solutions as your post has suggested, but I would actually be more concerned about using solutions like your hidden menu in production than what the parent has suggested. Some of them, like the checkbox dark mode, are indeed hacks and cause issues with accessibility, and when I've tried a suitably complex burger menu without JS, I find it a buggy and annoying UX.

I think the true progressive enhancement route would be to render the menu either visibly on the page (maybe at the bottom?) or on a separate page entirely. Your burger menu icon is a link (either an anchor to bring the menu into view or to the dedicated menu page) and if JS is supported, you hijack the link using code similar to the parent comment and add a class to bring the menu element into view from there.

In doing so, your page can work just as HTML, not even CSS required, and if JS is supported then you have real state management to control the visibility of your menu (although accessibility concerns still potentially exist if you're not careful!).

It's unfortunate that you are getting downvoted for a legitimate response. Switching off JS saves power considerably and there are folks disabling JS all the time. They don't get tracked and so are mistakenly considered a super-minority by the JS devout here.

Many people have built a career around JS, and are unhappy when their holy cow is considered a future hamburger.

JS has its uses. The majority of UI elements should not involve JS though. Unfortunately, UI also provides low-hanging fruit for beginner-level JS developers to tangle with.

About 98% of people have javascript enabled, and most of the rest will unblock your site if they need to use it anyway.

The remnant who absolutely refuse to run javascript under any circumstance aren't worth worrying about unless you want to appeal to them, specifically, as a demographic.

From further down the page, this is relevant https://kryogenix.org/code/browser/everyonehasjs.html

> Sky accidentally block jQuery, Comcast insert ads into your script, and if you've never experienced this before, drive to an airport and use their wifi.

Sure, in the year of 2010 maybe... With https on almost every website this is hardly an issue now. We need more valid critism, not these outdated incidents to scare people

Yea i kind of agree also the way I have set up the page it is only an issue in mobile view. I guess the combination of no JS and mobile is even smaller.

Really good point. I'm more of a backend person. But how would you do it?

E.g. how they implement CSS-only sidebar, with a custom checkbox: https://lanyon.getpoole.com/

I use this theme, because I disable js myself.

On my previous project I used an anchor for the menu button, and the :target selector to make the menu visible. If JavaScript is loaded, it takes control. But without JS, it still works.

You shouldn't be using a checkbox for dark mode (at least not as the main toggle). You should be using the css prefers-color-scheme media query so that you use the users default with no required interaction and no bright flash of white.


Agreed, but as a user sometimes I turn it off because an article doesn’t work well with it. So the default should be user’s global preference but I want local control

So you would like a website to implement a checkbox to toggle dark mode, in case it doesn't implement dark mode correctly?

That doesn't make any sense.

I think he would rather have a checkbox to disable dark mode in case a specific website. So he don't have to switch his system-wide preference in order to browse a single badly designed website.


Sounds like something that would be better solved by a browser extension than having every website with a dark mode also implement a toggle.

I think the point of checkbox is fine as long as they default to prefers-color-scheme, because there are times when it is nice to be able to switch on a site without having to change your OS color scheme.

I agree, that is what I meant with the "main" source. It would also be cool if browsers could just add a color-scheme toggle in their UI. That way it can be available for all websites without needing to look around for the in-site toggle. (Firefox has this in the dev tools but that isn't exactly user-friendly).

I agree that it'd be cool for browsers to add a per-site color-scheme toggle in the UI.

While it does lack in many other areas, Safari on MacOS has a wonderful interface for per-site default behavior for: automatically using reader-mode, allowing permissions (microphone, etc), setting page zoom, etc. This would be the perfect place for per-site overrides of the system light/dark mode.

I use both. I have a toggleable button for using the "other" color scheme, but it uses by default the preferred color scheme exposed by the browser.

> You should be using the css prefers-color-scheme media query

Problem is, this doesn't always work;

https://forum.manjaro.org/t/google-chrome-not-in-dark-mode/8... https://forum.manjaro.org/t/why-media-query-always-choosing-...

Editing config or .desktop files to work around such issues may be an option for experienced user, but even speaking from such a users perspective, I would much prefer a webpage to offer me a simple button or checkbox.

If you want to argue with "this doesn't always work", I'd assume that the caniuse statistics[0] are more relevant than an implementation bug that affects less than 1% of browser users.

[0]: https://caniuse.com/prefers-color-scheme

Did you read these links?

The first is a complaint about a browser context menu not the web page and the second is about a GNOME theme which obviously has no affect on CSS in browsers.

I uses a tristate flag: system, light, and dark modes.

Too bad that FF with enhanced tracking protection on reports that the user wants a light color scheme instead of reporting no preference.

HTML needs to really catch up already. Who tf uses checkboxes in 2021? Why isn't there an <input type="slide_toggle"> already that uses the native UI?

Instead of a shitty div hell to construct a slide toggle, which becomes super laggy if you have to have a scrollable list of 1000 of them.

But like, it's 2022. Anyway, I've never seen any suggestion that checkboxes are obsolete. They seem easier to use than slide toggles to me. It's easier to tell if they're "on". It's harder for me to remember which direction or color indicates on in a slide. But with a checkbox, it's dead-simple. Simple solution to shitty slide_toggle divs is just use input type=checkbox, since they work perfectly.

I won't argue against the value of a native slide toggle, but they have different semantics compared to a checkbox, in my opinion, and you shouldn't use a slide everywhere you had used a checkbox.

Slide toggles would be completely bizarre on a survey, for example. "ah yes I'll just turn on 'member of the armed forces'"

So provide it as an option damnit! I wasn't suggesting getting rid of checkboxes not sure why everyone makes that assumption

    <input type="checkbox" ...>

    <input type="slide_toggle" ...>

    <input type="range" min="0" max="1000" step="5">

    <input type="color">

You can have whatever you want, just saying, make modern UI native components accessible via HTML without some CPU-intensive div-react-polyfill-javascript fluff. It's ridiculous that if you need to implement a slide toggle, which is available as a native component, that you try to emulate the shit out of it with some images and CSS and javascript and more div hell for the sliding animation and then even more div hell for the little radiating animation instead of just dropping in the native widget which will do all of that and at way better fps than your emulated version.

Instead of all that hell; just use a checkbox.

Pecking accurately at checkboxes while trying to keep your balance on a commuter train is not fun. Slide toggles are much easier to hit accurately. They also are visually easier to understand as an on-off switch. Often people tend to go for design anti-patterns with checkboxes like

[X] Mute notifications

[X] Large fonts

Whereas with slide toggles the on-off semantics are much more obvious and design patterns tend to get forced to a better, simplified pattern:

[o--] Notifications

[--o] Large fonts

(where the toggle is clearly lit up for the "on" state of course)

How about getting tri-state checkboxes?

What does that even mean? Just use radio buttons and be explicit.

checkboxes do have a third 'indeterminate' state[0], but you can't activate it manually. it's basically 'null' rather than an affirmative 'true'/'false'.

[0]: https://developer.mozilla.org/en-US/docs/Web/CSS/:indetermin...

Many slide toogles are bad at showing what means on or off.

Checkboxes may be ugly but pretty clear.

Checkboxes are extremely hard to peck correctly on mobile, hence slide toggles.

The first link needs a section on Smooth Scrolling.

Here's an HTML and CSS snippet to implement smooth scrolling:


That's it. An empty string. In other words, nothing. It's already implemented in the browser! Wasn't that easy?

Now stop wasting time on an JS-based implementation of smooth scrolling that breaks in at least 1 browser.

These are great - I've bookmarked the 2nd for when I inevitably get asked the question!

I really wish developers would just ask themselves if a feature is actually necessary before trying to create it without JS

For example, you can make an accordion menu with plain HTML, but should you? Accordions are horrible. They just hide information. 20 years ago an accordion was a design pattern that made a bit of sense - scrolling meant moving the mouse to the scrollbar or pressing Page Down which took you out of the reading flow on the page. Not to mention screens were tiny so a long page didn't work very well. Today though, users can scroll easily with a mouse wheel or a swipe, and screen are much bigger. Just show the text and let the user scroll past it.

CSS-derived dark mode is another example of "Yeah, you can, but it's a bit rubbish." The site won't retain the user's choice if you use plain CSS which is pretty horrible. Either use JS, or use your build step to bake two versions and serve them on different URLs like "/dark/page-1" and "/weird-bright-mode-wtf/page-1".

The off-canvas menu and sticky bar are quite nice, but again it does feel like developing something that could be better without any clever CSS or JS through sensible design choices.

> 20 years ago an accordion was a design pattern that made a bit of sense - scrolling meant moving the mouse to the scrollbar or pressing Page Down which took you out of the reading flow on the page

Scroll wheels were a thing 20 years ago too :)

I've been building websites as well as surfing the web for nearly 30 years now and I can honestly say I've never once found the scrollbar or using the arrow keys (which I favored over the Page Down) as jarring to the reading experience like you said it is. Generally you'd just keep one hand hovered over the keyboard button or the mouse cursor on the scrollbar, much like you might keep your finger on the scroll wheel now.

If anything, I find swiping on a mobile screen more jarring since it means I have to use both hands (since I'd be holding the phone with one hand), or do some "phone gymnastics" where I try to shift the phone position in my hand enough to slide the screen with my thumb while still holding the phone, and do so without dropping the phone. Which often results in scrolling either too far or not far enough.

> Not to mention screens were tiny so a long page didn't work very well.

Mobile screens display a lot less text than a webpage did on a 90's 800x600 PC screen. Remember that modern screens will have a higher DPI to make things look smoother. On older screens we just accepted that stuff would look pixelated because that was the state of the art.

Web pages without JS are web pages that are served faster, render faster and consume considerably less power.

Incidentally, the biggest mistake the web 'committee' did was to make a web-components spec that mandatorily requires javascript even for a basic 'hello world' label. That made it strictly a no-go for many domains where HTML/CSS generation/rendering is accepted but JS is not.

I am in hard-favour of approaches towards UX components without JS.

> The site won't retain the user's choice if you use plain CSS which is pretty horrible

Correct, that's why the suggested solution here is just as bad.

"Plain CSS" dark mode just follows your device’s setting via `prefers-color-scheme` @media query. Anything else is just unnecessary and should be suppressed. Just set your whole system once and be done.

That "Plain CSS" works perfectly and indeed does not need any JS nor different URLs (wut? who does that.)

Some people want dark mode for some things and light mode for others. I don't, but I know people who do.

Then those people should use a browser that lets them make that distinction. There is nothing saying that prefers-color-scheme needs to match the rest of the system or needs to be the same for all websites - but it should reflect what the user wants from that particular website so implemention an override on top of that should make no sense.

On accordions, I'm of the opposite opinion... sort of.

I love outliners such as Workflowy and Dynalist. I'd like most textual content to look more like them. It's really great being able to expand/collapse/zoom into entire sections, link from one section to another, etc. You can expand everything with a single command and you should also be able to flatten the tree and read it like a normal page if that's how you like it.

Regular pages with accordions are just a poorer version of this. I'd like it to go all the way in that direction.

Could you point to a specific example please? Or screenshot if those are apps. I'm curious about trying some accordion pattern that people actually _like_.

What if I told you...


We're in one right now?

Yes! I thought about it after writing this comment, HN's collapsible comments are one of the best features! But they work the opposite than when you think about an "accordion", where the default is closed and then you can show more info.

Sorry, I can't send screenshots right now, but you can easily find some by googling (yes, they're apps).

There's nothing much to it, it's just collapsible nested lists. And to be clear, I think most people would be weirded out by a blog post that looked like that. I think making the "flat" view the default one but adding a toggle for a hierarchical view would be the ideal UX for me, but I bet this is a very niche preference and it wouldn't be worth it for a larger audience.

This is what we need , more native functionality instead of insane levels of JavaScript. But we also need sane standards instead of more for no reason. How many CSS units are there now? 20? And things like css grid just don't look right. We need to make html and the web approachable by the common man, again

All the things that used to work in HTML still work, aside from some trivialities like <blink>, so it’s not like it stopped being approachable for simple things.

The trick is, people want less-simple things now.

I thought HTML frames were considered bad practice something something Google?

There are a lot of things that are a bad practice. But they still work, for example: https://way2tutorial.com/html/frame/frame_example2.html

Another one that really bombs UX is using javascript for the site navigation in general. That is, instead of

    <a href="/some/path">Place</a>
They will do something like

    <a href="#" onclick="window.location.href='/some/path'">Place</a>
(or whatever the current equivalent is in framework du jour) Making it impossible to right click the link and open a new tab. Yo, I need to be able to reference data from multiple areas of the application and your javascript is making that really hard to do! I know that you can do this properly in javascript, but it would appear that at least some people have not gotten the memo. So I'm going to say - you don't need javascript for navigation.

> Making it impossible to right click the link and open a new tab

Keeping `<a href="/some/path">Place</a>` but adding an event listener to capture your click and run some JS instead fixes that particular issue but opens a whole other can of shit.

20 years ago this was called "unobtrusive javascript" and it's still a good idea today.

BTW, https://remix.run is a sweet new framework that properly embraces progressive enhancement, ie almost everything works with JS disabled.

for example?

Google does it. Search any query, hover over a link, and then click the link. While hovering (pre-click) you'll see the actual target link, but once you click it redirects through some Google tracking nonsense.

Reminds me of my favorite sign that the site has been developed by people who know nothing about the web: you aren't allowed to have more than one window or tab open to the same site (looking at you, ADP).

It's also hostile to users who browse with javascript disabled, as a privacy or security precaution, for example.

It's also really bad for SEO. At least in theory, a search crawler cannot follow that link to discover the target. In practice, they may actually try to parse this pattern, as they know the web is a mess.

Meanwhile, many websites decide to deliberately hide their content from you if you don't allow them to run JS. Not out of necessity - purely out of spite. Like a div that obscures the content, or styling that makes content invisible by default and requires JS to become visible.

Blame the business folks, because this is almost certainly due to analytics.

I assume it's more out of lazyness / apathy than spite in most cases - e.g. they use custom fonts and then only unhide content using JS once the fonts are loaded. Not really an excuse, just don't think its people being actively malicious.

> hide their content from you if you don't allow them to run JS. Not out of necessity - purely out of spite.

Like a news site?

From my daily experience it's more small blogs and the likes than big sites. The kind of site that you only visit once because they got linked on HN.

Recently there appeared a philosophy of "let's hide the loading content so it doesn't reflow".

I've seen a few sites requiring javascript that can only be explained by it.

Sidebar and sticky examples don’t work on iOS safari on iPhone. I’m pretty sure sticky can be made to work. Sidebar would need a different technique since “:hover” is not a thing there.

In general I like the concept of not using js unless you have to, but it’s important to consider mobile.

The sidebar work for me with a long press. I would have know to try it if I didn’t read your comment, it isn’t very obvious or intuitive.

The sidebar example is my fault for forgetting to make the menu itself tab-accessible (ie focusing the sidebar will trigger the `:focus-within` selector rather than just focusing the links or hovering). I'll update the example so hopefully it should work.

As for the sticky example, I'm really not sure what's going on there. It certainly seems to be supported. https://caniuse.com/css-sticky

The sticky was hard to figure out. You have to scroll down in the example frame, but the scroll bar is hidden and there's no indication of more content.

The SVG didn’t animate for me in Firefox/iOS.

Same on Firefox on android

Do most frontend devs in 2022 even know CSS?

They might know tailwind or bootstrap, but I doubt they even know what kind of HTML their react component library is producing, let alone have the capability to style it.

> Do most frontend devs in 2022 even know CSS?

My experience in the last few years has been "no", in general. It is a rare, elite few who bother to learn it. Most devs don't want to put in the effort, and so think it's hard, or think there is a better, easier solution out there.

As a freelancer, I've seen many teams prefer to reach for React components that do layout, or for other libraries like MaterialUI which take just as much effort to learn as CSS, but then they are unequipped to troubleshoot the inevitable unexpected consequences.

CSS is a pretty amazing system for laying things out responsively. I've not seen anything better.

Absolutely awful take. Basically every interview will have some section asking about styling.

I've been doing primarily front-end stuff for the past two years. What's awful about my take?

Never had an interview question about styling before - but some places ask you about inverting binary trees than never have you do anything that involves inverting a binary tree, so that wouldn't tell me much.

Your two years of experience is showing.

My years of backend before that certainly influences how I see things. Maybe it would have been better if I'd drank the "modern front end" kool aid from day one. I came in a sceptic and remained one.

The front end world is a miserable place of dreadful software built on fantastic foundations.

I have dabbled periodically in modern front end development, but it depresses me hugely. All the mistakes that gave us PHP dominating back ends (another sad story) being repeated in a modern context.

Learn CSS? I did. Feel like I wore out MDN but I agree it is awesome. An adequate solution to a very difficult problem.

CSS animation look cool but do we have a way to debug css performance issues? Last time when I had to fix this I found not tool so the solution was look at the CPU usage and remove the elements you think are problematic until CPU usage goes to 0%.

Is super easy for someone to screw things up and cause a 25% CPU usage and not notice it on his dev machine.

After this incident my rule is to always triple check in code reviews any animation that has "infinite" in it (though I am mostly a backend dev)

Chrome devtools have a Performance tab that's extremely useful for this, as well as other performance issues. It includes repaint information, CPU usage and more, and makes it relatively easy to find the culprit. That said, as a frontend developer I very much agree that CSS animations are a great footgun. A testament to this is running into laggy and slow animations on random webpages, oftentimes ones owned by big companies. Of course, they can be done well too, but not without great care.

I know about that tool, but for JS you can dig and find the hot spots with painting operations you could not find what css triggered them. I could use them to identify JS code that did too much DOM changes and optimize them though.

If you make a performance recording of the page, you can then select the main thread, open event log, and filter by "Layout". You won't get a summarized overview, but you can see the layout root for each entry, which will show you what caused the layout update. For complex pages with numerous parallel animations, you might need to filter this data more, but for example in the article we're discussing right now, manual checking quickly reveals where the layout updates are coming form.

Firefox Developer also has a performance tab, can't remember if the normal FF build has.

Just a pet peeve: Sticky headers or footers that overlay scrolled content are bad, because they interfere with jumping to page search results and anchors, as browsers do not take into account that the target may be hidden by an overlaid element.

=> If you use sticky headers/footers, lay out the other content so that it isn’t overlaid by those headers/footers.

seems like the better solution is for the browser to take into account the sticky block when scrolling to the desired content.

The problem, I guess, is that there can be legitimate transparent-ish overlays (covering large parts or the whole of the viewport), and it would be difficult to find a sensible logic that works well in most cases in practice.

Anyway, it doesn’t matter much what would be the better solution as long as browsers don’t implement it.

yah, it's fraught with edge cases, but every browser/dom feature seems to need to run a gauntlet of them anyway, so i'm not sure this one is especially complicated.

but the slowness of new features is definitely frustrating, even if understandable.

Came here for "things I don't need Javascript for", from there flowed into Lexoral as a product (pretty cool) and then into the architecture behind it which was interesting. Nice ride.

Thank you! That's just about the nicest message I've ever read :D If there's a specific bit you're interested in, let me know because I'm happy to chat about it / write future posts about it

Well, my journey ended here: https://lexoral.com/blog/svelte-firestore-binding/ and it would be interesting to hear about the whole cloud native serveless journey after you've had some good mileage on it. Lessons learned, pitfalls, caveats and of course victories and fun times.

> "3. Sticky Positioning"

Yes but javascript can enhance a sticky top nav by watching the scroll position and updating the nav with whatever is intended by design, relative to the scroll position or direction. Such as hiding/showing or doing something else in response.

Even though it might still function as a basic nav without js, if I made a movie and found out people were watching it with "special effects turned off" it wouldn't be fun to learn that about the audience.

> "1. Animating SVGs"

Cool, but the more interesting animation possibilities are javascript driven. Like when using timing, waiting, chaining multiple animations, and responding to user interaction or other events. Need javascript for dynamic animation.

What about compatibility with browsers? CSS can do a lot that JS can but sometimes it just won't work on all browsers. For example the SVG animation on the page doesn't seem to work for me?

Also for animation it depends on the use-case. Complicated animations are better suited for JS than CSS https://developers.google.com/web/fundamentals/design-and-ux...

I recall trying out a complicated SVG animation and it used a decent chunk of CPU time

Have you disabled animations (aka 'prefer reduced motion') in the accessibility options of your device? I check for that and disable animations on the site.

If not, then I'd be interested in the device you're using, to try and debug the animation.

You're correct though, SVG animations can be resource-intensive. There's an interesting discussion elsewhere in the comments about how best to use the developer tools to debug poor performance in animations, but it can be a struggle.

Yep, I tried the animation in mobile safari and mobile brave. Neither browser animated it and in brave it was a black blob with colored lines on it's edges.

But I don't really want that. I hate that my code is spread out over HTML, CSS and Javascript files, it makes it hard to see the whole.

Javascript offers ways to do everything only in Javascript. That's wonderful.

Off-topic, but this is a big reason why I love using Svelte. A `.svelte` file contains the HTML markup, JS code, and styling for that component.

As an example: https://github.com/stevenwaterman/Lexoral/blob/stage/fronten...

I do agree with you. I'd go even further and say using vue helps build more maintainable websites in that it encapsulates components and thus keeps related things together. Also that it provides a separation of the data model and how it is displayed, so one can reason about both things separately.

But, all that are not things this article is about. They just name five specific things you meet regularly in web design and that don't need JS anymore. And in that case it's valid as the browser will generally do things better than you do yourself, be more accessible and integrate better into different platforms / OSes.

You can also build all kinds of toggleable things with hidden <input>s, "+" sibling selectors, and <label>s to activate the inputs. For example, an accordion that only has one section expanded at a time can be made with hidden radio buttons next to each item. Or a navigation drawer/sidebar can be made with a hidden checkbox. Any kind of spoiler-style "click to reveal contents" sort of thing can also be made with a hidden checkbox, it's more flexible than <details>.

Hover doesn’t work with touch screens and I wish <details> state was manageable by CSS for responsive pages.

Check this out, it adds really useful enhancements to <details> https://github.com/zachleat/details-utils

Something I'm struggling to implement at the moment is image carousels. I don't necessarily need something that has full functionality without JavaScript, but it would be nice to provide some kind of progressive enhancement, and make something that works both on desktop and mobile.

Thanks, I saw that one too.

Thanks, but I also want the carousel to have reasonable behavior for mobile devices. So there's a lot of synthesis from different carousels online that I'm doing. The synthesis is the hard part.

I wonder if you could abuse the <marquee> tag to get halfway there. It won't be pretty or feature-filled, but it should at least render properly on all devices.

<marquee> is fairly solidly deprecated. If I just wanted an auto-scrolling set of images, I can conjure that up with some CSS animations.

I was consulting for a startup once and the owner asked me to create an examination he could use to screen front-end "developers". Question #1 asked the applicant to create a modal dialog without using Javascript. He told me that question filtered out several candidates.

This is incredibly short sighted and defeats the purpose of an interview. You’re not trying to trick the interviewee with a gotcha question, you’re trying to find ones with the top skills. Who cares if they can open a modal without JS, when you’re building a front end app, guess what, you’re gonna use JS to open the modal. Building on my point about gotcha questions, I recently had a React interview and 3/4 of the interview was about currying functions in JS, something that’s never ever done in a Reqct app.

Plenty of people who represent themselves as "front-end" "developers" know a good amount of Javascript, or at least some frameworks, but barely know HTML and CSS. This question (and some of the others) filtered out those people.

It filtered out people who didn't know how to use HTML and CSS to render a modal, which is a very specific and not-widely-used HTML/CSS technique.

It filtered out people without a good general knowledge of HTML and CSS and the creativity and problem-solving skills to apply that knowledge.

There's nothing problem-solving about it - they either know some obscure CSS tag or they don't. You're not really testing any skills at all with the question.

I don't think knowledge of the :target pseudoclass is an especially useful filter. It's not without its uses, but it's not exactly part of the core toolbelt either.

If a software developer needed to implement such a feature given those constraints, they could gain the necessary knowledge with a two-minute internet search. Knowledge and information are common and easily acquired, critical thinking and creativity are not. I strongly recommend an interview process that screens for the latter, not the former.

You dont need Javascript to add margin on a website, yet this website cuts off the text on mobile.

I understand that the .dev TLD is not supposed to support unencrypted HTTP (i.e. it is HTTPS only), browsers are supposed to know about this, and in fact the main ones supposedly do.

I wonder if we could also have a .restricted TLD that doesn't support javascript, the more invasive of these CSS hacks, transclusions of any sort except from the same domain, or cookies persisting longer than the browser session. That would make it a lot easier to have reasonable security assurance about pages with private contents, at the expense (or rather, the added benefit) of not being able to have blingy javascript effects on the page.

This kind of information is not appropriate for a TLD. If anything, it should be tacked on by extending the existing client-side-only URI fragment, i.e. the portion after a # delimiter. A number of mechanisms are available for such an extension to be broadly compatible with existing uses.

Hmm ok, but maybe .dev should also have been handled that way? It seems too easy to mess up. Maybe the change should be at the protocol level, like rhttps (restricted https) instead of https. We do already have gemini but it is not really practical.

The dark mode checkbox in this example doesn't remember my selection if I refresh the page. So wouldn't you need JS for it to follow you both across the domain and also upon page refresh?

Works for me on Firefox 97

Doesn't work on Chrome or Edge.

I was working on a hobby project recently and wanted to do it without JS. For some reason, I thought there was a way using HTML forms to form a URL.

That is, imagine I have two `select` dropdown with a set of numbers in each, and a `submit` button. I thought there was a way to construct a target url based on the values of `select` without using JS. So you might select '2' and '5' from the dropdowns and hitting submit would send you to 'mysite.com/2/5'. As far as I can tell, I was wrong. Anyone disagree?

   <form method="get" action="foo.php">
   <select name="item" mutiple>
If you select option 1 and option 3 it will submit to foo.php?item[]=1&item[]=3

So in general <form method="get"> will append a query string to the action url composed of the form field values. But it is not possible to specify an url template to control the exact structure of the url. If you want that you have to implement a server side redirect.

One thing I did not know until recently myself: form submit buttons can specify their own formaction and formmethod attributes that override that ones specified by the form. So you can have multiple buttons inside on form the submit to different locations.

Can only agree with this article! Details/summary, position sticky and the checked toggle are my favorites (position sticky needs some attention though).

It pays of to check for new HTML and CSS tags/functions once in a while. Have been a (web)developer for some years now, and it's only since recently that I found all these things. The amount of JS that I could ditch was astounding to me. Just liberating.

> This isn't just a toy example either. The browser will automatically remember the checkbox state, meaning you can save the user's preference for free - try ticking the box and refreshing this page!

Aside from the typical complaints that you should be using prefers-color-scheme instead… This doesn’t work for me. Is it supposed to leverage autocomplete or something?

Number zero: Reading text.

Worth noting that using `transform` can cause performance issues in some cases, especially if the element being transformed contains many heavy children. This is something that can come back to bite you later on if you rely on `transform` techniques too much.

A bit ironic that 4 out of the 5 don't seem to work in Firefox on macOS.

Pretty sure its not just Firefox, I'm on a Mac and it doesn't work in Safari or Chrome. My guess is somethings broken...

Only the accordion is working.

When I first loaded the page it was broken. Reloading make it work on Firefox on Linux.

My browser didn't remember the dark mode checkbox state after reloading.

One thing you really cannot do with javascript: write an alternative "working" web browser (noscript/basic (x)html) as a small team of devs (or an individual) in a reasonable amount of time.

The website is totally broken for me on mobile safari. 1 and 2 don’t work, and the lack of overflow:hidden causes a huge horizontal scrollbar…

I’d recommend more testing before using. Though the details element is great.

Why, you don't need javascript for anything.

Maybe for killing the user's battery?

Pretty sure CSS animations can kill battery.

I don't want animations in my web site either thank you. Unless it's a game maybe.

Things you don't need on your webpage: accordion menus.

Creating frontends. You can use Java's JSF for that (it has js under the belt but you don't need to touch it).

No love for classic menus and similar controls using the :target selector? Might be as old as the hills, but still ...

I couldn’t interact with the sidebar on mobile. It kept either reloading the page or scrolling to the top

I can't seem to get the firework example working. Is this supported on Firefox?

It definitely works on Firefox, that's my main browser. Have you disabled animations in your OS? I have it set up to respect your accessibility settings - if you have indicated that you prefer reduced motion, it won't play.

unreadable on mobile

Chrome on Android: unreadable.

The left side of the paragraphs, somehow, is cut off.

I cannot scroll sideways.

It's unreadable on desktop Firefox!

I love how a page criticising web developers is unreadable on my phone because one centimeter of text is cut off on the right (:

I'm sorry about this, and don't have any excuse for it. I'm working on fixing it now.

Edit - It should be fixed now. GitHub Actions seems to be having some issues so it took a long time to deploy

Hey man. Just chill. We're a bunch of opinionated techies that like to banter - but we don't sign your pay check or teach your kids or do anything that's actually beneficial for you.

You don't owe us an excuse

Next post: 5 Things you don't need GitHub actions for

I'm 100% guilty of over-using GH actions, although it wouldn't have helped in this case. The issue was GH pages refusing to update the site after I'd pushed the new files to the repo.

Of course, all that would be avoided by just running a web server locally!


so many people I know have amazing projects and work they're afraid to post here because they don't want a massive audience of highly technical people picking at the bugs

I know there's no malicious intent, I'm just sad that such a basic thing is preventing people from reading the post. I'm happy when people are picking holes in the content - that's all valuable discussion we wouldn't have had otherwise, but I don't think anyone's going to argue in favor of making your website not fit on a mobile screen!

I 100% agree with your point with what you can do without javascript but like... test on mobile first we can't read your site it's like 6am where I am and I am NOT getting out of bed to read this on a computer

It's fixed now, so you should be able to read it fine on mobile.

The reason it was broken was because when writing the toy examples, I went in with the mindset of creating an example rather than production code, and set them all to a static `width: 25em` - forgetting that these toy examples were going to be inlined into the page. Silly mistake, should be checking each post before publishing, learnt my lesson now!

> they don't want a massive audience of highly technical people picking

I'd suggest finding a bright side: if all a massive audience of highly technical people can find wrong is presentation nitpicks, then there your project/idea/content can't be too terrible.

Though to be fair to the nitpickers, if you are criticising design matters you should probably make sure your own design is solid enough.

lol, I'm in this boat (although no idea if my project is amazing or if it's just a really stupid idea). One day I'll probably post it.

It definitely requires a bit of a thick skin at times, and to know when not to respond to people. Still though, I'd encourage you to post it! Some of the best discussions I've ever had about my projects has been with people on / from HN

I've learned over the years that in this business you grow thick skin or get out. I have found too that being able to accept criticism has made me a better person.

From time to time though, "Fuck everyone, you're all wrong!" is also still kind of fun.

There is still something wrong: https://imgur.com/a/OcedUsX

The main text column has the right size now but I can scroll 50 vw out to the side.

It's absolutely unusable on my iPhone with increased UI size.


same on samsung note 9

> doesn't overdose on javascript

> overdoses on css instead

Separation of concerns isn't a bad thing

Applications are open for YC Winter 2024

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact