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!