blog/posts/cube.md
2024-09-26 15:57:49 +02:00

122 lines
5.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
date: 2024-09-25
title: cube
tags: [computer, website]
summary: >
i redesigned my personal website. it was a bit of an ordeal.
...
![this is the most complex web page i have ever made by a huge margin](/images/yummycricket.png){.floating .right}
so for the past little while i've been making a big update to my [personal website]. it's a cube now! i wanted to make sure it worked in several browsers:
- firefox latest (easy) and <abbr title='extended support release'>ESR</abbr> (ok)
- chrome (annoying)
- safari (had to make a few sacrifices)
- [qutebrowser] (uhhh)
you know, the big four.
:::aside
one of my partners uses qutebrowser, which is why i care about it, and indeed have heard of it at all. it uses QtWebEngine, which is related to webkit, but even more… let's say _eccentric_.
:::
i got there in the end, with _mostly_ satisfactory results.
[personal website]: https://yummy.cricket
[qutebrowser]: https://qutebrowser.org
# first try
the first incarnation of __the cube__ was very elegant. the sides were moved with 3d transforms, and were brought to the front by applying a transformation to the whole cube. it didn't even need javascript!
if you have a document that looks like this…
```html
<nav>
<!-- page switcher -->
<input type=radio name=page id=r-one>
<input type=radio name=page id=r-two>
</nav>
<main>
<!-- pages -->
<section id=one> 1111111111111111 </section>
<section id=two> 2222222222222222 </section>
</main>
```
…you can make a page switcher like this!
```css
/* hide sections by default */
main > section { display: none; }
/* show one if r-one is checked, and same for two/r-two */
body:has(#r-one:checked) #one { display: block; }
body:has(#r-two:checked) #two { display: block; }
```
the last two rules say that if the `body` contains a thing called `r-one` (or `r-two`) which is checked, then a descendant called `one` (`two`) should be displayed. add four more sections and ~~some~~ a lot of css, and you got yourself a cube babey.
but it wasn't to last, because firefox ESR and qutebrowser don't support [`:has()`][has]. in a few years you might be able to do this though.
[has]: https://developer.mozilla.org/en-US/docs/Web/CSS/:has
# second try
ok, fine, i'll use javascript.
one thing about putting the pages on a cube is that the front is overlapping with the back on the page. obviously. but this means that sometimes scrolling or selecting text ends up on the back face you can't see. so all sides except the front have `pointer-events: none` applied, so you can't accidentally click links you can't see, or whatever.
this worked fine in latest firefox (well, so did the non-javascript one). but in chrome, the faces that started on the left and right sides wouldn't respond to the mouse when brought to the front. just those two. presumably this had been happening the whole time, and i just hadn't noticed yet.
# third try <small>(how the sausage is made)</small>
ok so. rotating the whole cube at once is a bust. fine. i'll manipulate each side individually then.
:::aside
from now on, a `@face@` is one of the sides of the cube (front, top, etc), and a `@pane@` is one of the sections (links, etc).
:::
now i'm keeping a state for each pane, of which face it is on, and how it is rotated. annoying, because composition of transformations isn't commutative, so currently i just have some big lookup tables to do that (sorry i am bad at computer and also at algebra).
oh no now the sides are moving separately, like i told them to, and the transition looks all nutso! so what it _actually_ does is:
a. give the whole cube a `transition` style
b. rotate the whole cube
c. remove the `transition` style
d. de-rotate the cube (which, after c, is non-animated)
e. move the individual sides into place
urgh
in a way, this was a good thing. i can now animate the z-axis transform separately to the other two, which i think looks nicer, and i can give the cube an idle "breathing" animation so hopefully people stop asking if the sides are supposed to be touching.
:::aside
they aren't because then you can barely see them and what is even the point
:::
both of those would have been harder with the whole-cube rotation. silver lining or whatever.
# other stuff {.unnumbered}
- it's not done. there's still more stuff i want to do. but it's done _enough_ to use.
- there's a flat mode when [`prefers-reduced-motion`][reduce] is active. i don't want anyone barfing over my spinning cube.
- dark theme! all the art turns into neon signs (kinda). this was <a href=//zatzhing.me>myno</a>'s idea and i think it rules
- in flat mode, the hidden panes need to have `display: none` applied, otherwise VoiceOver can still see them. apparently it doesn't count as a pointer event.
- in safari and qutebrowser, the breathing animation is disabled. otherwise, in safari, the top and bottom faces disappear _sometimes_, and in qutebrowser everything just goes to hell
- qutebrowser's [`AbortController`][abort] doesn't seem to work so i had to do some minor contortions around that
- qutebrowser's media queries in `<link>` tags are slightly broken, but it's not really a big deal
[reduce]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
[abort]: https://developer.mozilla.org/en-US/docs/Web/API/AbortController