fales
fales

Reputation: 99

Make biggest square possible in HTML/CSS

I have a parent <div> of unknown size and I would like to create a child <div> of the size of the biggest square which can be contained in the parent and center this square in the middle of the parent. Is it possible with HTML and CSS?

I am aware of max-width and max-height but do not know how to ensure the aspect-ratio.

I want to be able to do something like this:

.frame {
  height: 80%;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.square {
  width: 750px;
  height: 750px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.back {
  width: 100%;
}

.front {
  width: 70.5%;
  top: 23.965%;
  position: absolute;
}
<div class="frame">
  <div class="square">
    <img class="back" src="back.png">
    <img class="front" src="front.png">
  </div>
</div>

But in the square I want the width and height set based on its parent frame as described. The parent frame can be both landscape or portrait.

Upvotes: 0

Views: 925

Answers (1)

tbjgolden
tbjgolden

Reputation: 1335

This was not possible for a long time; as padding-top:100% and aspect-ratio:1/1 are limited to the width (and not the height) of the container.

BUT It is now possible; keep reading...

The Problem

███ <- square fills the width correctly
███ 
░░░ <- outer box (portrait)
░░░
███████████ \
███████████  } <- outer box (landscape) stops here
███████████ /     but square overfloweth
███████████
███████████
███████████

The "Solution"

Technically, the aspect-ratio doesn't fill the width, so much as the "block direction", which in western languages is always the width...

However, we can change the writing-mode property to get the block direction to be height, like so:

writing-mode: vertical-lr

███░░░ <- outer box (landscape)
███░░░
 ^- square fills the height correctly
███████ 
███████ 
███████
███████
^---^
   `---- outer box (portrait) stops here, but square overfloweth

So now we have the opposite problem, it works in landscape but not portrait.

The Magic

Using the right combination of media queries it should be possible to switch the writing mode at the exact dimensions it switches from portrait to landscape.

html, body {
  margin: 0;
}

*, *:before, *:after {
  box-sizing: border-box;
}

.bounds-outer {
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
}
.bounds-inner {
  writing-mode: vertical-rl;
  width: 100%;
  max-width: 90%;
  height: 100vh;
  border: 1px dashed black;
  display: flex;
  align-items: center;
}

.a {
  position: relative;
  flex: 1 0 1px;
  background: red;
  padding-block-start: 100%;
}

.b {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  color: white;
  writing-mode: horizontal-tb;
}

/* this media query depends on layout */
@media (max-aspect-ratio: 10/9)  {
  .bounds-inner {
    writing-mode: horizontal-tb;
  }
}
<div class="bounds-outer">
    <div class="bounds-inner">
      <div class="a">
        <div class="b">
          Hi
        </div>
      </div>
    </div>
</div>

NOTE: Your media queries will depend on the size of the box. Verified in Chrome, Firefox and Safari.

Upvotes: 3

Related Questions