Flexbox fun

I was doing a tutorial on codeacademy today as a birthday gift to myself and during the tutorial I got an idea I wanted to try. Note: This page is in dark mode style only to make the effect easier to enjoy

Context

During a tutorial I was doing on flexbox, they provided some CSS like this:

.container {
  height: 150px;
  background-color: whitesmoke;
  display: flex;
  justify-content: center;
}

.left,
.center,
.right {
  min-height: 75px;
  width: 125px;
  background-color: dodgerblue;
  border: 2px solid lightgrey;
}

#baseline .center {
  height: 100px;
  width: 100px;
  border: 5px solid turquoise;
}

#baseline {
  align-items: baseline;
}

and some HTML like this:

<div class='container' id='baseline'>
  <div class='left'></div>
  <div class='center'></div>
  <div class='right'></div>
</div>

And of course, this produces the following HTML:

The way this works is that the baseline of each item within the flexbox are aligned, so the bottoms of the boxes line up. And then the justify-content centers the whole thing into the middle of the screen. But, when I saw this I immediately thought about vaporwave cities and the type of boxy purple images you see.

And so, I figured I'd give it a shot!

The vaporwave city:

Three boxes a city does not make. The usual thing I see with these types of images is a sun behind it, so let's get something like that going first. what I think I can do, is setup sopme divs, one with a z-index behind the other, but both using the flexbox for centering content. Then, I just need to make a circle in the back one, then the city bits in the front. So, trying that out:

<div style="display:flex; align-items: baseline; justify-content: center; height: 100px; max-height: 100px; overflow: hidden;">
    <div style="z-index: 1; height: 40px; background-color: red; width: 10px;"></div>
    <div style="z-index: 1; height: 44px; background-color: purple; width: 20px;"></div>
    <div style="z-index: 1; height: 60px; background-color: blueviolet; width: 15px;"></div>
    <div style="z-index: 1; height: 40px; background-color: purple; width: 10px;"></div>
    <div style="z-index: 0; height: 100px; width: 100px; background-color: orangered; border-radius: 80px;"></div>
    <div style="z-index: 1; height: 46px; background-color: blueviolet; width: 5px;"></div>
    <div style="z-index: 1; height: 48px; background-color: purple; width: 16px;"></div>
    <div style="z-index: 1; height: 46px; background-color: blueviolet; width: 5px;"></div>
    <div style="z-index: 1; height: 60px; background-color: purple; width: 23px;"></div>
    <div style="z-index: 1; height: 30px; background-color: red; width: 11px;"></div>
    <div style="z-index: 1; height: 20px; background-color: blueviolet; width: 20px;"></div>
    <div style="z-index: 1; height: 45px; background-color: purple; width: 12px;"></div>
</div>

Close. But not quite, the "sun" is too high in the sky and also needs to moved down.

<div style="display:flex; align-items: baseline; justify-content: center; height: 100px; max-height: 100px; overflow: hidden;">
    ...
    <div style="z-index: 0; height: 100px; width: 100px; background-color: orangered; border-radius: 80px; transform: translateY(25%);"></div>
    ...
</div>

Making sure to include overflow: hidden ensures the sun sinks beneath the horizon, and using transform: translateY allows us to move the sun downwards. Now we just need to figure out how to get the z-index to play along nicely. I think the problem is that the sun is still one of the components within the flex items for the flex box and so it's subject to the layout constraints. So, we can use the position property to tweak things I think. Using a relative position and a float we should be able to move the div, after we've taken it out of the flex box, to stick it behind the city:

Not bad. We can control the size of the "sun" via its height, width, and border-radius properties.

<div style="height: 100px; max-height: 100px; overflow: hidden;">
    <div style="z-index: 0; height: 100px; width: 100px; background-color: orangered; border-radius: 80px;
        position: relative; float:left; left: 50%; transform: translateY(20%);"></div>

    <div style="display:flex; align-items: flex-end; justify-content: center; height: 100px;">
        <div style="z-index: 1; height: 40px; background-color: red; width: 10px;"></div>
        <div style="z-index: 1; height: 44px; background-color: purple; width: 20px;"></div>
        <div style="z-index: 1; height: 60px; background-color: blueviolet; width: 15px;"></div>
        <div style="z-index: 1; height: 40px; background-color: purple; width: 10px;"></div>
        <div style="z-index: 1; height: 46px; background-color: blueviolet; width: 5px;"></div>
        <div style="z-index: 1; height: 48px; background-color: purple; width: 16px;"></div>
        <div style="z-index: 1; height: 46px; background-color: blueviolet; width: 5px;"></div>
        <div style="z-index: 1; height: 60px; background-color: purple; width: 23px;"></div>
        <div style="z-index: 1; height: 30px; background-color: red; width: 11px;"></div>
        <div style="z-index: 1; height: 20px; background-color: blueviolet; width: 20px;"></div>
        <div style="z-index: 1; height: 45px; background-color: purple; width: 12px;"></div>
    </div>
</div>
                

We can make the buildings more interesting via some border radius fiddling, and we can get that "vaporwave sun" feeling by messing with animated gradients I think. So let's do one thing at a time. First off, the sun needs some gradients. Messing around in the color picker, I can tweak a gradient in 10% stripes to get something pretty close to the usual thing:

<div style="height: 100px; max-height: 100px; overflow: hidden;">
    <div style="
        z-index: 0; height: 100px; width: 100px; 
        background-color: orangered; 
        background: rgb(255,69, 0);
        background: 
            linear-gradient(180deg, rgba(255,69, 0, 1) 0%,
            rgba(249,0,151,1) 10%,
            rgba(170,17,193,1) 20%,
            rgba(255,69, 0, 1) 30%,
            rgba(170,17,193,1) 40%,
            rgba(255,69, 0, 1) 50%,
            rgba(170,17,193,1) 60%,
            rgba(255,69, 0, 1) 70%,
            rgba(255,0,159,0.9556197478991597) 100%);
        border-radius: 80px;
        position: relative; float:left; left: 50%; transform: translateY(20%);"></div>
</div>

Then, to animate it, I couldn't get the background-position to actually move like I initially thought I'd do. So instead, I ended up duplicating the sun, layering them on top of each other, and then alternating the opacity of each:

This is accomplished with the following HTML and CSS:

<div style="height: 100px; max-height: 100px; overflow: hidden;">
    <style type="text/css">                      
        @keyframes Animation1 { 
            0%{
                opacity: 1;
            }
            50% {
                opacity: 0;
            }
            100%{
                opacity: 1;
            }
        }
        @keyframes Animation2 { 
            0%{
                opacity: 0;
            }
            50% {
                opacity: 1;
            }
            100%{
                opacity: 0;
            }
        }
    </style>
    <div style="
        z-index: 0; height: 100px; width: 100px; 
        background-color: orangered; 
        background: rgb(255,69, 0);
        background: 
            linear-gradient(180deg, 
            rgba(255,69, 0, 1) 0%,
            rgba(249,0,151,1) 10%,
            rgba(170,17,193,1) 20%,
            rgba(255,69, 0, 1) 30%,
            rgba(170,17,193,1) 40%,
            rgba(255,69, 0, 1) 50%,
            rgba(170,17,193,1) 60%,
            rgba(255,69, 0, 1) 70%,
            rgba(255,0,159,0.9556197478991597) 100%);
        border-radius: 80px;
        position: relative; float:left; left: 50%; transform: translateY(20%);
        animation: Animation1 5s ease infinite;
    "></div>
    <div style="
        z-index: 0; height: 100px; width: 100px; 
        background-color: orangered; 
        background: rgb(255,69, 0);
        background: 
        linear-gradient(180deg, 
            rgba(255,69, 0, 1) 10%,
            rgba(249,0,151,1) 20%,
            rgba(170,17,193,1) 30%,
            rgba(255,69, 0, 1) 40%,
            rgba(170,17,193,1) 50%,
            rgba(255,69, 0, 1) 60%,
            rgba(170,17,193,1) 70%,
            rgba(255,69, 0, 1) 80%,
            rgba(255,0,159,0.9556197478991597) 100%);
        border-radius: 80px;
        position: relative; float:left; left: 50%; transform: translate(-100%, 20%);
        animation: Animation2 5s ease infinite;
    "></div>

Which, while not what I originally envisioned, is a pretty neat effect. Adding the city back into the mix

It's pretty neat looking. It'll look a bit different depending on how you stretch your browser window since I changed justify-content: space-evenly; for this one, but you can always tweak it back and have some fun.