tavoyne
tavoyne

Reputation: 6539

Sizing a grid column based on a child's aspect ratio

My question is similar to this one: I'm trying to contain an aspect-ratio element within its parent element. One difference though, this aspect-ratio element has siblings—a header and a footer—and all this nice family should be center-aligned and share a common width.

Images are worth a thousand words:

enter image description here

GIFs are worth a thousand images:

enter image description here

I'm close to that result, but I'm not quite there yet:

body {
  height: 100%;
  margin: 0;
}

html {
  background-color: lightgrey;
  height: 100%;
}

#footer,
#header {
  background-color: blue;
  height: 50px;
}

#paper {
  aspect-ratio: 1;
  background-color: red;
  margin: auto;
  max-height: 100%;
  overflow: hidden;
  width: 100%;
}

#wrapper {
  align-content: center;
  display: grid;
  height: 100%;
}
<div id="wrapper">
  <div id="header"></div>
  <div id="paper"></div>
  <div id="footer"></div>
</div>

Any CSS wizard to help me out?

Upvotes: 2

Views: 490

Answers (3)

tavoyne
tavoyne

Reputation: 6539

Actually Container Queries enable us to solve this kind of problems elegantly.

Support for this feature is currently very bad (see here), but it's part of Interop 2022 so I guess it'll look different by the end of the year.

I post this as an answer as it might help someone in the future 👽👋

Note that you currently need to turn on a flag on Chrome to be able to test it.

body {
  container-type: size;
  height: 100%;
  margin: 0;
}

html {
  background-color: lightgrey;
  height: 100%;
}

#footer,
#header {
  background-color: blue;
}

#paper {
  background-color: red;
}

#wrapper {
  align-content: center;
  display: grid;
  grid-template-columns: min(100cqi, (100cqb - 100px));
  grid-template-rows: 50px min(100cqb - 100px, 100cqi) 50px;
  justify-content: center;
}
<div id="wrapper">
  <div id="header"></div>
  <div id="paper"></div>
  <div id="footer"></div>
</div>

Here's the same code but relying on viewport units (works in all browsers):

body {
  height: 100%;
  margin: 0;
}

html {
  background-color: lightgrey;
  height: 100%;
}

#footer,
#header {
  background-color: blue;
}

#paper {
  background-color: red;
}

#wrapper {
  align-content: center;
  display: grid;
  grid-template-columns: min(100vw, (100vh - 100px));
  grid-template-rows: 50px min(100vh - 100px, 100vw) 50px;
  height: 100%;
  justify-content: center;
}
<div id="wrapper">
  <div id="header"></div>
  <div id="paper"></div>
  <div id="footer"></div>
</div>

Upvotes: 0

Temani Afif
Temani Afif

Reputation: 272703

Not sure if you can get all the requirements but here is the best I could do (seems to work on chrome only)

body {
  background-color: lightgrey;
  margin: 0;
}

#footer,
#header {
  background-color: blue;
  height: 50px;
}

#paper {
  aspect-ratio: 1;
  background-color: red;
  max-height: 100%;
  max-width: 100vw;
}

#wrapper {
  place-content: center;
  display: grid;
  height: 100vmin;
  margin-block: max(0px,50vh - 50vmin);
  grid-template-rows: auto minmax(0, 1fr) auto;
}
<div id="wrapper">
  <div id="header"></div>
  <div id="paper"></div>
  <div id="footer"></div>
</div>

If the 50px is known you can do like below:

body {
  background-color: lightgrey;
  margin: 0;
  --h: 50px; /* the fixed height */
}

#footer,
#header {
  background-color: blue;
  height: var(--h);
}

#paper {
  aspect-ratio: 1;
  background-color: red;
  width: min(100vw,100vh - 2*var(--h));
}

#wrapper {
  place-content: center;
  display: grid;
  height: min(100vh, 100vw + 2*var(--h));
  margin-block: max(0px, (100vh - 100vw - 2*var(--h))/2);
  grid-template-rows: auto minmax(0, 1fr) auto;
}
<div id="wrapper">
  <div id="header"></div>
  <div id="paper"></div>
  <div id="footer"></div>
</div>

Upvotes: 1

Anton
Anton

Reputation: 8508

Try this solution, all the magic happens in grid-template-columns and grid-template-rows.

html {
  background-color: lightgrey;
  height: 100%;
}

body {
  height: 100%;
  margin: 0;
}

#wrapper {
  --footer-header-height: 50px;
  align-content: center;
  display: grid;
  height: 100vh;
  grid-template-columns: 1fr minmax(auto, calc(100vh - var(--footer-header-height) * 2)) 1fr;
  grid-template-rows: auto minmax(auto, 100vw) auto;
}

#footer,
#header {
  grid-column: 2;
  background-color: blue;
  height: var(--footer-header-height);
}

#paper {
  grid-column: 2;
  aspect-ratio: 1 / 1;
  background-color: red;
}
<div id="wrapper">
  <div id="header"></div>
  <div id="paper"></div>
  <div id="footer"></div>
</div>

Upvotes: 1

Related Questions