The Google Antigravity website, rebuilt with Modern CSS

Screenshot of the Google Antigravity Website Recreation

As an experiment to see if Modern CSS is up to the task, I recreated the Google Antigravity website with Modern CSS.

~

Recently, Google Antigravity was released along with its website. I haven’t used the application myself yet, but I did check out its website. Besides being visually appealing, one of the first things that caught my eye is that the scrolling felt “off”. Opening DevTools confirmed that my hunch was right: the site is using scroll-jacking, which makes the scrolling feel uncanny. Hmmm.

Recording of the Google Antigravity Website, recorded in Google Chrome Canary

Digging further in, I also noticed that the site does not use any of the latest Modern CSS features, even though the site is packed with patterns that can be done with CSS nowadays. Now, I do get why that team might have chosen not to lean on those recent CSS capabilities: the website is a marketing tool, so they want need it to look and behave – including all the visual flair – exactly the same in every browser. I get it. But it does feel like a missed opportunity from my “Chrome DevRel for CSS/UI” point-of-view.

~

So as one does, I nerd sniped myself into recreating the website using Modern CSS Features. The goal of my experiment wasn’t to make an exact copy of the Antigravity website, but more to see if Modern CSS would hold up throughout building it.

A few nights of burning the midnight oil, and this is what I landed on:

Recording of my rebuild of Google Antigravity Website, recorded in Google Chrome Canary

To get to that result, I leaned on these Modern CSS features:

(Not included in this list are things I consider basic nowadays: Responsive Design, Cascade Layers, CSS Nesting, Custom Properties, …)

The only bit of JavaScript used is the registration of the PaintWorklet, and a tad of JS to sync the cursor’s position to two custom properties for the CSS to use.

~

The recreation I built is embedded below, but you should check it out on CodePen as the website is responsive. You must use Chrome Canary to see the latest niceties in action.

If you are not using Google Chrome Canary (or not using Chrome at all) don’t worry: the site was built with Progressive Enhancement in mind and everything – except @scope 😔 – is feature-detected with @supports. So even if your browser understands only a fragment of the Modern CSS that is used, everything can be viewed perfectly fine 🙂

The rest of the CSS is admittedly a bit messy, as I quickly threw this together during some late night coding sessions. Like, the grid approach could be done much better. I also didn’t get to code up all parts of the site (such as the mega menu or the footer) as this is merely an after-hours POC.

TIP: Go disable the @layer named moderncss in the Style Sheet to force the site into its “basic” view. The easiest way to do so, is to change @layer moderncss to @slayer moderncss and you’re done.

~

All in all, I would say Modern CSS held up very nicely here. There are still a few rough edges I encountered:

  • Using @scope from a progressive angle is difficult, because you can’t feature detect it. We really need at-rule() to become a thing.
  • When determining the gap for a flex or grid layout, I want to have different gaps for the rows and columns. gap: inline-gap block-gap would be handy.
  • Getting the pointer’s x and y position on an element should not require JavaScript – I filed w3c/csswg-drafts#6733 for that a long time ago
  • When using scroll-snapping to, for example, snap to the center of a horizontal scroller, the first item can’t really snap to that edge because it is the first item in that scroller so it’s stuck to the left edge. You can fix this by adding some virtual padding to the scroller, but that involves manually calculating the size of it.
  • It feels like the CSS snapped state query is triggering while it is still scrolling – so a bit too early. I needed to delay the entry transitions a bit (magic number!) to sync things up.
  • In the mobile view, I am using the checkbox hack to show the menu. Ideally this would need to be a button, but then I think I would need JS to update the aria-pressed of it. AFAIK there is no “toggleable button” I can use for this.
  • In CSS Carousels, there is no wrapper around the two ::scroll-button()s, so I had to diverge from the original design.
  • Grid blowouts still catch me off guard and subgrid sometimes leaves me headscratching, but that’s most likely just PEBKAC.
  • There is no way to disable an entire cascade layer. You have to slayer it.
  • I could use something like an animation-speed to control how fast the strip of icons should slide in (also see w3c/csswg-drafts#5091 (comment)). Now I have to adjust the time in a media query, whereas “100px per 0.1s” would automatically adjust things.

All the rest went pretty smooth 🙂

If you haven’t done so already, go check out “Google Antigravity with Modern CSS” on CodePen.

~

🔥 Like what you see? Want to stay in the loop? Here's how:

I can also be found on 𝕏 Twitter and 🐘 Mastodon but only post there sporadically.

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation

2 Comments

  1. Hi!

    Really love the work. Congrats! I only have one question, you have another work at codepen that I think is more “accurate” for the hero section. “CSS Houdini Ring Particles” is a smooth and nice way to represent the hero, why you did not use it? Again, amazing job and congrats!

Leave a comment

Leave a Reply to Bramus! Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.