You would be forgiven if you’ve never heard of Cohost.org. The bespoke, Tumblr-like social media website came and went in a flash. Going public in June 2022 with invite-only registrations, Cohost’s peach and maroon landing page promised that it would be “posting, but better.” Just over two years later, in September 2024, the site announced its shutdown, its creators citing burnout and funding problems. Today, its servers are gone for good. Any link to cohost.org redirects to the Wayback Machine’s slow but comprehensive archive.

The landing page for Cohost.org, featuring our beloved eggbug.
Despite its short lifetime, I am confident in saying that Cohost delivered on its promise. This is in no small part due to its user base, consisting mostly of niche internet creatives and their friends — many of whom already considered “posting” to be an art form. These users were attracted to Cohost’s opinionated, anti-capitalist design that set it apart from the mainstream alternatives. The site was free of advertisements and follower counts, all feeds were purely chronological, and the posting interface even supported a subset of HTML.
It was this latter feature that conjured a community of its own. For security reasons, any post using HTML was passed through a sanitizer to remove any malicious or malformed elements. But unlike most websites, Cohost’s sanitizer was remarkably permissive. The vast majority of tags and attributes were allowed — most notably inline CSS styles on arbitrary elements.
Users didn’t take long to grasp the creative opportunities lurking within Cohost’s unassuming “new post” modal. Within 48 hours of going public, the fledgling community had figured out how to post poetry using the <details>
tag, port the Apple homepage from 1999, and reimplement a quick-time WarioWare game. We called posts like these “CSS Crimes,” and the people who made them “CSS Criminals.” Without even intending to, the developers of Cohost had created an environment for a CSS community to thrive.
In this post, I’ll show you a few of the hacks we found while trying to push the limits of Cohost’s HTML support. Use these if you dare, lest you too get labelled a CSS criminal.
Width-hacking
Many of the CSS crimes of Cohost were powered by a technique that user @corncycle dubbed “width-hacking.” Using a combination of the <details>
element and the CSS calc()
function, we can get some pretty wild functionality: combination locks, tile matching games, Zelda-style top-down movement, the list goes on.
If you’ve been around the CSS world for a while, there’s a good chance you’ve been exposed to the old checkbox hack. By combining a checkbox, a label, and creative use of CSS selectors, you can use the toggle functionality of the checkbox to implement all sorts of things. Tabbed areas, push toggles, dropdown menus, etc.
However, because this hack requires CSS selectors, that meant we couldn’t use it on Cohost — remember, we only had inline styles. Instead, we used the relatively new elements <details>
and <summary>
. These elements provide the same visibility-toggling logic, but now directly in HTML. No weird CSS needed.
These elements work like so: All children of the <details>
element are hidden by default, except for the <summary>
element. When the summary is clicked, it “opens” the parent details element, causing its children to become visible.
We can add all sorts of styles to these elements to make this example more interesting. Below, I have styled the constituent elements to create the effect of a button that lights up when you click on it.
This is achieved by giving the <summary>
element a fixed position and size, a grey background color, and an outset border to make it look like a button. When it’s clicked, a sibling <div>
is revealed that covers the <summary>
with its own red background and border. Normally, this <div>
would block further click events, but I’ve given it the declaration pointer-events: none
. Now all clicks pass right on through to the <summary>
element underneath, allowing you to turn the button back off.
This is all pretty nifty, but it’s ultimately the same logic as before: something is toggled either on or off. These are only two states. If we want to make games and other gizmos, we might want to represent hundreds to thousands of states.
Width-hacking gives us exactly that. Consider the following example:
In this example, three <details>
elements live together in an inline-flex
container. Because all the <summary>
elements are absolutely-positioned, the width of their respective <details>
elements are all zero when they’re closed.
Now, each of these three <details>
has a small <div>
inside. The first has a child with a width of 1px
, the second a child with a width of 2px
, and the third a width of 4px
. When a <details>
element is opened, it reveals its hidden <div>
, causing its own width to increase. This increases the width of the inline-flex
container. Because the width of the container is the sum of its children, this means its width directly corresponds to the specific <details>
elements that are open.
For example, if just the first and third <details>
are open, the inline-flex
container will have the width 1px + 4px = 5px
. Conversely, if the inline-flex
container is 2px
wide, we can infer that the only open <details>
element is the second one. With this trick, we’ve managed to encode all eight states of the three <details>
into the width of the container element.
This is pretty cool. Maybe we could use this as an element of some kind of puzzle game? We could show a secret message if the right combination of buttons is checked. But how do we do that? How do we only show the secret message for a specific width of that container div?
In the preceding CodePen, I’ve added a secret message as two nested divs. Currently, this message is always visible — complete with a TODO reminding us to implement the logic to hide it unless the correct combination is set.
You may wonder why we’re using two nested divs for such a simple message. This is because we’ll be hiding the message using a peculiar method: We will make the width of the parent div.secret
be zero. Because the overflow: hidden
property is used, the child div.message
will be clipped, and thus invisible.
Now we’re ready to implement our secret message logic. Thanks to the fact that percentage sizes are relative to the parent, we can use 100%
as a stand-in for the parent’s width. We can then construct a complicated CSS calc()
formula that is 350px
if the container div is our target size, and 0px
otherwise. With that, our secret message will be visible only when the center button is active and the others are inactive. Give it a try!
This complicated calc()
function that’s controlling the secret div’s width has the following graph:

You can see that it’s a piecewise linear curve, constructed from multiple pieces using min
/max
. These pieces are placed in just the right spots so that the function maxes out when the container div is 2px
— which we’ve established is precisely when only the second button is active.
A surprising variety of games can be implemented using variations on this technique. Here is a tower of Hanoi game I had made that uses both width and height to track the game’s state.
SVG animation
So far, we’ve seen some basic functionality for implementing a game. But what if we want our games to look good? What if we want to add ✨animations?✨ Believe it or not, this is actually possible entirely within inline CSS using the power of SVG.
SVG (Scalable Vector Graphics) is an XML-based image format for storing vector images. It enjoys broad support on the web — you can use it in <img>
elements or as the URL of a background-image
property, among other things.
Like HTML, an SVG file is a collection of elements. For SVG, these elements are things like <rect>
, <circle>
, and <text>
, to name a few. These elements can have all sorts of properties defined, such as fill color, stroke width, and font family.
A lesser-known feature of SVG is that it can contain <style>
blocks for configuring the properties of these elements. In the example below, an SVG is used as the background for a div. Inside that SVG is a <style>
block that sets the fill
color of its <circle>
to red
.
An even lesser-known feature of SVG is that its styles can use media queries. The size used by those queries is the size of the div it is a background of.
In the following example, we have a resizable <div>
with an SVG background. Inside this SVG is a media query which will change the fill color of its <circle>
to blue
when the width exceeds 100px
. Grab the resize handle in its bottom right corner and drag until the circle turns blue.
Because resize handles don’t quite work on mobile, unfortunately, this and the next couple of CodePens are best experienced on desktop.
This is an extremely powerful technique. By mixing it with width-hacking, we could encode the state of a game or gizmo in the width of an SVG background image. This SVG can then show or hide specific elements depending on the corresponding game state via media queries.
But I promised you animations. So, how is that done? Turns out you can use CSS animations within SVGs. By using the CSS transition
property, we can make the color of our circle smoothly transition from red
to blue
.
Amazing! But before you try this yourself, be sure to look at the source code carefully. You’ll notice that I’ve had to add a 1
×1px
, off-screen element with the ID #hack
. This element has a very simple (and nearly unnoticeable) continuous animation applied. A “dummy animation” like this is necessary to get around some web browsers’ buggy detection of SVG animation. Without that hack, our transition
property wouldn’t work consistently.
For the fun of it, let’s combine this tech with our previous secret message example. Instead of toggling the secret message’s width between the values of 0px
and 350px
, I’ve adjusted the calc formula so that the secret message div is normally 350px
, and becomes 351px
if the right combination is set.
Instead of HTML/CSS, the secret message is now just an SVG background with a <text>
element that says “secret message.” Using media queries, we change the transform scale of this <text>
to be zero unless the div is 351px
. With the transition
property applied, we get a smooth transition between these two states.
Click the center button to activate the secret message:
The first cohost user to discover the use of media queries within SVG backgrounds was @ticky for this post. I don’t recall who figured out they could animate, but I used the tech quite extensively for this quiz that tells you what kind of soil you’d like if you were a worm.
Wrapping up
And that’s will be all for now. There are a number of techniques I haven’t touched on — namely the fun antics one can get up to with the resize
property. If you’d like to explore the world of CSS crimes further, I’d recommend this great linkdump by YellowAfterlife, or this video retrospective by rebane2001.
It will always hurt to describe Cohost in the past tense. It truly was a magical place, and I don’t think I’ll be able to properly convey what it was like to be there at its peak. The best I can do is share the hacks we came up with: the lost CSS tricks we invented while “posting, but better.”
The Lost CSS Tricks of Cohost.org originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Source: Read MoreÂ