The Responsive Stick Figure
Who knew a stick figure would be the most difficult part of my portfolio…
My site had just been deployed. I transformed the template, took a new headshot, bought a domain, and chatted with Bluehost customer support for hours. Finally the project was done and I was proud to show it off. I sent the portfolio to my girlfriend to checkout. She sends me this screenshot:
After way too much time spent on the portfolio, it still wasn’t done. As you can see, on my girlfriend’s wide monitor the stick figure was getting cut off at the top and the feet placement was too high above the words. I couldn’t check this on my laptop, but I did decide to double check all of the phone options with Chrome inspect… and they were off, too!
I really, reaaally wanted to just say screw it and let my portfolio display properly for most devices. But a small part of me couldn’t let me do that. So, I had to mess with the CSS.
There were two major issues I had to face:
- The stick figure was part of the background image, not its own element.
- The words and their spacing would change as the screen width/height changed.
When I first made the portfolio, I created my background image in illustrator with the background color and figure as one file. I thought this was a good idea because I could use only one image, putting the swordsman in one place near the middle of the screen, and have it sit right above the word “Hi”.
This was not a good idea.
Sure, getting the site up with the swordsman as the background was quick. But when I adjusted the screen width, the text bunched up and rose vertically on the screen, covering the figure. My fix for this problem was to add a class on the “hi” h4 element. This class adjusted the top and bottom margins as the screen width changed using “@media”.
This made sure that as the screen widened and thinned, the word “hi” would always stay at about the exact spot vertically. There was still a bit of movement, but it was pretty darn close.
Now, the stick figure’s foot stayed just above the word “hi” on most devices. On some, however, the figure itself shrunk and warped, offsetting the swordsman (even with “hi” being in a fixed location). This was goes back to it being a background image. Here was the style:
Because the image had background-position: center center; it would keep the center of the background image in the dead center of the window. This includes height. The position of the stick figure on the background image is above the center. So when the screen became shorter, such as on an iphone 5, the figure would drop vertically, making the figure look closer to center. Since the text did not have the same properties as the background image, the image and text would overlap.
This is similar to what was happening on my girlfriend’s wide monitor. Except the head being cut off on her monitor was due to the image having the property: value “background-size: cover”. When the screen width becomes wider than the image width, background-size: cover causes the image to zoom. This is so the width of the screen and the picture stay the same. And to prevent warping, the top and bottom of the image go above and below the edge of the screen. Since her screen was wider than my background image, the stick man rose vertically, further away from the text.
So what was the solution? Not having the figure be part of the background image.
I made the new background image as one solid color, and exported the swordsman as its own image. My plan was to use absolute and relative positioning to fix the foot of the stick figure right above the word “hi”. As with most things with coding, this was more difficult than I thought it would be.
First I tried putting position: relative on the h4 “hi” and position: absolute on the img directly under it in the HTML. This didn’t work. After looking around online, I decided a better approach would be to think about the box model, and put relative onto an entire div. So, I made a div with the “Hi” as a child element, and gave the div position:relative. Then, I made a second div with the img as a child element, and gave this second div position: relative. Again this didn’t work. I noticed that the image kept choosing the body, and other elements, and not the word “hi”.
Finally I got my HTML correct:
Here, the img is in it’s own div with position: absolute. This div and the h4 “hi” are both inside of a div with position: relative. I was on the right track thinking of the box model, but I hadn’t put the “box” with the image as a child of the div with position: absolute. With it as a child, the stick figure would be relative to the parent. Now I had control over where the stick figure would appear in relation to “hi”.
First, I set the width of the swordsman and it’s position to work on a standard laptop screen:
Remember my earlier “@media” usage to keep the “hi” from changing its vertical position? Now I had to use “@media” for the swordsman:
The swordsman drifted to the right as the screen thinned. This is because the swordsman had the property left: 45%;. Since the word “hi” was fixed to center, the horizontal position at left: 45%; would not always be the exact same amount of pixels away from center as the screen adjusted. Using “@media” to add left 40% and 42% at certain px widths, I was able to keep the foot directly over the text as the screen adjusted.
There was just one issue left. When the height of the screen shrunk, the stick figure would be pushed up. The image itself wouldn’t get smaller, and therefore on shorter devices, the head would get cut off. To change this, I added a final “@media” based on height.
Now, whenever the screen was under 700px tall, the height of the stick figure image would always be 29% of the viewport height. I added Width: auto; so the stick figure kept the correct height and width proportions and didn’t warp as if it was going into a black hole.
And that was it! It’s not a huge coding problem solved, but when I went through the devices on chrome inspect and saw that it was responsive on all of them, I was ecstatic and showed it off to my bootcamp peers.
This is something I absolutely love about coding. I can get stuck on a problem that should be quick and simple. I can keep trying solutions and yet it doesn’t work. But then when it does work, I feel like this: