← all tags

0 entries
week 1
0 entries
week 2
0 entries
week 3
0 entries
week 4
0 entries
week 5
0 entries
week 6
0 entries
week 7
0 entries
week 8
0 entries
week 9
0 entries
week 10
0 entries
week 11
0 entries
week 12
0 entries
week 13
0 entries
week 14
0 entries
week 15
0 entries
week 16
0 entries
week 17
0 entries
week 18
0 entries
week 19
0 entries
week 20
0 entries
week 21
0 entries
week 22
0 entries
week 23
0 entries
week 24
0 entries
week 25
0 entries
week 26
0 entries
week 27
0 entries
week 28
0 entries
week 29
0 entries
week 30
0 entries
week 31
0 entries
week 32
0 entries
week 33
0 entries
week 34
0 entries
week 35
0 entries
week 36
0 entries
week 37
0 entries
week 38
0 entries
week 39
0 entries
week 40
0 entries
week 41
0 entries
week 42
0 entries
week 43
0 entries
week 44
0 entries
week 45
0 entries
week 46
0 entries
week 47
0 entries
week 48
0 entries
week 49
1 entry
week 50
0 entries
week 51
2 entries
week 52

3 entries over 52 weeks of #homelab activity. Less More

Writing 2 posts

Bits 1 bit

update #wilhelm.codes, #homelab, #css#design

I’ve been rebuilding the public landing page for the homelab this weekend and somewhere in the middle of it I laid a scanline over the whole thing. It’s a single hairline that repeats itself every three pixels. It’s faint enough that the page stops looking quite so flat without you ever working out why. Then, obviously, I wanted it here too.

The lazy version is a white line at about 1.5% opacity, which is what the other page uses, because the other page is forty words of neon over black; legibility isn’t really the goal. However, this site is mostly prose, so a white line lightens the words as well as the background. I didn’t spend all that time on the reading column just to lay a haze over it.

So the grain mixes off --text instead of white:

CSS
--grain: color-mix(in srgb, var(--text) 1.5%, transparent);

This can be applied like so:

CSS
.grain {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 10;
  background: repeating-linear-gradient(
    to bottom,
    var(--grain) 0 1px,
    transparent 1px 3px
  );
}

And finally referened like so just above the closing </body> tag:

HTML
<div class="grain" aria-hidden="true"></div>

This works out great, because a colour mixed with itself gives that colour straight back. The grain physically cannot touch the body copy. I’ve learned quite a few new things today!

As a bonus the lightbox is a <dialog> and the browser promotes a modal dialog into the top layer. This sits above every z-index on the page; including the one holding the grain. So a zoomed photograph comes up perfectly clean and I didn’t have to write a rule to make that happen.

Whether you can see any of this depends entirely on your monitor, your colour settings and even your resolution. If you can’t see it, it’s working.