Faking 3D Elements with CSS

Although not always practical, creating the illusion that some of your web elements are “3D” can be a fun experiment. I set out to see if I was able to create such an illusion with only 2 HTML elements and as little CSS as possible.

This is what I ended up creating:

See the Pen CSS Orb by Bradley Taunt (@bradleytaunt) on CodePen.


Prepare for your mind to be blown:

<div class="main-orb">
    <div class="inner-orb"></div>

That’s it – I wasn’t kidding when I said we would use only 2 HTML elements. The .main-orb is the core shape (set to 400×400) and the .inner-orb is placed on top of it’s parent at a slightly smaller size (360×360) – but more on that below in the CSS portion.


First we give the bigger orb element (.main-orb) the default styling needed to represent a 2D circle:

.main-orb {
    background: linear-gradient(#fff 0%, #eee 10%, #2E86FB 50%, #1A237E 100%);
    border-radius: 9999px;
    height: 400px;
    margin: 4rem auto;
    position: relative; /* This is important for the inner orb element later */
    width: 400px;

Next, we include both :before and :after pseudo elements for our orb’s drop shadow. You could do this with a simple box-shadow property on the .main-orb itself, but I’ve explained in a previous post why that’s not the best approach.

/* Shared styling for both pseudo elements - Remember DRY */
.main-orb:before, .main-orb:after {
    border-radius: 200px 200px 9999px 9999px;
    bottom: -10px;
    filter: blur(20px);
    height: 40px;
    position: absolute;
    z-index: -1;

/* Bigger, lighter shadow */
.main-orb:before {
    background: rgba(0,0,0,0.4);
    left: 7.5%;
    width: 85%;

/* Smaller, darker shadow */
.main-orb:after {
    background: rgba(0,0,0,0.7);
    left: 20%;
    width: 60%;

With our main orb complete we can move on to the .inner-orb element to help bring slightly more depth to our floating ball of CSS:

.inner-orb {
    background: linear-gradient(#fff 0%, #2E86FB 60%, #283593 100%);
    border-radius: 9999px;
    box-shadow: 0 8px 20px rgba(0,0,0,0.5);
    height: 360px;
    filter: blur(18px);
    left: 20px;
    position: absolute;
    top: 15px;
    width: 360px;

Poor-man’s 3D elements

Clearly implementing something like this will never come close to generating true 3D renders on a website, but it is a fun exercise to see how much further we can push simple CSS. Feel free to fork the above CodePen to play around with different colors and shadow placements.


  1. Cool, but it looks a little more realistic by changing “filter: blur(15px);” on the .inner-orb class to 25px. Check it out for yourself. 😁

    • Using 25px definitely makes the .inner-orb element slightly smoother, although you then run into the issue of it flowing “outside” the parent orb. Making almost a glowing effect. Of course, you could also shrink down the .inner-orb as well to fix that.

  2. Jaclyn Tan says:

    Hiya, just wanted to say I LOVE your site design. Let’s bring back the scrolling divs! haha. Keep up the awesome articles.

  3. Chris Morgan says:

    The second element seems quite unnecessary to me; you can use an inset box-shadow (or more than one) instead. The spread parameter may be useful in this endeavour.

    • Agreed that it is possible to mimic this 3D styling with multiple insets, but I always prefer the flexibility of being able to resize each individual element. (If I ever wanted that inner-orb to be even smaller / different border-radius / transform effects, etc.)

Leave a Reply

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