That's what I thought too, at first. Some of the iterations I went through before reaching this point:
- Links for the up/down arrows with target=<hidden iframe>, that set "visibility: hidden" on :visited. But oh, only color-changing CSS properties are allowed for :visited selectors.
- Links for the up/down arrows with unicode ▲ and ▼ that set their color to the page background color on :visited, using a sibling selector to hide the other arrow as well once either has been clicked. But oh, sibling selectors are forbidden in conjunction with :visited selectors. Same for selecting nested elements inside a :visited link - only the simplest uses of :visited are allowed. One could wrap both arrows in the same <a> tag, but then there'd be no differentiating between an up/down vote.
- An invisible radio button next to each up/down arrow, with both wrapped inside a <label> so that clicking the arrow causes the radio button to become :checked. Use a sibling selector to hide the arrows when either radio button becomes checked. But oh, if you click a link inside a <label> it's not counted as marking the radio button as selected.
- An invisible radio button hidden under each vote up/down image. Each radio button is wrapped in an <a> tag that causes a hidden iframe to navigate to the voting link. The vote up/down buttons are "pointer-events: none", so trying to click on one really marks the radio button underneath as selected and triggers a link click. This works fine in Firefox, but in Chrome, marking a radio button as selected doesn't trigger a link click.
I thought of that, but then the arrows don't hide immediately after you click them as on HN - they'd still be visible until the request completes. So you'd end up with the same problem: hiding both arrows when either is clicked without using JS.
(I assume you mean putting each pair of arrows in an <iframe>, rather than each individual arrow.)
If it's a button, it'll be in the :focused state, you can use that to style it. Or you could use a CSS transition with a very very long time in one direction on the :active state.
And of course, you can use adjacency selectors with buttons, while you can't with :visited links.