So yesterday I made this post. The idea of the post was to recap a thread of YouTube embeds I made on Mastodon, and Cohost AFAIK(??) doesn't do YouTube embeds yet, so what I wanted to do was post twelve YouTube thumbnails linking to their respective videos.
Problem: Cohost currently doesn't let you intersperse image attachments through the post, they only go at the top, and there is a limit of 4.
The first problem apparently has a standard best-practice solution already, which is that you attach your image attachments to a draft, save the draft, and copy-image-URL the attachments from the draft. Kind of weird, and I guess this means I now have a post in my drafts I can never ever delete?, but fine. The second problem I thought would be easy: I'll just do CSS spritesheets! It was not easy.
So if you're not familiar, the idea with CSS spritesheets is you have many small images you want to use on a webpage, and instead of vending many literal image files you just bundle them together into one big image. Then you display the images as the background:url() of a <div /> or (if you want alt= and the other semantic niceties) an <img> that happens to have a transparent background. So to set that up I dumped all 13 thumbnail images in a folder and crammed them into one 1MB image using imageMagick (montage -tile 1x0 -geometry 1280x720 -border 0 -quality 50 *.jpg done/all2.jpg; this actually produced an incorrect result because I had named the images 1.jpg 2.jpg 3.jpg and imageMagick wants them as 01.jpg 02.jpg 03.jpg, so the final image has the images out of order but by the time I figured that out I'd already uploaded it. I think I don't actually like imageMagick) and wound up with this image.
Then I immediately hit two problems, both related to the fact that I don't per se know what the width of the content div on cohost was and I wanted the image to have a width that was simply 100% of its container.
- There is no way to declare an object's height in terms of its width. I wanted the image to scale itself to the width of the container, but I also wanted it to preserve the 16:9 aspect ratio of the original images. <img>s do this automatically, but I was adding a background to a div. Well, this one had a workable hatchet solution: Put a second image on cohost's CDN which is 16 pixel wide and nine pixels tall
- Scaling the image down with background-size (necessary because remember it's not an image, it's a background) broke the coordinate system of background-position. Each sub-image within the image was 720 pixels tall, but if I set background-size, then setting a background-position vertical offset of 720px would set the position at some kind of random-feeling place partway between images. I concluded that, although I can't find anything in MDN or other CSS documentation sources suggesting this is true, the "pixels" in background-position are in the coordinate system after things are rescaled by background-size and not before.
So here's the solution I wound up with, which is copied and pasted with different background-positions 13 times in the "best electronic music on YouTube" post:
<img
style="background: url(https://staging.cohostcdn.org/attachment/cb1f490a-670e-4a1c-95ac-f7c773b4c285/all2.jpg);
background-position:0px 8.33%;
background-size: 100%; width:100%; display:block"
src="https://staging.cohostcdn.org/attachment/6a7e2b13-9ea4-4a65-9988-aaf061d185f5/transparent.png"
alt="YouTube link"
/>
This works but I don't understand why.
The solution was, since background-size was a percent, to give background-position in terms of a percent also. The vertical positions of the "sprites" would be 8.33%, 16.66%, 0.25 etc counting up 1/12 of the way each time for each of the 12 images in the spritesheet. All right. But there are still two problems with this solution:
- There aren't 12 images!!! There are 13!!! When I was initially fiddling I experimentally tried setting the background-position y to 8.3%, and it successfully gave me the second image, so I didn't interrogate further and set all the remaining images to multiples of 8.33%. But I got 8.3% in the first place by dividing 1 by 12. I'd misremembered the number of images in the sprite sheet! With 13 images the offsets should have been 7.69%, 15.38%, 23.07%. But those aren't the percentages that work. In my testing in Chrome, it's the 1/12 intervals that work.
- The 13th image in the spritesheet has a background-position y of 100%. I guess this is the only possible way it could work, if I'm going to represent 13 images with multiples of 12, but still, what the hey? This seems to imply the y-position refers to the bottom left corner of the frame, which doesn't seem to be how it worked with the other images and is not how MDN documents it as working.
So now I have a working solution which I guess??? I could even reuse in future, but I'm just completely lost. Why 1/12 instead of 1/13? What does background-position:100% mean? Was there a better way to do any of this? Is there a document somewhere (spec, MDN, anything) that formally explains how background-size and background-position are supposed to interact? And why did W3C create all these elaborate and helpful units related to the "viewport" (afaik the browser window size, not what I need) but for sizes related to the enclosing element we're stuck with "%" and its axis-fixedness and unclear semantics?
I should probably note at this point I don't actually like CSS. I've been using it very nearly since it was invented and I feel like I've earned the right to say I just don't like it. Everything is so much more work than it ought to be, it's wildly overexpressive in some ways but startlingly limited on some basic things you often want to do. On Twitter I used to have a problem where every time I tried to post a video, I'd wind up making one single post containing the video and then a long thread about my struggles fighting with the ffmpeg interface and Twitter's video upload rules, which since the thread was longer meant more people saw it and it often got more engagement. Nice as it is Cohost allows CSS it is apparently, demonstrably because this post contains more words than the "best Techno on YouTube" post, the case that CSS is the Twitter video compression of Cohost. There is more to say about CSS technique than there is to say about the content I am using the CSS to express.
