Scale image in flexbox to available width OR height

℡╲_俬逩灬. 提交于 2020-01-06 20:03:44

问题


I want an image on a webpage to grow/shrink to the available height or width of a flexbox and keep the original aspect ratio.

I have used max-height:100%; max-width:100% on the image but that doesn't work.

The page always fills the browser window without overflow. It has 3 rows:

  1. a title at the top with fixed height
  2. an article, with image and description side by side
  3. a footer at the bottom with fixed height

The image should grow/shrink with the available height or width, depending on the aspect ratio of the image and surrounding box.

This means most of the times empty space is present left or under the image.

This is a example page:

<html><head>
<title>Title</title>
<style type="text/css">
*    {font-size:100%; font:inherit; padding:0; border:0; margin:0}
body {background:#FFC; color:#333; font-family:sans-serif}

body                {display:flex; flex-direction:column; height:100%}
h1                  {text-align:right; margin-right:20em; background:#CAA}

article             {flex:1; display:flex}
article figure      {flex:1}
article figure img  {display:block; max-width:100%; max-height:100%}

#description        {width:20em; background:#ACA}
footer              {background:#AAC}
</style>
</head><body>
  <h1>Title</h1>

  <article>
    <figure> <img src="https://placekitten.com/987/765" /> </figure>
    <div id="description">
      <p>The description.</p>
    </div>
  </article>

  <footer> Footer </footer>
</body></html>

I made a JSFiddle, but it does not place the footer fixed at the bottom as it does when viewed in a separate browser window.

It would be nice to use flexbox as it's promoted for it's easy layout. But if this cannot be done with it I'll use absolute positioning.


回答1:


i believe you missed to make height:100% be inherited from viewport ,

for the rest, it is just a matter of flexbox inbrication , flex values overflow and max-size to be reset:( demo to play with )

html,/* viewport values for height/width % */
body {
  height: 100%;
  margin: 0;
}
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
body {
  display: flex;
  flex-flow: column;
}
article {
  display: flex;/* also a flex child */
  flex: 1;
  overflow: hidden;/* we'll squeeze children inside */
}
#description {
  width: 20em;
}
figure {
  flex: 1;
  display: flex;/* again also a flex child */
  overflow: hidden;/* we'll squeeze children inside */
}
img {
  margin: auto;/* will shrink to fit inside and sit in middle */
  max-height: 100%;
  max-width: 100%;
}
h1 {
  margin: 0;
  background: #CAA
}
#description {
  background: #ACA
}
footer {
  background: #AAC
}
<h1>Title</h1>

<article>
  <figure>
    <img src="https://placekitten.com/987/765" />
  </figure>
  <div id="description">
    <p>The description.</p>
  </div>
</article>

<footer>Footer</footer>

note: here image won't grow more than its original size, it will only scale down . min-height + max-height 100% is height 100%, idem for width.

until object-fit comes avalaible everywhere the fallback background-size will be an alternative but loosing image from content.


So the tricky way via CSS only and still keeping image into the content is :

  • to set the image as a background to figure and use contain for background-size,
  • to reduce width to image itself down to zero to only see it painted in the background.(this is to keep it part of the content and keep the alt attribute efficient for screen readers and search engines )

http://caniuse.com/#search=background-size (for older IE, check polyfills but flex is involved so i guess you did not mind those so much )

html,/* viewport values for height/width % */
body {
  height: 100%;
  margin: 0;
}
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
body {
  display: flex;
  flex-flow: column;
}
article {
  display: flex;/* also a flex child */
  flex: 1;
  overflow: hidden;/* we'll squeeze children inside */
}
#description {
  width: 20em;
}
figure {
  flex: 1;
  display: flex;/* again also a flex child */
  overflow: hidden;/* we'll squeeze children inside */
  background:url(https://placekitten.com/987/765) center no-repeat;
  background-size:contain;
}
img {/* hide it and show as a background */
  height:0;
}
h1 {
  margin: 0;
  background: #CAA
}
#description {
  background: #ACA;
  display:flex;
}
p {
  margin:auto 1em;
  }
br:last-of-type {margin-bottom:1em;line-height:2em;}
footer {
  background: #AAC
}
<h1>Title</h1>

<article>
  <figure>
    <img src="https://plcekitten.com/987/765" alt="kitty to pet" /><!-- broken link to show the alt attribute and  that image is still part of content -->
  </figure>
  <div id="description">
    <p>Hide image and place it into figure's background,<br/> So it scales without any distorsion.<br/>Link to image broken on purpose to show that alt is here to be the content </p>
  </div>
</article>

<footer>Footer</footer>

DEMO to play with




回答2:


You not defined the width of "dad element"

<html><head>
<title>Title</title>
<style type="text/css">
*    {font-size:100%; font:inherit; padding:0; border:0; margin:0}
body {background:#FFC; color:#333; font-family:sans-serif}

body                {display:flex; flex-direction:column; height:100%}
h1                  {text-align:right; margin-right:20em; background:#CAA}

article             {flex:1; display:flex; width: 100%;}

article .image {width: 100%;}
article .image img{ width: 100%; }

#description        {width:20em;display:flex; background:#ACA}
footer              {background:#AAC}
</style>
</head><body>
  <h1>Title</h1>

  <article>
     <div class="image">
       <img src="https://placekitten.com/987/765" alt="" />
     </div>
     <div id="description">
       <p>The description.</p>
     </div>
  </article>

  <footer> Footer </footer>
</body></html>


来源:https://stackoverflow.com/questions/37624201/scale-image-in-flexbox-to-available-width-or-height

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!