CSS: keep aspect ratio without overflowing content
Asked Answered
M

1

10

I am using CSS and I want to create a box with a certain ratio that is kept no matter the size of the box. But also I want the box to grow if there is more content in it.

To summerize in order words:

  • CSS only (if possible)
  • preserve given aspect ratio
  • allow box to grow if there is more content (with ratio)

In those techniques I've tried so far the content of the box is not able to make the box grow. Instead my only options are overlapping or clipping the content.

  1. Padding-ratio Hack
  2. Viewport based units
  3. Replaced Element Scale Hack

The first and the third method are preoccupying the space inside of a wrapper and the content is place on top of that using absolute position. Since the content is absolutely positioned it is removed from the document flow. Therefore it is unable to expand the wrapping element.

The Second Option is using a fixed height, which doesn't allow the content to grow beyond it either.

Here is a demo using the second option. (based on viewport units)

* {margin: 0; padding: 0;}
div{
  width: 50vmin; height: 50vmin;

  font-size: 30px;
  background: #ccc;
  margin: auto; 
  padding: 3%;
}
<div>
 <p>If you scale your window, you will see that the text does not fit into the box at some point, and therefore the text will be overlapping the box.<p>
</div>

Further Methods I partially tested:

  • object-fit positioning
  • flexbox

Object-Fit only affects replaced-elements as far as I know. I am unable to get any effect on my div/p-elements with this properties.

Flexbox is not practical either for my scenario. According to my current level of knowledge flexbox does not help here very well. Since its mostly about establishing relationships between multiple items. But I am not sure about that. Maybe there is something in flexbox that I am not aware of yet.

Marv answered 2/3, 2016 at 16:50 Comment(8)
so if the content is too large for the box, the box overflows its container?Krishnakrishnah
@Krishnakrishnah yes, the content is overflowing the box.Marv
try div { font-size: 4.5vmin; }Bridoon
@TamilSelvan good point! But I don't know for sure how much content there is.Marv
Basically, you need Javascript. CSS isn't designed with aspect ratios in mind. You can fake it but it's just not built that way.Swage
Try fittextjs.com javascript for itBridoon
Consider the CSS object-fit property: https://mcmap.net/q/1168767/-fill-a-div-with-an-image-respecting-aspect-ratioCarmine
@Michael_B I did but it does not have any effect on non-replaced elementsMarv
V
2

Update

OP is now emphasizing the importance of text, so here's my take:

  • Using a background-image and background-size:contain.
  • figure has the background-sized background-image
  • figcaption is holding the text.
  • This particular png is 800x600 AR 4:3 which it maintains admirably.
  • The text flows well between resizes and the inevitable overflow of text is cutoff, but never breaches the borders.

Plunker

Snippet

@font-face {
  font-family: EraserRegular;
  src: url(http://glpjt.s3.amazonaws.com/so/font/EraserRegular.ttf);
}
html {
  box-sizing: border-box;
  font: 500 16px/1.428'EraserRegular';
  height: 100vh;
  width: 100vw;
}
*,
*:before,
*:after {
  box-sizing: inherit;
  margin: 0;
  padding: 0;
}
body {
  position: relative;
  font-size: 1rem;
  line-height: 1;
  height: 100%;
  width: 100%;
  overflow-x: hidden;
  overflow-y: scroll;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
h1,
h2,
h3,
h4,
h5,
h6,
legend {
  font-variant: small-caps;
  margin-bottom: 15px;
}
h1 {
  font-size: 1.5rem;
}
h2 {
  font-size: 1.4rem;
}
h3 {
  font-size: 1.3rem;
}
legend {
  font-size: 1.35rem;
}
p {
  margin: 0 5px 15px;
}
img {
  display: inline-block;
  width: 25em;
  height: auto;
  margin: 20px 0;
}
a {
  color: #Fc0;
  text-decoration: none;
  margin: 10px 20px;
  display: inline-block;
}
a:hover {
  color: #CCC;
}
button {
  font: inherit;
  line-height: 1.5;
  padding: 1px 3px;
  border-radius: 8px;
  border: 1px solid #fc2;
}
.noSel {
  -moz-user-select: none;
  -webkit-user-select: none;
  user-select: none;
}
code * {
  font: 100 1rem/1.5'Consolas';
  color: #6F3;
  background: #777;
  border: 2px inset #CCC;
  margin: 10px 10px 15px 15px;
}
.board {
  width: 100%; padding-bottom: 75%; height: 0; position: relative; background: url(http://i.imgur.com/gUobVE5.png) center center no-repeat;  background-size: contain; }
  figcaption {
    font-size: 100%;
    color: white;
    text-align: left;
    position: absolute;
    z-index: 1;
    max-width: 100%;
    max-height: 100%;
    padding: 40px 30px;
  }
<figure class="board">
  <figcaption>TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST
    TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST
    TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST
    TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST
    TEST TEST TEST TEST TEST TEST TEST</figcaption>
</figure>

Two properties come to mind is object-fit: contain and background-size:contain in conjunction with background-image The value contain invokes a certain behavior:

background-size / -image

figure {
    background: url(https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png) center center no-repeat;
    -moz-background-size: contain;
    background-size: contain;
    width: 9em;
    height: 9em;
}
code { font: 400 14px/1.3 'Consolas'; background: #ccc; }
<figure></figure>
<figcaption><code>background-image</code> and <code>background-size:contain</code> also maintains it's AR;<br> fixed lengths are not required; <br>this is for replaced objects like images and videos</figcaption>

Multiple background-images

section { width: 100vw; height: 100vh; display:table; }
.shirley_lenna {
  background: url(http://4.bp.blogspot.com/_xyCeswQjRbc/TTTtaB5t2vI/AAAAAAAACCc/lc_kHPTSnSg/s1600/Shirley+02.jpg) left center no-repeat, url(https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png) right center no-repeat;
  background-size: contain;
  width: 100vw;
  min-height: 20em;
  display: table-cell;
}
<section>
<figure class="shirley_lenna"></figure>
  
  </section>

object-fit

img {
    width: 140px;
    height: 140px;
    border: solid 1px white;
    object-fit: cover;
}

code { font: 400 14px/1.3 'Consolas'; background: #ccc; }
<figure>
<img src="https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png">
<figcaption><code>object-fit</code> maintains AR;<br> must use fixed width and height;<br> for replaced objects like img, video, etc.</figcaption></figure>
Velleman answered 2/3, 2016 at 17:15 Comment(2)
I know about this method. But I have to deal with text rather than only an image.Marv
@Marv Sorry, I tend to focus on a single aspect when a topic has the potential to expand. Please review the update, it addresses both image and text.Velleman

© 2022 - 2024 — McMap. All rights reserved.