Skip to content

Instantly share code, notes, and snippets.

@mwongeraE
Created November 20, 2019 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mwongeraE/6b0f38f0ef8afe7bbd3736eca8a26abc to your computer and use it in GitHub Desktop.
Save mwongeraE/6b0f38f0ef8afe7bbd3736eca8a26abc to your computer and use it in GitHub Desktop.
Under construction/maintenance city
<main>
<section class="advice">
<h1 class="advice__title">Site under construction or maintenance </h1>
<p class="advice__description"><span><</span> building <span>/></span> not finished yet</p>
</section>
<section class="city-stuff">
<ul class="skyscrappers__list">
<li class="skyscrapper__item skyscrapper-1"></li>
<li class="skyscrapper__item skyscrapper-2"></li>
<li class="skyscrapper__item skyscrapper-3"></li>
<li class="skyscrapper__item skyscrapper-4"></li>
<li class="skyscrapper__item skyscrapper-5"></li>
</ul>
<ul class="tree__container">
<li class="tree__list">
<ul class="tree__item tree-1">
<li class="tree__trunk"></li>
<li class="tree__leaves"></li>
</ul>
<ul class="tree__item tree-2">
<li class="tree__trunk"></li>
<li class="tree__leaves"></li>
</ul>
<ul class="tree__item tree-3">
<li class="tree__trunk"></li>
<li class="tree__leaves"></li>
</ul>
<ul class="tree__item tree-4">
<li class="tree__trunk"></li>
<li class="tree__leaves"></li>
</ul>
<ul class="tree__item tree-5">
<li class="tree__trunk"></li>
<li class="tree__leaves"></li>
</ul>
<ul class="tree__item tree-6">
<li class="tree__trunk"></li>
<li class="tree__leaves"></li>
</ul>
<ul class="tree__item tree-7">
<li class="tree__trunk"></li>
<li class="tree__leaves"></li>
</ul>
<ul class="tree__item tree-8">
<li class="tree__trunk"></li>
<li class="tree__leaves"></li>
</ul>
</li>
</ul>
<ul class="crane__list crane-1">
<li class="crane__item crane-cable crane-cable-1"></li>
<li class="crane__item crane-cable crane-cable-2"></li>
<li class="crane__item crane-cable crane-cable-3"></li>
<li class="crane__item crane-stand"></li>
<li class="crane__item crane-weight"></li>
<li class="crane__item crane-cabin"></li>
<li class="crane__item crane-arm"></li>
</ul>
<ul class="crane__list crane-2">
<li class="crane__item crane-cable crane-cable-1"></li>
<li class="crane__item crane-cable crane-cable-2"></li>
<li class="crane__item crane-cable crane-cable-3"></li>
<li class="crane__item crane-stand"></li>
<li class="crane__item crane-weight"></li>
<li class="crane__item crane-cabin"></li>
<li class="crane__item crane-arm"></li>
</ul>
<ul class="crane__list crane-3">
<li class="crane__item crane-cable crane-cable-1"></li>
<li class="crane__item crane-cable crane-cable-2"></li>
<li class="crane__item crane-cable crane-cable-3"></li>
<li class="crane__item crane-stand"></li>
<li class="crane__item crane-weight"></li>
<li class="crane__item crane-cabin"></li>
<li class="crane__item crane-arm"></li>
</ul>
</section>
</main>
// ¯\_(ツ)_/¯ I told you that there was no JS
// Variables
$c-main: hsla(0, 100%, 100%, .75);
$c-secondary: hsla(200, 5%, 11%, 1);
$c-malabars: hsla(178, 40%, 49%, 1);
$c-trunk: hsla(23, 18%, 29%, 1);
$c-white: hsla(0, 255%, 255%, 1);
$bg-main: hsla(210, 3%, 15%, 1);
$city-skyscrappers: 5;
$city-cranes: 3;
$city-trees: 8;
$crane-width: 260px;
$crane-height: $crane-width / 1.5;
$crane-border: 1px;
$trunk-height: 8px;
$media900: 900px;
$media768: 768px;
$media450: 450px;
// Fonts
@import url('https://fonts.googleapis.com/css?family=Josefin+Sans');
// General
* {
box-sizing: border-box;
}
main {
position: relative;
height: 100vh;
z-index: -10;
background: linear-gradient(to top, $c-secondary, $c-main);
}
body {
font-size: 12px; // 1rem=12px
font-family: 'Josefin Sans', 'Roboto', sans-serif;
color: $c-main;
overflow: hidden;
background-color: $bg-main;
}
// Specific
.crane__list,
.skyscrappers__list,
.tree__container {
position: absolute;
width: 100%;
bottom: 0;
}
.advice {
display: flex;
height: 50vh; // Ensures that the text doesn't overlap the buildings until a weird aspect ratio occurs
width: 100vw;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
&__title {
font-size: 3rem;
text-align: center;
}
&__description {
margin-top: 1rem;
font-size: 2rem;
text-align: center;
span:first-child {
margin-right: -.7rem;
}
span:last-child {
margin-left: -.7rem;
}
}
}
.city-stuff {
display: flex;
position: absolute;
justify-content: center;
width: 100%;
height: 100%;
bottom: 0;
overflow: hidden;
box-shadow: inset 0 -60px 0 -30px $c-malabars;
}
.skyscrappers__list {
width: 100%;
height: $crane-height / 2;
left: 0;
.skyscrapper__item {
position: absolute;
height: inherit;
bottom: 15%;
width: $crane-height / 4;
background: linear-gradient(115deg, $c-malabars 73%, darken($c-malabars, 10%) 73%, darken($c-malabars, 10%) 100%);
&::after {
content: '';
position: absolute;
width: 80%;
height: 80%;
left: 10%;
bottom: 10%;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAFElEQVQImWP4////fwYYIJKDEwAAfPsP8eFXG40AAAAASUVORK5CYII=') space;
}
&:last-child:not(:only-child) { // Dynamic last-child pseudo-class selector (if it's desired to add new buildings)
background: $c-malabars;
}
}
@for $i from 1 through $city-skyscrappers {
.skyscrapper-#{$i} {
width: $crane-height / ($i / .7); //Building's width
height: $crane-height / ($i / .8); //Building's height
right: (15 + ($i * 10)) * 1%; // Building positioning and workaround to add units to SCSS calculation
bottom: 0;
z-index: 10;
transform: rotate(180deg);
// Minor SCSS changes to make buildings more unpredictable
@if $i == 2 {
bottom: 10%;
@media screen and (max-width: $media900) {
display: none;
}
}
@if $i == 3 {
height: $crane-height / ($i / 2);
@media screen and (max-width: $media900) {
display: none;
}
}
@if $i == 4 {
height: $crane-height / ($i / 2);
&::after {
width: 20%;
height: 60%;
left: 25%;
}
}
@if $i == 5 {
width: 7%;
right: 67%;
height: 50%;
z-index: 11;
&::after {
height: 0;
}
}
}
@media screen and (max-width: $media450) {
.skyscrapper-1{
display: none;
}
}
}
}
.crane-cabin, .crane-arm, .crane-picker {
transform-origin: 80% center;
animation: crane__movement 12s infinite alternate;
}
.crane__list {
width: $crane-width;
height: $crane-height;
z-index: 0;
perspective: 600px;
.crane__item {
position: absolute;
border: solid 1px $c-malabars;
border-radius: 2px;
}
.crane-cable {
width: 1px;
height: 1px;
border: none;
outline: 1px solid transparent;
background: $c-malabars;
z-index: 0;
}
.crane-cable-1 {
width: 60%;
top: 0;
left: 11%;
transform-origin: right 0;
animation: cable-1__movement 12s infinite alternate;
}
.crane-cable-2 {
width: 19%;
top: 0;
right: 8%;
transform-origin: top left;
animation: cable-2__movement 12s infinite alternate;
}
.crane-cable-3 {
height: 30%;
top: 22%;
left: 9%;
transform-origin: right center;
animation: cable-3__movement 12s ease-in-out infinite alternate;
&::after {
content: '';
display: block;
position: absolute;
height: .2em;
width: 9000%;
bottom: 0;
left: -4500%;
background: lighten($c-malabars, 20%);
border: $crane-border solid $c-malabars;
}
}
.crane-stand {
width: 5%;
height: 100%;
right: 25%;
z-index: 1;
background: linear-gradient(to top, $c-malabars, desaturate(lighten($c-malabars, 30%), 20%));
}
.crane-weight {
width: 8%;
height: 20%;
right: 4%;
top: 12%;
z-index: 2;
background: desaturate(lighten($c-malabars, 25%), 10%);
transform-origin: 0 center;
animation: crane-weight__movement 12s infinite alternate;
}
.crane-cabin {
width: 12%;
height: 9%;
right: 24%;
top: 20%;
z-index: 2;
background: desaturate(lighten($c-malabars, 25%), 10%);
&::after {
content: '';
display: block;
position: absolute;
width: 100%;
height: 10%;
top: 60%;
left: 0;
background: $c-white;
}
}
.crane-arm {
width: 100%;
height: 7%;
top: 15%;
border-top-left-radius: 10px;
z-index: 3;
background: desaturate(lighten($c-malabars, 25%), 10%);
}
}
@for $i from 1 through $city-cranes {
.crane-#{$i} {
left: 10 + $i * 10 * 1%; //Crane positioning
z-index: 10;
@if $i == 2 {
bottom: -1rem;
z-index: -1;
transform: scale(.75) scaleX(-1); // Mirror and scale effect to simulate a far crane
@media screen and (max-width: $media900) {
display: none;
}
}
@if $i == 3 {
bottom: -.5rem;
transform: scale(.8);
@media screen and (max-width: $media900) {
z-index: -1;
transform: scale(.75) scaleX(-1);
}
@media screen and (max-width: $media900) {
display: none;
}
}
@if $i > 1 {
.crane-cable-3 {
animation-delay: $i * 1.5s;
}
}
}
}
.tree__container {
width: 100%;
height: $crane-height / 2 - $trunk-height * 3;
left: 0;
margin-bottom: $trunk-height / 2;
}
.tree__item {
display: flex;
flex-flow: column nowrap;
position: absolute;
justify-content: flex-end;
align-items: center;
left: 60%;
}
.tree__trunk {
order: 2;
display: block;
position: absolute;
width: $trunk-height / 2;
height: $trunk-height;
margin-top: $trunk-height;
border-radius: 2px;
background: $c-trunk;
}
.tree__leaves {
order: 1;
position: relative;
border-top: 0 solid transparent;
border-right: 4px solid transparent;
border-bottom: $trunk-height * 4 solid $c-malabars;
border-left: 4px solid transparent;
&::after {
content: '';
position: absolute;
height: 100%;
left: -4px;
border-top: 0;
border-right: 0;
border-bottom: $trunk-height * 4 solid darken($c-malabars, 10%);
border-left: 4px solid transparent;
}
}
@for $i from 1 through $city-trees {
.tree-#{$i} {
@if $i <= 2 {
left: 65% + $i; //Tree positioning
@media screen and (max-width: $media768) {
display: none
}
}
@if $i > 3 and $i < 6 {
left: 53% + $i;
}
@if $i > 6 {
left: 44% + $i;
@media screen and (max-width: $media450) {
display: none
}
}
}
}
// Animations
@keyframes cable-1__movement {
0%, 20% {
transform: rotateY(0) rotateZ(-10deg);
}
70%, 100% {
transform: rotateY(45deg) rotateZ(-10deg);
}
}
@keyframes cable-2__movement {
0%, 20% {
transform: rotateY(0) rotateZ(29deg);
}
70%, 100% {
transform: rotateY(15deg) rotateZ(29deg);
}
}
@keyframes cable-3__movement {
0% {
transform: translate(0, 0);
}
20% {
transform: translate(2500%, -18%);
}
60% {
transform: translate(11000%, -25%);
}
70% {
height: 30%;
transform: translate(9100%, -25%);
}
90%, 100% {
height: 80%;
transform: translate(9100%, -15%);
}
}
@keyframes crane__movement {
0%, 20% {
transform: rotateY(0);
}
70%, 100% {
transform: rotateY(45deg);
}
}
@keyframes crane-weight__movement {
0%, 20% {
transform: rotateY(0) translateX(0);
}
70%, 100% {
transform: rotateY(45deg) translateX(-50%);
}
}

Under construction/maintenance city

##Under construction/maintenance city

Fully responsive minimal "under construction" city, which became less tightened as the window width decreases. It's a pure SCSS pen, no JS has been used.

The HTML uses two mainly <section> in order to separate the text and the city. The first one doesn't have much mystery; it's just a simply flexbox. The second one stands for the city stuff; internally it's just nested <ul> and <li> structure. I've decided to use this structure because it turns easy to imagine what's inside each list. In detail, the main <ul> represents the city cranes, buildings and trees, with all necessary parts inside (cables, cabin, arm, weight for cranes and tree and trunk for trees).

Regarding the SCSS, the interesting part in this pen, it's based in BEM methodology and it has been enriched with some useful key comments. I've used a SCSS loop to build each part (buildings, cranes and trees), including some conditions inside to shape the positioning of and detailing specific items. This is also useful to remove them in the responsive scenario and to add some delay between animations.

  • Buildings are made using a data-image background which is repeated (represents the windows) and a gradient which represent a shadow.

  • Cranes, the tricky part, are made using a coordination of animations, translating and changing the height of the hook. And changing the perspective property of the cables and other items to make the crane turn effect. There's only one SCSS crane constructor, the other cranes are made modifying the scale (and scaleX) properties. I've also played with the z-index property to put them at the desired depth.

  • Trees are made using the border property, simulating a pine tree (which it's easier than others) also playing with them depth. I've also changed the border-left color to simulate a shadow, as I did with the buildings.


Acknowledgements: Marian Alrt (@marianarlt) for the idea, crane and building construction.

A Pen by Mwongera Evans on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment