How to Create a Responsive Square with CSS
During a recent project I came upon an interesting CSS problem. I needed to create a square element that would maintain its square shape as it responsively resized to a changing window size.
The Problem
It is easy to create a square when we can explicitly declare its ‘width’ and ‘height’ :
However, when we try to make our square element responsive by changing our units to percentages, we run into a problem:
The element’s width is calculated as a percentage of its parent’s width, while its height is calculated as a percentage of its parent’s height. Because our width and height are calculated from different measurements, the square will no longer hold its shape.
The Solution
After quite a bit of searching, I came upon a surprising solution to the problem. By making use of the :after pseudo-element and ‘padding-bottom’ , we can create our responsive square using only CSS.
The solution relies on the somewhat counterintuitive fact that padding is calculated as a percentage of its parent element’s width, not height. This rule applies, even for ‘padding-top’ and ‘padding-bottom’ , despite being vertical measurements.
To capitalize on this fact, we must first remove the ‘height’ property from our .square element. In its place, we add an empty :after element to .square and set ‘padding-bottom: 100%’ :
Because the pseudo element’s padding is calculated as a percentage of its parent’s width, and its parent is our .square element, we are effectively fixing the height of the pseudo-element to the width of .square . Whenever .square ’s width changes, so will the pseudo-element’s height.
Adding Content
Finally, we might like to add some content to our .square element. The above solution relies on both .square and .square:after having a height of 0, so adding content to either of them would break our solution.
Fortunately, this problem is easily solved by creating an absolutely positioned element and placing it within .square . The new element can be sized to match the square, but since it is absolutely positioned, its content will not affect the dimensions of our square:
.square < position: relative; width: 50%; >.square:after < content: ""; display: block; padding-bottom: 100%; >.content
A width-responsive perfect square in pure CSS
The resize property — I wasn’t aware you could actually control this past textareas, but stumbled upon it when looking for a way to make a user-resizable div without using JavaScript.
How the square is made
#square width: 100%; padding-bottom: 100%; position: relative; background-color: #2980b9; >
- width: 100% is to make sure it’s defined as having the same width as its outer, resizable container.
- padding-bottom: 100% is based on a trick in the CSS spec. When specifying a margin or padding by percentage, it’s always based on the width, even if it’s a -top or -bottom property. In this way we get a property that’s equal to the width.
- position: relative is so that I can put stuff inside it without disrupting the padding; any additional content would add content to the box, which would make it a rectangle
- background-color is there so you can see where it is ¯\_(ツ)_/¯
How the circle is made
Once you have any square, making a circle is easy enough. The only trick you really need is border-radius: 50% , but let’s break down the responsive circle a bit more.
#circle position: absolute; top: 0; bottom: 0; width: 100%; height: 100%; border-width: 4px; border-color: #27ae60; border-style: solid; border-radius: 50%; >
- position: absolute makes sure that this circle stays within the position: relative square while not adding any in-flow content to it.
- top: 0; bottom: 0; width: 100%; height: 100%; constrains the circle to the exact dimensions of the responsive square. At this point, what we have is a position: absolute container that is an inner copy of our square.
- The border-* properties are used to build the outline of the circle. We have a 4px green solid border, and it has a radius of half the edge of the square.
Quick geometry recap
Here’s an illustration of why 50% is the magic number to make a circle from a square:
The radius of the circle is equal to half the side of the square.
How to style a div to be a responsive square? [duplicate]
I want my div to adapt its height to always equal its width. The width is percental. When the parent’s width decreases, the box should decrease by keeping its aspect ratio. How to do this is CSS?
Square elements in pure css is challenging and with limitations, but has been answered before. Another useful reference may be this answer.
6 Answers 6
Works on almost all browsers.
You can try giving padding-bottom as a percentage.
The outer div is making a square and inner div contains the content. This solution worked for me many times.
This is very good tutorial if you want to use padding-bottom method. [link]dwuser.com/education/content/…
Preferable to the chosen answer because it works within the constraints of a container, NOT the viewport which is rarely useful
@C.Lee You have to add position: absolute; on the inner div to make it work. Elements with absolute positioning are ignored when the parent dimensions are calculated. That means you can add content, but also padding, borders, etc to the inner element. 🙂 See this fiddle.
To achieve what you are looking for you can use the viewport-percentage length vw .
Here is a quick example I made on jsfiddle.
I am sure there are many other ways to do this but this way seemed the best to me.
This is definitely the cleanest solution. For people interested in browser support, I found this overview.
This solution doesn’t play nice with a grid system. If you’re looking at squares expanding with columns width, the answer of @rahulbehl works better.
Tip: if you want to fit a square inside a viewport on either portrait or landscape view: «` @media (orientation:portrait)
.square-box < position: relative; width: 50%; overflow: hidden; background: #4679BD; >.square-box:before < content: ""; display: block; padding-top: 100%; >.square-content
This solution works really well when the width might be restricted by a ‘max-width’ rule. In those cases the actual computed width might be less than the width set in percentage and all the other solutions which set the padding directly on the outermost element will fail.
This works because that the padding of an element is calculated relative to the width of its parent element.
I have been looking for answers to keep aspect ratio of divs while resizing them with flex box and this is the only one that worked perfectly. Pure magic, thanks!
It is as easy as specifying a padding bottom the same size as the width in percent. So if you have a width of 50%, just use this example below
Edited version with responsive text: http://jsfiddle.net/kJL3u/394
You can fix that problem with overflow:hidden or other absolute positioning of children inside the container. Conveniently exactly like @gidzior’s answer
Another way is to use a transparent 1×1.png with width: 100% , height: auto in a div and absolutely positioned content within it:
This is a more useful method, because you have actual size and height to work with — useful for elements inside the square div.
This is what I came up with. Here is a fiddle.
First, I need three wrapper elements for both a square shape and centered text.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
This is the stylecheet. It makes use of two techniques, one for square shapes and one for centered text.
body > div < position:relative; height:0; width:50%; padding-bottom:50%; >body > div > div < position:absolute; top:0; height:100%; width:100%; display:table; border:1px solid #000; margin:1em; >body > div > div > div