On January 12, 2016, web developers sounded a collective cheer. That day marked the end of support by Microsoft for their Internet Explorer browsers older than version 11. (By the way, if you’re using one of those older versions, you really need to update your browser, or even try a different browser.) One of the major reasons for that celebration is that it paved the way for the incorporation of a long-awaited layout tool in CSS.
Introducing: Flexbox
At this time, all vendor-supported versions of the major browsers available support flexbox. While not all browsers have the best support (yes, we’re still talking about you, Internet Explorer), they all support flexbox well enough to start using it in production. For the bugs that you may run into, check out Philip Walton’s Flexbugs site for known issues and workarounds.
The Project
A few weeks ago, I was working on a project for a client that had four circular call-out sections on their home page. Each section had a background image and a text area. The sections would stack vertically in a single column on smaller viewports, but would be displayed in a single row on wider viewports. The width of the containing element they were in adjusted with the size of the viewport. The sections needed to be able to adjust along with the container. I immediately recognized this as a chance to put flexbox to use.
To make the sections display as circles, I was going to need to start by creating perfect squares. Then, I could use a border-radius set at 50% to perfectly round the section into a circle. In the old days, I may have set exact width and height for the elements, but that wasn’t going to work here. Due to the flexible nature of the call-out sections, it was impossible to set an explicit width for them. Instead, their width was going to be dependent on the screen they were displayed on. Another issue that I was facing was that width and height for elements are calculated differently.
Go Ahead, Make My Day
So, how could I set flexible width and height for these elements? Luckily, Mark Hinse at made my day literally made my day. As he explained in his blog post, when setting an element’s margin with percentages, that value is determined by the width of the container. That means that the top and bottom margin values are set using width, not height! Armed with that bit of knowledge, I was then able to use the rest of his blog post to create those call-out sections at a perfect 1:1 ratio.
The HTML
The “trick” here is simple. You start by creating the outermost (parent) element for the section and giving it a flexible width (again, I was using flexbox for this part). That parent element must also have a position property of “relative”. Next, we nested another div (child) within the parent div and set the position property to “absolute” while positioning it to stretch to all 4 edges of the parent container. This was also the layer that received the overlay effect. Unfortunately, the parent container still wasn’t a perfect square. That’s where the trick comes in.
The CSS
I used the ::before
pseudo-element with the parent container. I then set that pseudo-element to display as a block level element. To ensure that the element would render, but still remain empty, I used content: ' '
. Finally, I added a padding-top of 100% to the ::before
pseudo-element. When using percentage values with padding and margin, the calculated value is based on the width of the parent element. So, by using a value of 100%, we’re adding height to the pseudo-element that is exactly the same as its width.
After the pseudo-element was setup, I then setup the div that was going to display the overlay. I set that element to be absolute positioned and set all four edges to a position of 0. That stretched the overlay out to cover the div entirely. Once that was setup, I just had to add a background-color with some transparency to it. The final step was to add the text to the content.
Get Out There And Use It
As you can see, this trick can be quite useful. You can even use it for other things besides making perfect circles. Just make sure that the percentage value that you set for the top padding on the parent pseudo-element matches the ratio you’re trying to achieve. For example, a box that is twice as tall as it is wide would use a padding-top value of 200%. If you want the box to be twice as wide as it is tall, set the padding-top value to 50%.