Specify the natural size of an HTML element
Asked Answered
H

3

13

Let's talk about images in HTML. If I drop an image onto the page with no other constraints, it will assume its "natural size"---that is, the literal size of the image in pixels. If I specify a CSS max-width and max-height then it will keep its natural aspect ratio but scale down to fit the size constraint. Awesome!

I want that exact behavior on an arbitrary element. That is, I want to create a <div> or something else that has a natural size (which I would specify in pixels) and maintains its aspect ratio when affected by max-width and max-height. (Bonus points: it would be cool if the technique also supported min-width and min-height.)

Here is some more information I have collected:

  • For an HTML5 image you can read the natural size of an image with the naturalWidth and naturalHeight attributes, provided the complete attribute is true. Unfortunately, as MDN points out, these properties are read-only and are specific to image elements.

  • This approach is brilliant, but (even though the height responds to max-width) the width does not respond to max-height.

  • A bit of searching has failed to turn up a CSS-only solution, which makes me think that one may not exist. I will also accept JavaScript solutions, but they need to be robust to changes in window size and parent element size.

Habitforming answered 27/7, 2012 at 20:57 Comment(3)
I think this is a proposed feature of CSS4. You are then able to define a length as a fraction of another length. Since tags don't have a natural size this is probably the closest you can get. I see if I can find the reference and will post it here.Eudocia
So, you would first define the CSS width and CSS height of the DIV, and then you would additionally define max-width and/or max-height in order to shrink the DIV, correct?Leix
@ŠimeVidas Yes, but it is important that the aspect ratio be maintained. Just setting width/height/max-width/max-height is not enough.Habitforming
M
2

Here's my super duper solution:

The HTML

<div class="ratioBox">
    <div class="dummy"></div>

     <div class="el">This is the super duper ratio element </div>

</div>

The CSS

.ratioBox{
    position: relative;
    overflow: hidden;      /* to hide any content on the .el that might not fit in it */
    width: 75%;            /* percentage width */
    max-width: 225px;
    min-width: 100px;
    max-height: 112.5px;
    min-height: 50px;  
}

.dummy {
    padding-top: 50%;      /* percentage height */
}

.el {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: silver;
}

​

See it working here: http://jsfiddle.net/joplomacedo/7rAcH/

The explanation, in case you can't understand what is happening, will come at the end of the day as I'm unfortunately out of time. [it's July 28, 2:54PM (GMT Time) as I write this]

Melitta answered 28/7, 2012 at 13:44 Comment(5)
This is also explained at ansciath.tumblr.com/post/7347495869/css-aspect-ratio (though display: inline-block is mentioned there, which is not present here). The comments also mention a workaround for IE 7.Neogothic
It's not the same thing as what the author of that post does there - it's similar but in some fundamental aspects it's not the same. I started by simplifying that solution, which got me to this jsfiddle.net/g9Awv . It accomplishes the same thing, but it uses one less element. From there I got to the code above (which allows max and min widths)Melitta
Oh... and the display: inline-block I guess, is there because img elements have that too. The author, probably, might have wanted to make the block behave like an image.Melitta
After looking at this more closely, it seems the post I linked is claiming to use inline-block to get "shrink-to-fit" behaviour, but the CSS spec says that behaviour only applies once the width is set to auto... Odd. Your solution works pretty well and looks straightforward, thanks for sharing.Neogothic
Clever, but this seems to suffer from the same problem as the one at ansciath.tumblr.com/post/7347495869/css-aspect-ratio: if you scale the page horizontally then the height adjusts properly, but if you scale the page vertically then the width does not adjust properly.Habitforming
E
1

Resize a div like an image with CSS

DEMO : resize the result window (width and height) to see the div resize like the image.

In the demo you can see both image and div resize the same way according to the height and the width of the result window viewport.

This technique uses vh/vw units. They alow you to set the width according to the height of viewport and the height according to the width of viewport.
With the combined use of max-width and max-height you can make it behave and resize like an image on browser resize.
Browser support for these units : IE9+. For more info see canIuse.
The above demo uses a 1:1 aspect ratio but you may with a bit of calculation use any other aspect ratio, examples :

  • 4:3 aspect ratio : demo
  • 16:9 aspect ratio : demo

CSS (for a 1:1 aspect ratio)

div{    
    width: 80vw; 
    height: 80vh;

    max-width: 80vh;
    max-height: 80vw;
}

One step further : vmin and vmax

You can also use vmin/vmax. These units select the minimum or maximum value between the width and height of viewport so you can have the max/min-height and max/min-width desired behaviour. But the browser support for these units isn't as good as vh/vw (canIuse).

Demo

CSS (for a 1:1 aspect ratio) :

div{    
    min-width:200px;
    min-height:200px;

    width: 80vmin; 
    height: 80vmin;

    max-width: 800px;
    max-height: 800px;
}
Ectophyte answered 25/5, 2014 at 13:11 Comment(2)
This is a great answer (I was unaware of vw/vh/etc) and is perfect for something like a lightbox, but sadly it still falls short of The Dream. Instead of vh and vw, this needs something like "pw" and "ph" for "parent width" and "parent height". Your solution is awesome but only works if you want to scale your element relative to the entire viewport. There are no pw and ph in CSS. :/Habitforming
@Habitforming I think that vw/vh can be usefull according to the usecase. They require to think and build layouts diferently. Just like designing with px or percentages you need to have though about it before and all along the designing process. I agree with you for the "pw/ph" though, they would be easier to use especialy when you want to adapt them to existing websites.Ectophyte
N
0

I don't think that is possible to do so now with pure CSS. Maybe in future when we will have the full support of CSS variables and calculations. Now you can use a transparent image to specify the aspect ratio or using scripts. Also maybe something like LESS can be useful.

Nucleotide answered 28/7, 2012 at 6:42 Comment(2)
LESS wouldn't help. LESS is just a CSS preprocessor. That is, the end result of a LESS file is a CSS file. If you can't do it with css, you can't do it with LESS.Melitta
You are not right. With LESS you can calculate the height based on the width of the element so you will have the right aspect ratio.Nucleotide

© 2022 - 2024 — McMap. All rights reserved.