Archive

Author Archive

Time Travelling CSS With :target

September 9th, 2024 No comments

Checkbox and radio button hacks are the (in)famous trick for creating games using just CSS. But it turns out that other elements based on user input can be hacked and gamified. There are very cool examples of developers getting creative with CSS games based on the :hover pseudo-class, and even other games based on the :valid pseudo-class.

What I’ve found, though, is that the :target pseudo-class seems relatively unexplored territory in this area of CSS hacking. It’s an underrated powerful CSS feature when you think about it: :target allows us to style anything based on the selected jump link, so we have a primitive version of client-side routing built into the browser! Let’s go mad scientist with it and see where that takes us.

Unbeatable AI in CSS

Did I type those words together? Are we going to hack CSS so hard that we hit the singularity? Try to beat the stylesheet below at Tic Tac Toe and decide for yourself.

CodePen Embed Fallback

The stylesheet will sometimes allow the game to end in a draw, so you at least have a smidge of hope.

No need to worry! CSS hasn’t gone Skynet on us yet. Like any CSS hack, the rule of thumb to determine whether a game is possible to implement with CSS is the number of possible game states. I learned that when I was able to create a 4×Sudoku solver but found a 9×9 version pretty darn near impossible. That’s because CSS hacks come down to hiding and showing game states based on selectors that respond to user input.

Tic Tac Toe has 5,478 legal states reachable if X moves first and there’s a famous algorithm that can calculate the optimal move for any legal state. It stands to reason, then, that we can hack together the Tic Tac Toe game completely in CSS.

OK, but how?

In a way, we are not hacking CSS at all, but rather using CSS as the Lord Almighty intended: to hide, show, and animate stuff. The “intelligence” is how the HTML is generated. It’s like a “choose your own adventure” book of every possible state in the Tic Tac Toe multiverse with the empty squares linked to the optimal next move for the computer.

We generate this using a mutant version of the minimax algorithm implemented in Ruby. And did you know that since CodePen supports HAML (which supports Ruby blocks), we can use it secretly as a Ruby playground? Now you do.

Each state our HAML generates looks like this in HTML:


<div class="b" id="--OOX----">
  <svg class="o s">
    <circle></circle>
  </svg>

  <a class="s" href="#OXOOX----">
    <div></div>
  </a>

  <svg class="o s">
    <circle class="c"></circle>
  </svg>

  <svg class="o s">
    <circle class="c"></circle>
  </svg>

  <div class="x"></div>

  <a class="s" href="#O-OOXX---">
    <div></div>
  </a>

  <a class="s" href="#O-OOX-X--">
    <div></div>
  </a>

  <a class="s" href="#O-OOX--X-">
    <div></div>
  </a>

  <a class="s" href="#O-OOX---X">
    <div></div>
  </a>
</div>

With a sprinkling of surprisingly straightforward CSS, we will display only the currently selected game state using :target selectors. We’ll also add a .c class to historical computer moves — that way, we only trigger the handwriting animation for the computer’s latest move. This gives the illusion that we are only playing on a single gameboard when we are, in reality, jumping between different sections of the document.

/* Game's parent container */
.b, body:has(:target) #--------- {
  /* Game states */
  .s {
    display: none;
  }
}

/* Game pieces with :target, elements with href */
:target, #--------- {
  width: 300px;
  height: 300px; /
  left: calc(50vw - 150px);
  top: calc(50vh - 150px);
  background-image: url(/path/to/animated/grid.gif);
  background-repeat:  no-repeat;
  background-size: 100% auto;
  
  /* Display that game state and bring it to the forefront  */
  .s {
    z-index: 1;
    display: inline-block;
  }
  
  /* The player's move */
  .x {
    z-index: 1;
    display: inline-block;
    background-image: url("data:image/svg+xml [...]"); /** shortened for brevity **/ 
    height: 100px;
    width: 100px;
  }
  
  /* The browser's move */
  circle {
    animation-fill-mode: forwards;
    animation-name: draw;
    animation-duration: 1s;
    
    /* Only animate the browser's latest turn */
    &.c {
      animation-play-state: paused;
      animation-delay: -1s;
    }
  }
}

When a jump link is selected by clicking an empty square, the :target pseudo-class displays the updated game state(.s), styled so that the computer’s precalculated response makes an animated entrance (.c).

Note the special case when we start the game: We need to display the initial empty grid before the user selects any jump link. There is nothing to style with :target at the start, so we hide the initial state — with the:body:has(:target) #--------- selector — once a jump link is selected. Similarly, if you create your experiments using :target you’ll want to present an initial view before the user begins interacting with your page. 

Wrapping up

I won’t go into “why” we’d want to implement this in CSS instead of what might be an “easier” path with JavaScript. It’s simply fun and educational to push the boundaries of CSS. We could, for example, pull this off with the classic checkbox hack — someone did, in fact.

Is there anything interesting about using :target instead? I think so because:

  • We can save games in CSS! Bookmark the URL and come back to it anytime in the state you left it.
  • There’s a potential to use the browser’s Back and Forward buttons as game controls. It’s possible to undo a move by going Back in time or replay a move by navigating Forward. Imagine combining :target with the checkbox hack to create games with a time-travel mechanic in the tradition of Braid.
  • Share your game states. There’s the potential of Wordle-like bragging rights. If you manage to pull off a win or a draw against the unbeatable CSS Tic Tac Toe algorithm, you could show your achievement off to the world by sharing the URL.
  • It’s completely semantic HTML. The checkbox hack requires you to hide checkboxes or radio buttons, so it will always be a bit of a hack and painful horse-trading when it comes to accessibility. This approach arguably isn’t a hack since all we are doing is using jump links and divs and their styling. This may even make it — dare I say —“easier” to provide a more accessible experience. That’s not to say this is accessible right out of the box, though.

Time Travelling CSS With :target originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

Sticky Headers And Full-Height Elements: A Tricky Combination

September 9th, 2024 No comments

Quite a fun article I worked on with Philip Braunen. Do you know that little bit of elasticity you get when scrolling beyond the viewport when browsing the web on a mobile device? iPhone calls it a “rubber-banding” effect. And you know it’s cool because Apple has previously fought to hold a copyright on it.

Anyway, Philip wrote into Smashing Magazine with a clever approach to mimic rubber-banding in CSS — not only for non-mobile UI but also applied to any sort of container you like.

But what about sticky headers and footers? If those have to be pinned to the container’s block edges, then how in heck do we include them in the rubber banding? Phillip’s trick is an extra div before the header, though we can get more concise markup using pseudos instead.


Sticky Headers And Full-Height Elements: A Tricky Combination originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

Quick Hit #17

September 9th, 2024 No comments

“Wrapping the


Quick Hit #17 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

20 Best New Websites, September 2024

September 9th, 2024 No comments

Welcome to this collection of what has been catching our eye on the web over the past month.

Categories: Designing, Others Tags:

Quick Hit #16

September 5th, 2024 No comments

“Never, ever hire for JavaScript framework skills. Instead, interview and hire only for fundamentals like web standards, accessibility, modern CSS, semantic HTML, and Web Components.” — Alex Russell


Quick Hit #16 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

Quick Hit #15

September 5th, 2024 No comments

Almost missed that the WP Twenty Twenty-Five theme was approved a couple weeks ago.


Quick Hit #15 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

Quick Hit #14

September 3rd, 2024 No comments

Inclusive Design 24 is in 8 short days — and it’s FREE, no sign-up required!


Quick Hit #14 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

Exciting New Tools for Designers, September 2024

September 2nd, 2024 No comments

Welcome to September’s toolbox.

Categories: Designing, Others Tags:

Paragraphs

August 30th, 2024 No comments

I sure do love little reminders about HTML semantics, particularly semantics that are tougher to commit to memory. Scott has a great one, beginning with this markup:

<p>I am a paragraph.</p>
<span>I am also a paragraph.</span>
<div>You might hate it, but I'm a paragraph too.</div>
<ul>
  <li>Even I am a paragraph.</li>
  <li>Though I'm a list item as well.</li>
</ul>
<p>I might trick you</p>
<address>Guess who? A paragraph!</address>

You may look at that markup and say “Hey! You can’t fool me, only the 

 elements are “real” paragraphs!

You might even call out such elements as divs or spans being used as “paragraphs” a WCAG failure.

But, if you’re thinking those sorts of things, then maybe you’re not aware that those are actually all “paragraphs”.

It’s easy to forget this since many of those non-paragraph elements are not allowed in between paragraph tags and it usually gets all sorted out anyway when HTML is parsed.

The accessibility bits are what I always come to Scott’s writing for:

Those examples I provided at the start of this post? macOS VoiceOver, NVDA and JAWS treat them all as paragraphs ([asterisks] for NVDA, read on…). […] The point being that screen readers are in step with HTML, and understand that “paragraphs” are more than just the p element.


Paragraphs originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags:

Shipping Tumblr and WordPress

August 29th, 2024 No comments

Didya see that Tumblr is getting a WordPress makeover? And it’s not a trivial move:

This won’t be easy. Tumblr hosts over half a billion blogs. We’re talking about one of the largest technical migrations in internet history. Some people think it’s impossible. But we say, “challenge accepted.”

Half a billion blogs. Considering that WordPress already powers somewhere around 40% of all websites (which is much, much higher than 500m) this’ll certainly push that figure even further.

I’m sure there’s at least one suspicious nose out there catching whiffs of marketing smoke though I’m amicable to the possibility that this is a genuine move to enhance a beloved platform that’s largely seen as a past relic of the Flickr era. I loved Tumblr back then. It really embraced the whole idea that a blog can help facilitate better writing with a variety of post formats. (Post formats, fwiw, are something I always wished would be a WordPress first-class citizen but they never made it out of being an opt-in theme feature). Tumblr was the first time I was able to see blogging as more than a linear chain of content organized in reverse chronological order. Blog posts are more about what you write and how you write it than they are when they’re written.

Anyway, I know jobs are a scarce commodity in tech these days and Auttomatic is looking for folks to help with the migration.

I was about to say this “could” be a neat opportunity, but nay, it’s a super interesting and exciting opportunity, one where your work is touching two of the most influential blogging platforms on the planet. I remember interviewing Alex Hollender and Jon Robson after they shipped a design update to Wikipedia and thinking how much fun and learning would come out of a project like that. This has that same vibe to me. Buuuut, make no illusions about it: it’ll be tough.


Shipping Tumblr and WordPress originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Categories: Designing, Others Tags: