The Frame Component
In this lesson, we will build the Frame primitive, which frames out a visual media, like an image or video, and forces it into the aspect ratio needed for the design without distorting the image.
Images on the web are surprisingly tricky. A whole course could be devoted to best practices for images on the web, but from a layout point of view, one of the more difficult parts to deal with is the size and aspect ratio. The images we use are rarely the same size and aspect ratio as our web page's design. This problem is compounded by the need to support multiple viewports that our image will need to load. We typically deal with the size issue by making the image size responsive - we can set the
max-width of the image to
100%, which we did in our CSS Reset.
However, dealing with aspect ratios is not as simple. Images have an intrinsic aspect ratio based on the actual width and height of the image file. If we try to force the image into a box of a different aspect ratio, then the image becomes skewed and deformed.
We need a way to not just control the size, but also the aspect ratio, by cropping the image where it is too tall or too wide for the aspect ratio we need.
In this lesson, we will build the Frame primitive, which frames out a visual media, like an image or video, and forces it into the aspect ratio needed for the design, without distorting the image.
The problem: the New Arrivals#
In this lesson, we are going to build a "New Arrivals" card, like this:
In the above widget, the image is cropped at a 1:1 aspect ratio, or in other words, a square. It also needs to be responsive to the size of the parent container by growing or shrinking accordingly.
Here is how our code starts out. You can follow along at the starter project over at codesandbox.io:
And this is how it looks:
So let's start building our Frame primitive:
It may seem like a lot is going on here, but it isn't. First, we are setting the Frame primitive to have a
relative position and setting the width and height to
18rem. These settings will give us an
18rem square box.
Next, we are selecting all the direct children, setting the position to be
absolute, and setting the
right properties to 0. Zero is one of those unique values in CSS that you never have to give the unit of. That is because zero of any unit, be it
vw, will always still be zero. The value you set to each of these properties is how much you want to offset from the
bottom, for example. By setting these properties to zero, we are effectively pinning the children to the outer div element, ensuring the child will be the same size as the outer div that is wrapping the image. Then we are setting the
height to be
100% to force any media object to fit in the box.
Now we just need to wrap our
img tag with our Frame primitive, like this:
And our New Arrivals component looks like this:
We have a square now, but the image is distorted as we've forced it into a square box. The image is also too small in this view. In other views it will be too large. What we need is a way to keep the aspect ratio, without hard-coding the size itself.