Maximum possible size image and div extension to fill in a space

I am sure this has been asked before, but I cannot find the answer to a specific question.

I need a very simple layout:

------------------- header ------------------- | content | graphic | ------------------- 

Where:

  • The height of the header is determined by the font size;
  • Content has a fixed minimum width;
  • Graphics are the maximum possible, given these two limitations and maintaining the aspect ratio (that is, it will be as high as the screen minus the title, unless it makes the content panel too narrow);
  • The content will be as broad as possible, given these three limitations.

[edited to add:]

  • Vertical: the image is centered vertically when the width and aspect ratio constraints make it shorter than the maximum height
  • Horizontal: the image is always hard against the right side of the screen (except for any manually added add-ons), and the content always goes directly to the left side of the image (except for manually added add-ons).

I tried using flexboxes and satisfied the first three restrictions, but I cannot force the content panel to grow horizontally to fill the space not used by the image. The best results I got use HTML and CSS below, but as you can see in the screenshot below, this leads to the fact that the contents of the div and the image are the same size, and not the content of the div pushing the image to the right, (This is the expected behavior from setting flex = 1 for both, so I did not expect it to work, but at least it gives me the image size that I like).

Screenshot

What I'm using is in https://jsfiddle.net/uv566jc3/ :

 .grid { border: solid 1px #e7e7e7; height: 95vh; display: flex; flex-direction: column; } .header { flex: 0; } .grid__row { flex: 1; display: flex; flex-direction: row; } .grid__item { flex: 1; padding: 12px; border: solid 1px #e7e7e7; } img { flex: 1; object-fit: contain; overflow: hidden; border: solid 1px #e7e7e7; } 
 <div class="grid"> <div class="header">Some header stuff </div> <div class="grid__row"> <div class="grid__item">1</div> <img id="pic" src="https://s27.postimg.org/oc7sozu7n/clouds.png"> </div> </div> 
  • flexbox grid style in the column direction containing the header and grid__row; Headline
  • has flex 0, that is, the height is set by the content;
  • grid__row has flex 1, that is, it fills the height remaining after the header; is also a flexible container in the direction of the row, containing grid__item and img.
  • grid__item has flex 1, that is, it fills the available width;
  • img has flex 1 and uses object-fit = 1 (which gets the necessary properties to determine the image size) and overflow = hidden (which I really don’t understand what it does, but if I leave it, the img container will expand horizontally by 2 times) .

I did not set min-width explicitly in the grid__item element in jsfiddle, but I do not expect this to matter.

Is there an easy way to get what I want in CSS? Sorry if this is a duplicate.

+7
html css flexbox css3
source share
9 answers

I edited the code, is your solution what you want? I'm not sure.

https://jsfiddle.net/vjLps7qs/6/

This will:

  .container { width: calc(100vw); height: 100vh; overflow: hidden; } .top { height: 1.25em; padding: 3px; background: yellow; display: flex; flex-direction: row; } .innerCtr { height: 100%; overflow: hidden; } .left { height: 100%; background: red; overflow: hidden; } .right { max-height: 100%; max-width: 80%; calc(100% - 1.25rem); background: blue; float: right; object-fit: contain; overflow: hidden; position: relative; top: calc(50% - 1.25rem); transform: translateY(-52%) scale(0.95); } 

added calc, which is supported by all major browsers

  .right { calc(100% - 1.25rem); top: calc(50% - 1.25rem); } 

Again, I am very sorry if this is not what you were looking for, but this stream is difficult to navigate.

+2
source share

Flex factor flex: 1

In the grid__row flex container, which is in the line, two flex elements - grid__item and img - each of them has flex: 1 .

This means that both elements will evenly distribute the available space in the container among themselves. In other words, 50/50, as in the illustration.

My suggestion: remove flex: 1 from img .


Space resulting from object-fit: contain

With object-fit: contain aspect ratio of the image is saved and scaled to object-fit: contain in the field.

As a result, there may be spaces on the left and / or right (portrait fit), or upper and / or lower (landscape is suitable).

This may be the reason that you see a β€œfill” space to the left and right of the image.

If you try cover , all of the space will be used, but there it is cropped ( demo ).

Learn more about object-fit : fooobar.com/questions/94033 /.


overflow: hidden effect overflow: hidden

Regarding your side comment:

... overflow = hidden (which I really don’t understand what it is doing, but if I leave this, the img container will expand horizontally factor 2).

This is probably due to the minimal algorithm for calibrating the flexibility elements.

By default, the flexibility item cannot be smaller than the size of its contents.

However, this function can be overridden with overflow: hidden .

Read more here: Why doesn't a flex item reduce the size of the content?

+1
source share

This example uses the concept of float:

Portrait Image:

 * { box-sizing: border-box; } body { margin: 0px; } .header { width: 100%; height:8vh; border: 1px solid #aaa; } .main-content { width: 100%; border: 1px solid #aaa; padding: 0px; } .main-content > .left { float: left; width: 50%; } .main-content > .right { float: right; width: 50%; } .main-content > div { min-height: 50%; max-height: 90%; } .main-content > .right > img { max-width: 100%; max-height: 90vh; } .main-content:after, .main-content:before { display: table; clear: both; content: ""; } 
 <div class="header"> Some Header stuff.. <br> </div> <div class="main-content"> <div class="left"> Somehitng on the left </div> <div class="right"> <img src="https://s-media-cache-ak0.pinimg.com/236x/41/89/8c/41898cae6d9edd8737dfef07ab50ea57.jpg" /> </div> </div> 

Landscape image:

 * { box-sizing: border-box; } body { margin: 0px; } .header { width: 100%; height: 8vh; border: 1px solid #aaa; } .main-content { width: 100%; border: 1px solid #aaa; padding: 0px; } .main-content > .left { float: left; width: 50%; } .main-content > .right { float: right; width: 50%; } .main-content > div { min-height: 50%; max-height: 90%; } .main-content > .right > img { max-width: 100%; max-height: 90vh; } .main-content:after, .main-content:before { display: table; clear: both; content: ""; } 
 <div class="header"> Some Header stuff.. <br> </div> <div class="main-content"> <div class="left"> Somehitng on the left </div> <div class="right"> <img src="http://www.w3schools.com/css/img_fjords.jpg" /> </div> </div> 
+1
source share

You have to remove flex from your image and wrap it inside the container according to your requirements.

I modified the code a bit to achieve the same. Check for changes.

UPDATE

I updated my answer and used display: inline-flex now. Must meet all your requirements.

 .grid { border: solid 1px #e7e7e7; height: 95vh; display: flex; flex-direction: column; } .header { flex: 0; } .grid__row { flex: 1; display: flex; flex-direction: row; } .grid__item { flex: 1; padding: 12px; border: solid 1px #e7e7e7; } .img_ctr { border: solid 1px #e7e7e7; display: inline-flex; } img { height: 100%; } 
 <div class="grid"> <div class="header">Some header stuff </div> <div class="grid__row"> <div class="grid__item">1</div> <div class="img_ctr"> <img id="pic" src="https://s-media-cache-ak0.pinimg.com/236x/41/89/8c/41898cae6d9edd8737dfef07ab50ea57.jpg"> </div> </div> </div> 
0
source share

Perhaps this is the solution to your problem? See the violin here

 #pic { background: url('http://lorempixel.com/400/200/sports/1/') no-repeat; position: absolute; left: 440px; right: 0; top: 0; bottom: 0; } 

I placed the image as a background image with the cover property. Thus, the image accepts the entire width and height of the container, regardless of how you change it.

0
source share

I used max-width and max-height to apply restrictions to the image, but keeping aspect ratio. I also included the image in an independent div to allow compression and enlargement of the two divided sections.

Maybe this is what you are looking for? https://jsfiddle.net/johnnykb/pu1vpL3q/2/

Both extremely tall and extremely wide images scale perfectly to fit the image container, which in turn is compressed if the image is small enough, but it never grows larger than the minimum section width allowed.

HTML:

 <div class="grid"> <div class="header">Some header stuff </div> <div class="grid__row"> <div class="content">1</div> <div class="image"> <img id="pic" src="http://placekitten.com/200/2000"> </div> </div> </div> 

CSS

 .grid { border: solid 1px #e7e7e7; height:95vh; display: flex; flex-direction: column; } .header { flex: 0; } .grid__row { flex: 1; display: flex; flex-direction:row; } .content { flex-grow: 1; padding: 12px; border: solid 1px #e7e7e7; min-width: 400px; } .image { flex-shrink: 1; padding: 12px; border: solid 1px #e7e7e7; text-align: center; } img { overflow: hidden; border: solid 1px #e7e7e7; max-height: 100%; max-width: 100%; } 
0
source share

NOTE. This is the best answer I have found so far, but generosity is still open - see below.

I found the answer using float. See https://jsfiddle.net/wwhyte/vjLps7qs/ ; replace the image http://placekitten.com/1600/900 to see the behavior of the landscape.

CSS

  .container { width: calc(100vw); height: 100vh; overflow: hidden; } .top { height: 1.25em; background: yellow; } .innerCtr { height: 100%; overflow: hidden; } .left { height: 100%; background: red; overflow: hidden; } .right { max-height: 100%; max-width: 80%; background: blue; float: right; object-fit: contain; overflow: hidden; position: relative; top: 50%; transform: translateY(-52%) scale(0.95); } 

HTML:

 <div class="container"> <div class="top"> </div> <div class="innerCtr"> <img class="right" src="http://placekitten.com/1600/900"> <div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div> </div> </div> 

I think this is happening:

  • In the correct class:
    • max-height, max-width and object-fit give me the necessary scaling.
    • float: right gives me the position I need. (I got this from an article I found yesterday, but now lost, I will edit this answer to provide attribution if I find it again).
    • the conversion is inspired by the vertical alignment article at: http://zerosixthree.se/vertical-align-anything-with-just-3-lines-of-css/ .
    • 95% scale improves image visibility.
  • In left class height: 100% gives the size of the panel I want
  • The inner class Ctr gives the parent object to calculate its height against
  • The container class is suitable for the viewport in the browser window.

Even this is not quite perfect. There is some strange interaction between the height of the upper bar and the height of the image, so that the image is pushed from the bottom of the display. The outstanding amount is less, but related to the height of the upper bar - I have not fully explored. If you remove the top bar, the CSS above will behave fine. I turned to this with a 95 percent scale and a slight adjustment for Y-conversion, but it still does not behave exactly to the small size of the window - the image is not perfectly vertically centered. I thought setting height = calc (100vh-1.25em) in the container class could fix this, but it actually violates the vertical scaling of the image, so now it only scales horizontally. It was a completely unexpected behavior! Thus, generosity remains open if someone can get vertical centering in order to work accurately.

Thanks to everyone for all the suggestions!

0
source share

Answers about removing flex from the image are on the right track, flex is for containers that don't contain content. Here is a working example.

 .grid { border: solid 1px #e7e7e7; height:95vh; display: flex; flex-direction: column; } .header { flex: 0; } .grid__row { flex: 1; display: flex; flex-direction:row; } .grid__item { white-space:nowrap; padding: 12px; border: solid 1px #e7e7e7; } img { object-fit:contain; border: solid 1px #e7e7e7; max-width:75%; } 

Fiddle

0
source share

I set some details in your answer, now I believe that it works fine.

There are two versions of the demonstration, one for the landscape image and the other for the portrait.

I set the animation on hover over the image to show that it scales correctly, keeping it in the center

 body { margin: 0px; } .container { width: calc(100vw); height: 50vh; } .top { height: 1.25em; background: yellow; } .innerCtr { height: calc(100% - 1.25em); /* important to have the heuight ok */ position: relative; /* make the dimension inheritable */ } .left { height: 100%; background: red; overflow: hidden; } .right { max-height: 100%; max-width: 80%; background: blue; float: right; object-fit: contain; top: 50%; position: relative; transform: translateY(-50%) scale(0.95) ; } .right:hover { animation: zoom 4s infinite; } @keyframes zoom { from {transform: translateY(-50%) scale(0.98) } to {transform: translateY(-50%) scale(0) } } 
 <div class="container"> <div class="top"> </div> <div class="innerCtr"> <img class="right" src="http://placekitten.com/1600/900"> <div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div> </div> </div> <div class="container"> <div class="top"> </div> <div class="innerCtr"> <img class="right" src="http://placekitten.com/900/1600"> <div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</div> </div> </div> 
0
source share

All Articles