Yesterday, we made the function to build our 8-bit character, but it's still far from great. Let's use some Sass magic to make it better.
First, let's give some style to our character container. We create a map of flex variations (center, flex-end, etc), and we’ll use a mixin to easily assign them. This mixin receives the position (horizontal, vertical, or total) and the flex variations as arguments. Then, we use conditionals to verify if the variation is defined in our map. If it isn’t, we load default values. In case the variation exists, we verify the direction to assign the correct values to flex properties
align-item
,
align-content
, and
justify-content
. The direction keys are
h
for horizontal,
v
for vertical, and
t
for total.
// --assets/_variables.scss/
//flex variations
$flex_variations: (
"default": true,
"center": true,
"flex-end": true,
"flex-start": true
);
// --assets/_tools.scss/
@mixin flexbox($position, $variation: center) {
@if map_has_key($flex_variations, $variation) {
display: flex;
flex-wrap: wrap;
@if $position == "h" {
justify-content: unquote($variation);
} @else if $position == "v" {
align-content: unquote($variation);
align-items: unquote($variation);
} @else if $position == "t" {
justify-content: unquote($variation);
align-content: unquote($variation);
align-items: unquote($variation);
}
}
}
Now we can create a file in our components folder called
_character-container.scss
and use the mixin like this:
.character-container {
@include flexbox("h");
}
This still looks funny. Let’s add a
background-color
just calling the one we need from our map, using another Sass method called
map-get
. I have this transparent image of lines, which is a good match to the pixel look. Let’s add it, and then define a
background-size
of
80%
. We’ll give the container a
width
and
height
equal to the quantity of "pixels" in our character map, multiplied by the pixel size we have defined.
.character-container {
@include flexbox("h", "center");
background-color: map-get($colors, background);
background-image: url("https://ci6.googleusercontent.com/proxy/I9_wxwrAhiuQpSmQIfB35bP7cJgiSwDoMBK_c4YT6OqAgUNJC16_aDnSZnh8SdaAl8GkmtJD9ywNLtc-on0P1BRqxtixRPX9IPjpUrtsutnz9zwgZNLcuzb7A8NiuCHCKtCwzAGtqkdqOzV3Od2sevYNA56VZ_Q-M2MenDw=s0-d-e1-ft#https://gallery.mailchimp.com/f124657d471cc3500de9b20fd/images/5a43e19b-4719-4f30-b13b-5e08a6e993b9.png");
background-size: 80%;
height: $pixel-size*length(map-get($pixel-character, adam));
width: $pixel-size*length(map-get($pixel-character, adam));
}
Our character is out of our box. This happens because we move
1rem
to the right for each shadow value. Why
1rem
? Because that's the value we gave our
pixel-size
variable. To center our character we need to reset that, so we add
overflow: hidden;
and
position: relative;
to our container. Our character is now hidden, now we add
position: absolute
and set the left value to our pixel-size. We save this, and our character is centered, but only horizontally. To completely center it, we need to apply a negative pixel size to the top.
//--assets/components/_character-container.scss/
.character-container {
@include flexbox('h');
...
overflow: hidden;
position: relative;
...
}
//--assets/components/_pixel-adam.scss/
.pixel-adam {
left: $pixel-size;
position: absolute;
top: -$pixel-size;
...
}
Now our character is completely centered, but we can’t see the title. Let's make this box a little bigger, and move our character closer to the bottom. We can also give styles to our title. First we modify the
width
and
height
of our
character-container
. Then we give a top of
4rem
to our character. Now the character and the title are in the correct position. Lastly, we make our title white, and give it a text-shadow so it’s a bit more readable.
//--assets/components/_character-container.scss/
.character-container {
...
height: $pixel-size*length(map-get($pixel-character, adam)) + 8rem;
width: $pixel-size*length(map-get($pixel-character, adam)) + 3rem;
...
> .title {
color: white;
font-family: sans-serif;
text-shadow: .2rem .2rem 0 black;
}
}
//--assets/components/_pixel-adam.scss/
.pixel-adam {
left: $pixel-size;
position: absolute;
top: 4rem;
...
}
Nice! Our character and title are in position, but wait — if you look closely, the interaction between the character and the background is off. We want to make it look a little more three dimensional. I think a shadow for the feet would be enough, so let's add a
div
with class
boots-shadow
to our html.
...
<div class="pixel-adam">
<div class="boots-shadow"></div>
</div>
...
Now let's style it. We set the
width
and
height
to the same size as our character, but with a little more height. We need a defined size, so we’ll use percentage values. That way, even if we change the size of the pixels of the drawings, our shadows will still look good. Also, that extra height gives us enough room to move the shadows to the very bottom of both boots. After we define our character size, we define a
height
for our
boots-container
.
5.5%
is enough and a
width
of
80%
, which is a little bigger than the distance between our character’s two boots. Then we use
position: absolute;
and define a top equal to the height of our character. Basically, we are positioning the container just below the character itself. We give a right of
5%
just to center align the
boots-container
with the boots of the character.
//--assets/components/_pixel-adam.scss/
.pixel-adam {
...
height: $pixel-size*length(map-get($pixel-character, adam)) + 2.5rem;
width: $pixel-size*length(map-get($pixel-character, adam));
...
}
//--assets/components/_boots-shadow.scss/
.boots-shadow {
height: 5.5%;
position: absolute;
right: 5%;
top: $pixel-size*length(map-get($pixel-character, adam));
width: 80%;
}
Now, we're going to use
before
and
after
pseudo elements to simulate the shadows. We set a
border-radius
of
50%
to give the classic rounded shadow look, and instead of background, we use
box-shadow
due to its
blur
and
spread
parameters. Then we define two shadows, one internal using
inset
, and the other external with a little more blur. Lastly, we define a
width
, a
height
, and
content
to our pseudo elements.
.boots-shadow {
&:after,
&:before {
border-radius: 50%;
box-shadow: inset 0 -1rem 5rem 2rem rgba(black, 0.65), 0 -1rem 3rem 1rem
rgba(black, 0.65);
content: "";
height: 100%;
width: 30%;
}
}
Now we save this, and we have nothing. This is because everything else is absolutely positioned, so we have to do the same with the shadows. We add
position: absolute;
to our pseudo elements, and now we have a shadow. Let's separate them by adding a right and left to each pseudo element.
.boots-shadow {
&:after {
right: 7.5%;
}
&:before {
left: 12.5%;
}
}
Now we have both shadows correctly positioned, but this still looks bad. To fix it, we rotate both pseudo elements and add a
top
of
35%
:
.boots-shadow {
&:after,
&:before {
top: 35%;
transform: rotateX(80deg);
}
}
Now things look a lot better. Our character is completely styled, so let’s stop here. Tomorrow we’re going to animate our character, so stay tuned!
Comments for Build your own 8-bit character using Sass part II