Behind The Scene
A.k.a., how this m*f* website is made ahem, what consideration and
technique went into each aspect of the design, etc. I will be filling this out
gradually.
Try resizing this website!
A core feature of the design is in trying to make the layout zoom-adaptive,
with as little JS and CSS @media
queries as possible (as of Nov 22, '24: zero
in the layout; a bunch for theme and persistent configs). The secret is to use
a shit ton of Flexboxes. In short, it's a crazy generalized blend of horizontal
/ vertical stacking layouts and document flow but over boxes instead of text.
And it works wonders compared to traditional div
and display: float;
-based
layouts.
This entire page is one giant Flexbox containing a header / footer, a left /
(disabled) right ToC / Chat panes, and an <article>
in the center. There are
a few concerns:
- The Article shouldn't be too wide, as it'll make reading difficult.
- The side panes should always make way for the Article if they happen to be put side-by-side, but should scale to fit the width if forced above / below the content.
- The Nav and Footer should be on their own rows, and should be the first / last respectively.
To-do: need an image here for illustration.
The container is a flex box while each element inside is a flex item (which might be its own flex box). Here, we only concern ourselves with a row-wrapping flow.
The singles
To make the Nav and Footer their own rows, they need to "ideally be biiig" but also would "fit in a space out of necessity."
To-do: image.
What I do is set their "ideal size" (i.e. flex-basis
) to 220
pixels but allow them to shrink (i.e. flex-shrink: 1
).
"Stretch" priorities
The side panes need to grow in parallel with the article and the page right?
Make them flex-grow: 1;
. But if several flex-grow: 1;
items are put
side-by-side, they'll use up any extra space equally โ which is not what
I want. The trick is the Article gets a flex-grow
of 220 so it
totally masks the growth of the side panes. Remember, a typical screen is no
more than a few thousand pixels wide.
But how do I make the side panes even fit in when the Article has a million
growth weight? Fortunately, whether something goes on the same row is entirely
determined by the "ideal size" i.e. flex-basis
. The Article has a pretty
small "ideal width" even as it would gladly take up any extra space, so it
still lives on the same floor as the side panes whenever they'd fit.
Article max width
Now the article container can grow as much as it wants minus the size taken by the side panes, but how do I make sure the text itself doesn't get so wide to be uncomfortable for the eyes?
The actual <article>
element lives in a <div class="article-container">
.
The container may grow or shrink, but the Article itself has a max-width
.
- Container "basis" controls box wrapping;
- article "max-width" is there for eye comfort;
- there's no minimum width, so the page doesn't overflow sideways on a phone; once the article is on its own floor, nothing will be done aside from further shrinking it when the display gets even narrower.
To-do: image.
Uncoupling layout and color schemes
The Zola static site generator has support for Sass so I'm using that instead of raw CSS, so you might find the linked stylesheets not very readable.
In short, adaptive.scss
controls the
colorschemes (including the background images, which is why there is an entry
for background image size); base.scss
controls the
layout. Themeing doesn't touch the actual layout at all, while the layout file
doesn't appoint any colors apart from stub colors or colors for debugging.
Finally, there is a separate fonts.scss
that loads
a couple open-source fonts that I store local copies of. They also adjust the
font sizes for some elements (most remarkably monospace ones). This is because
each font has its own sizing, and thus this kind of sizing shouldn't really be
considered the same as layout sizing.
By the way, you can also find the corresponding Zola/Terra template
base.html
here.
Buttons with a height
You might have noticed the theme-switcher buttons that feel oddly like physical buttons you'd find on a casette record player. This is very intentional. The main technique involved in positioning is again Flexbox, with a little variation on alignment; the "height" you see is just separate border width for pressed vs released buttons.
To-do: illustration of the .buttongroup
flexbox.
To-do: illustration of the button border widths.
And then there's the geometric rounding of button shapes which is done entirely
through the border-radius
property in combination with :first-child
/
:last-child
pseudoelements.
To-do: illustration of the button border radii.
A little trick is to use box-sizing: border-box;
so that the buttons are
aligned by how big they are externally instead of how big the text area is.
Todo: illustration of box-sizing for buttons.
You'll see that the buttons reflect the current button pressed as well as the
last selection (if any). The former is easily achieved via :active
, while the
latter is a bit hacky:
body.adaptive div.buttongroup>button.adaptive { border-width: 1px; }
body.bgdark div.buttongroup>button.bgdark { border-width: 1px; }
body.bglite div.buttongroup>button.bglite { border-width: 1px; }
The same class name is being used for both the body and the buttons to indicate a relationship of correspondence. This allows me to do without modifying any property of the buttons themselves. While the button classes hold constant, the change to the body is enough to help "reselect" the correct button to be kept pressed down.
Logo
The logo is technically "fully contained" in the gradient nav bar. It's just border-box sizing and negative margins, really. I love negative margins.
Again I'm using
Actually, screw that. It's about the same w.r.t. what I want to achieve.box-sizing: border-box;
because the space used by the logo
can then be determined ahead of knowing how thick the border is, allowing for
easier adjustment, plus there's less ambiguity as to how "big" things are.
Todo: illustration of box-sizing interacting with paddings and margins.