Creating the DigitalOcean Logo in 3D With CSS

Read Time:9 Minute, 45 Second

Howdy y’all! Unless you’ve been living under a rock (and maybe even then), you’ve undoubtedly heard the news that CSS-Tricks, was acquired by DigitalOcean. Congratulations to everyone! 🥳

As a little hurrah to commemorate the occasion, I wanted to create the DigitalOcean logo in CSS. I did that, but then took it a little further with some 3D and parallax. This also makes for quite a good article because the way I made the logo uses various pieces from previous articles I’ve written. This cool little demo brings many of those concepts together.

So, let’s dive right in!

We are going to “trace” the DigitalOcean logo by grabbing an SVG version of it from

Being mindful that we’re taking this 3D, we can wrap our SVG in a .scene element. Then we can use the tracing technique from my “Advice for Advanced CSS Illustrations” article. We are using Pug so we can leverage its mixins and reduce the amount of markup we need to write for the 3D part.

The idea is to style these elements so that they overlap our logo. We don’t need to create the “arc” portion of the logo as we’re thinking ahead because we are going to make this logo in 3D and can create the arc with two cylinder shapes. That means for now all we need is the containing elements for each cylinder, the inner arc, and the outer arc.

Check out this demo that lays out the different pieces of the DigitalOcean logo. If you toggle the “Explode” and hover elements, you can what the logo consists of.

If we wanted a flat DigitalOcean logo, we could use a CSS mask with a conic gradient. Then we would only need one “arc” element that uses a solid border.

That would give us the logo. The “reveal” transitions a clip-path that shows the traced SVG image underneath.

Check out my “Advice for Complex CSS Illustrations” article for tips on working with advanced illustrations in CSS.

Extruding for the 3D

We have the blueprint for our DigitalOcean logo, so it’s time to make this 3D. Why didn’t we create 3D blocks from the start? Creating containing elements, makes it easier to create 3D via extrusion.

We covered creating 3D scenes in CSS in my “Learning to Think in Cubes Instead of Boxes” article. We are going to use some of those techniques for what we’re making here. Let’s start with the squares in the logo. Each square is a cuboid. And using Pug, we are going to create and use a cuboid mixin to help generate all of them.

Then we can use this in our markup:

Next, we need the styles to display our cuboids. Note that cuboids have six sides, so we’re styling those with the nth-of-type() pseudo selector while leveraging the vmin length unit to keep things responsive.

We are approaching this in a different way from how we have done it in past articles. Instead of applying height, width, and depth to a cuboid, we are only concerned with its depth. And instead of trying to color each side, we can make use of filter: brightness to handle that for us.

If you need to have cuboids or other 3D elements as a child of a side using filter, you may need to shuffle things. A filtered side will flatten any 3D children.

The DigitalOcean logo has three cuboids, so we have a class for each one and are styling them like this:

…which gives us something like this:

You can play with the depth slider to extrude the cuboids as you wish! For our demo, we’ve chosen to make the cuboids true cubes with equal height, width, and depth. The depth of the arc will match the largest cuboid.

Now for the cylinders. The idea is to create two ends that use border-radius: 50%. Then, we can use many elements as the sides of the cylinder to create the effect. The trick is positioning all the sides.

There are various approaches we can take to create the cylinders in CSS. But, for me, if this is something I can foresee using many times, I’ll try and future-proof it. That means making a mixin and some styles I can reuse for other demos. And those styles should try and cater to scenarios I could see popping up. For a cylinder, there is some configuration we may want to consider:

  • radius
  • sides
  • how many of those sides are displayed
  • whether to show one or both ends of the cylinder

Putting that together, we can create a Pug mixin that caters to those needs:

See how //- is prepended to the comment in the code? That tells Pug to ignore the comment and leave it out from the compiled HTML markup.

Why do we need to pass the radius into the cylinder? Well, unfortunately, we can’t quite handle trigonometry with CSS calc() just yet (but it is coming). And we need to work out things like the width of the cylinder sides and how far out from the center they should project. The great thing is that we have a nice way to pass that information to our styles via inline custom properties.

An example use for our mixin would be as follows:

This would create a cylinder with a radius of 20, 30 sides, where only sides 10 to 30 are rendered.

Then we need some styling. Styling the cylinders for the DigitalOcean logo is pretty straightforward, thankfully:

The idea is that we create all the sides of the cylinder and put them in the middle of the cylinder. Then we rotate them on the Y-axis and project them out by roughly the distance of the radius.

There’s no need to show the ends of the cylinder in the inner part since they’re already obscured. But we do need to show them for the outer portion. Our two-cylinder mixin use look like this:

We know the radius from the diameter we used when tracing the logo earlier. Plus, we can use the outer cylinder ends to create the faces of the DigitalOcean logo. A combination of border-width and clip-path comes in handy here.

We’re pretty close to where we want to be!

There is one thing missing though: capping the arc. We need to create some ends for the arc, which requires two elements that we can position and rotate on the X or Y-axis:

The arc’s capped ends will assume the height and width based on the end’s border-width value as well as the depth of the arc.

We’ve capped the arc!

Throwing everything together, we have our DigitalOcean logo. This demo allows you to rotate it in different directions.

But there’s still one more trick up our sleeve!

We’ve got our 3D DigitalOcean logo but it would be neat if it was interactive in some way. Back in November 2021, we covered how to create a parallax effect with CSS custom properties. Let’s use that same technique here, the idea being that the logo rotates and moves by following a user’s mouse cursor.

We do need a dash of JavaScript so that we can update the custom properties we need for a coefficient that sets the logo’s movement along the X and Y-axes in the CSS. Those coefficients are calculated from a user’s pointer position. I’ll often use GreenSock so I can use gsap.utils.mapRange. But, here is a vanilla JavaScript version of it that implements mapRange:

The magic happens in CSS-land. This is one of the major benefits of using custom properties this way. JavaScript is telling CSS what’s happening with the interaction. But, it doesn’t care what CSS does with it. That’s a rad decoupling. I use this JavaScript snippet in so many of my demos for this very reason. We can create different experiences simply by updating the CSS.

How do we do that? Use calc() and custom properties that are scoped directly to the .scene element. Consider these updated styles for .scene:

The makes the scene rotate on the X and Y-axes based on the user’s pointer movement. But we can adjust this behavior by tweaking the values for --rotation-x and --rotation-y.

Each cuboid will move its own way. They are able to move on either the X, Y, or Z-axis. But, we only need to define one transform. Then we can use scoped custom properties to do the rest.

That will give you something like this:

And we can tweak these to our heart’s content until we get something we’re happy with!

Adding an intro animation to the mix

OK, I fibbed a bit and have one final (I promise!) way we can enhance our work. What if we had some sort of intro animation? How about a wave or something that washes across and reveals the logo?

We could do this with the pseudo-elements of the body element:

Now, the idea is that the DigitalOcean logo is hidden until the wave washes over the top of it. For this effect, we’re going to animate our 3D elements from an opacity of 0. And we’re going to animate all the sides to our 3D elements from a brightness of 1 to reveal the logo. Because the wave color matches that of the logo, we won’t see it fade in. Also, using animation-fill-mode: both means that our elements will extend the styling of our keyframes in both directions.

This requires some form of animation timeline. And this is where custom properties come into play. We can use the duration of our animations to calculate the delays of others. We looked at this in my “How to Make a Pure CSS 3D Package Toggle” and “Animated Matryoshka Dolls in CSS” articles.

How do we get the timing right? A little tinkering and making use of the “Animations Inspector” in Chrome’s DevTool goes a long ways. Try adjusting the timings in this demo:

You may find that the fade timing is unnecessary if you want the logo to be there once the wave has passed. In that case, try setting the fade to 0. And in particular, experiment with the filter and fade coefficients. They relate to the 0.75s and 1.15s from the code above. It’s worth adjusting things and having a play in Chrome’s Animation Inspector to see how things time in.

That’s it!

Putting it all together, we have this neat intro for our 3D DigitalOcean logo!

And, of course, this only one approach to create the DigitalOcean logo in 3D with CSS. If you see other possibilities or perhaps something that can be optimized further, drop a link to your demo in the comments!

Congratulations, again, to the CSS-Tricks team and DigitalOcean for their new partnership. I’m excited to see where things go with the acquisition. One thing is for sure: CSS-Tricks will continue to inspire and produce fantastic content for the community. 😎


Tag Cloud

Java Java Logical Programs OTP Generation in Java python Recursion youtube video ASCII Upper and Lower Case blockchain javascript graph learn to code software development Successful Software Engineers breadth first search Java Array Programs Java Programs Uncategorized android ios programming kotlin web-development django data sql cybersecurity database swiftui serverless aws swift rust react background-position gradients loader mask grid nth-child pseudo elements indieweb WordPress Print Array without brackets C++ factorial Java String Programs Final Keyword Static Variable Axie Infinity Cryptokitties NFT games tool inserting MISC Tips Codes python code python projects python3 system info python project Bigginers How to Do Integrations Payment Gateways PHP checkout page in php Implement stripe payment gateway in Step by step in PHP integrate stripe gatway in php mysql payment gateway integration in php step by step payment gateway integration in php step by step with source code payment gateway integration in website PHP Integrate Stripe Payment Gateway Tutorial PHP shopping cart checkout code shopping cart in php stripe php checkout PHP/MySQL/JSON best international payment gateway does google pay accept international payments how to accept international payments in india paytm payment gateway razorpay codeigniter github razorpay custom checkout github razorpay get payment details razorpay integration in codeigniter github razorpay international payments Razorpay payment gateway integration in CodeIgniter razorpay payment gateway integration in php code Razorpay payment gateway integration with PHP and CodeIgniter Razorpay payment gateway setup in CodeIgniter Library & Frameworks Tips & Tricks UI/UX & Front-end coding birds online html code for google sign in login with google account in PHP login with google account using javascript login with google account using javascript codeigniter login with google account using php login with google account using php source code
Methods in Java with examples Previous post Methods in Java with examples
Final Keyword in Java explained with examples Next post Final Keyword in Java explained with examples

Leave a 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.