CSS square and rectangle

CSS square and rectangular containers with a fixed aspect ratio are very easy to implement when they are also fixed-size. It's just a matter of specifying width and height in pixels. When adding responsiveness, keeping an aspect ratio is not straighforward. For responsive shapes, using paddings is the way to go.

In this article I share the code used to create fixed-size and responsive CSS squares and rectangles with vertically centered content, which is a common use for them. An SVG image with a width percentage width and height:auto is an alternative to CSS squares. However, SVG adds the overhead of loading an extra file and won't hold content.

Fixed size CSS square

For a fixed-size CSS square:

I'm a 200 x 200 px square with centered content no matter how many lines it takes
<div class="fixed-size-square">
    <span>I'm a 200 x 200 px square with centered content no matter how many lines it takes</span>
</div>
.fixed-size-square {
    display: table;
    width: 200px;
    height: 200px;
    background: #4679BD;
}
.fixed-size-square span {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
    color: white
}

The content is vertically centered in the square using a CSS table-cell trick. For a rectangle just change width and height values.

Responsive CSS square and rectangle

As strange as it may seem, creating basic responsive shapes like a CSS rectangle that keeps its aspect ratio is not straighforward. For these kind of shape, using paddings/margins is the way to go. CSS percentage heights are calculated against parent's height while paddings are calculated against parent's width. This makes keeping an aspect ratio as easy as adding a percentage padding-bottom or padding-top to a zero-height element. However, there's trouble when the element is supposed to hold text.

I had to google for a while to find a way to create a responsive square div with content using CSS only. I thought it was worth re-sharing as it works perfectly and most of the solutions out there are not as simple:

The trick is using absolute positioning to make the content div fit the outer box div. This outer div is stretched to form a rectangle/square using the before pseudo-element. The content is then removed from the flow with position:absolute; and forced to fit with top:0; bottom:0; left:0; right:0;. A third div and a span are added just to vertically center the content using the table-cell trick.

The content may overflow the background so using overflow:hidden; or overflow:scroll; may be a good idea. For a square:

I'm a responsive CSS square with centered content!
<div class='square-box'>
    <div class='square-content'><div><span>I'm a responsive CSS square with centered content!</span></div></div>
</div>
.square-box{
    position: relative;
    width: 50%;
    overflow: hidden;
    background: #4679BD;
}
.square-box:before{
    content: "";
    display: block;
    padding-top: 100%;
}
.square-content{
    position:  absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    color: white;
}
.square-content div {
   display: table;
   width: 100%;
   height: 100%;
}
.square-content span {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
    color: white
}

Here's a Fiddle. To change the rectangle's aspect ratio just change the padding-top of the pseudo-element. For a 2:1 CSS rectangle:

I'm a responsive CSS rectangle! Resize the window to see how I keep my aspect ratio.
<div class='rectangle-box'>
    <div class='rectangle-content'><div><span>I'm a responsive CSS rectangle! Resize the window to see how I keep my aspect ratio.</span></div></div>
</div>
.rectangle-box{
    position: relative;
    width: 50%;
    overflow: hidden;
    background: #4679BD;
}
.rectangle-box:before{
    content: "";
    display: block;
    padding-top: 50%;
}
.rectangle-content{
    position:  absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    color: white;
}
.rectangle-content div {
   display: table;
   width: 100%;
   height: 100%;
}
.rectangle-content span {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
    color: white
}

For a Fiddle, use the responsive square's JSFiddle. The only difference is in padding-top. For a tall rectangle, remember padding may take values higher than 100% (eg. padding-top:200% for a 1:2 rectangle). Please share any suggestions or issues on the CSS square or rectangle.

3 comments

  1. This is great! Thanks!

    Now I have an issue:

    when i change

    .square-box{
    position: relative;
    width: 12vw;
    overflow: hidden;
    background: #4679BD;
    }

    to :

    .square-box{
    float:left;
    width: 12vw;
    overflow: hidden;
    background: #4679BD;
    }

    to have a group of 5 squares one next to the other, the TEXT DISAPPEARS.

    Any suggestion??

    Regards,

    Andrea

  2. Nice trick man!!
    after hard work and achieve it using paddings, as you mention before, I arrived to your post. Couldn't be more deeper and clearer about the thing!!

Leave a Reply

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>