CSS resize of image in fluid lightbox container
Asked Answered
T

5

7

Short version: Make the image fit nicely the visible area for small windows, starting from this fiddle

Update: There doesn't seem to be a solution for this issue. I thought there might be one because Chrome actually makes it possible (see my answer) but behavior is different in other browsers.

Longer version:

I'm working on a lightweight fluid lightbox and have an apparently simple CSS issue I can't resolve.

I want the content (a single image) to be downsized if needed to fit, while keeping the aspect ratio the same.

Here's a demo fiddle: http://jsfiddle.net/3a9y9/2/ . Resize the window so the image doesn't fit height wise.

It almost works, but the height given to the image is slightly more than what's actually visible so a bit of the bottom gets clipped. I've tried tweaking things to no avail; I wish I understood how come the available height is too high.

Maybe it's related, but IE 9 doesn't even maintain the aspect ratio with this attempt of a solution. Also, Chrome behaves strangely when resizing the window and clicking on run in the fiddle will sometimes redraw differently.

What's the solution?

It's no problem to wrap the <img> in a <div> or two if it's necessary, but the top-level structure should ideally remain the same (i.e. a .featherlight-content inside a .featherlight and that's it).

Tavie answered 7/4, 2014 at 18:56 Comment(3)
Have you noticed that Firefox (latest Win version) does not show the image at all? And beside this, I don't think that there is a pure CSS solution for this, as you have to determine if the width or the height of the image sets the maximum value depending on the viewport size. And this you cannot achieve/ solve with CSS. Therefor you need Javascript. So before writing an answer, please let us know, if a JS driven solution is also of any interest for you - thanks!Undershrub
@Netsurfer: I'm looking for a CSS solution, no JS.Louise
OK, but then, as written before, you cannot achieve your goal. It's not possible solely with CSS.Undershrub
D
4

In featherlight.min.css, change .featherlight-image{width: 100%} to .featherlight-image{max-width: 100%}

and at the end, write the following css:

@media only screen and (min-height:1000px) {
    .featherlight-image { height: 900px; }
}
@media only screen and (min-height:700px) {
    .featherlight-image { height: 600px; }
}
@media only screen and (max-height:700px) {
    .featherlight-image { height: 400px; }
}

What it's doing is changing the width of the lightbox from fixed 100% into a maximum of 100% (so that it's adjusted as per height). And then with @media, the height of the image is restricted. @media will allow for responsiveness based on browser height.

Higher resolution browsers will show the image at 900px height; those with a minimum of 700px height will show it at 600px, and smaller ones will show it at 400px.

You can of course adjust the numbers as per your preference; but this solution worked and solves the problem of long images.

Here's a jsfiddle. Note that using data-featherlight="image" is important for this to work properly.

Hope it helps.

Detachment answered 19/12, 2014 at 6:58 Comment(0)
F
3

In my opinion, the easiest way to both fit an image in the container and to center it is absolute positioning with margin: auto:

.featherlight img {    
    max-width:90%;
    max-height:90%;
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    margin: auto;
}

(Fiddle)

Alternatively, you can try to set the size of the image in viewport relative units (vw/vh), they have quite good browser support now: http://caniuse.com/#search=vw

Floats answered 10/4, 2014 at 22:21 Comment(2)
This way you won't be able to position any other elements (like controls) relative to the image. I think the OP needs a solution that fits the image to it's container (.featherlight-content).Nakasuji
This is probably as good as it gets. I think there is not (yet) a perfect answer to that problem. I've resorted to using Javascript. ThanksLouise
T
0

Note: The following appears to be true only for Chrome, but it doesn't work in Firefox or IE...

After much twiddling around, my conclusion is that there's a fundamental difference in the way that height and width are treated in general and that it affects calculations here.

It's bound to be related to the flow of things, like how reducing the width of a <div> will have the content flow down, expanding the height, but how reducing the height of a <div> won't make it wider.

The clipping here is due to the fact that the border-bottom and padding-top are not taken into account in the available height. The solution is thus to remove those altogether.

If one still wants a border, then it can be faked by adding an absolutely positioned <div>. Here's the corresponding fiddle.

Tavie answered 10/4, 2014 at 17:39 Comment(1)
Yes, it does not work correctly in Firefox. So this is still no "solution" to me. You could easily achieve almost the same effect if you use the image as a background-image and set the background-size: contain with background-position: center. BTW: Why not using a JS solution? It's simple and cross-browser. And the background method as fallback ...! But it's of course up to you.Undershrub
N
0

You can try the following approach. Elements that have a set width become wider when they have padding and/or border-width. To avoid these problems, make use of the now common box-sizing: border-box; reset.

*,
*:before,
*:after {
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

An element can be centered by setting height: 100%; to a "ghost" element (it can be a pseudo element) inside the parent and vertical-align: middle; to both.

.featherlight {
    background-color: rgba(0, 0, 0, 0.8);
    bottom: 0;
    font-size: 0;
    left: 0;
    overflow: auto;
    padding: 0 5%;
    position: absolute;
    right: 0;
    text-align: center;
    top: 0;
}

.featherlight:before {
    content: '';
    display: inline-block;
    height: 100%; 
    vertical-align: middle;
}

.featherlight-content {
    display: inline-block;
    margin: 5% 0;
    max-width: 100%;
    vertical-align: middle;
}

Images can be made responsive-friendly by applying max-width: 100%; and height: auto; to the image so that it scales nicely to the parent element.

.featherlight-content img {
    border: 25px solid #fff;
    display: block;
    height: auto;
    max-width: 100%;
}

See live example here: http://jsfiddle.net/cdog/AXzz8/.

Nakasuji answered 10/4, 2014 at 19:14 Comment(2)
Your live example doesn't even resize the image at all if it doesn't fit height-wise. Not giving a -1 because of lorempixel.com which I didn't know about.Louise
As far as I know, you can't do it for both width and height with CSS only yet. There's a CSS3 webstandard for it, defining a property called object-fit (w3.org/TR/css3-images/#the-object-fit) which aims to solve exactly these sorts of problems. Unfortunately browser support is as following: caniuse.com/#feat=object-fit.Nakasuji
H
0
  • It gets cut off because the padding is throwing it off.
  • It doesn't work in IE or Firefox because they don't assume that the height of content div should stretch to fit its container's height. You would have to use height: 100% or some other percentage. This causes more problems when trying to achieve a max-height.
  • It doesn't enlarge the image when the size gets larger in height because that is the way most browsers handle re-rendering the page (or not re-rendering in this case) when the size of the viewport changes in height. You will have to force a re-rendering of the page. The only CSS way I know how to do that is with a CSS3 animation.

Here is a solution that does not work in Firefox or IE (so... not that great of a solution), but it fixes the cutting-off and resizing issues.

http://jsfiddle.net/SombreErmine/ENrnu/5/

It utilizes calc() and CSS3 animations; so it's definitely limited in practical use. I'm not posting this as the solution. I'm mostly posting it to share some information on what I've learned. Hopefully, this will help lead to a real solution.

HTML Code:

<div class="featherlight" style="display: block;">
    <div class="featherlight-content">
        <img src="http://placekitten.com/640/480" alt="" class="featherlight-image featherlight-inner"/>
    </div>
</div>

CSS Code:

.featherlight {
    position:fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    text-align: center;
    background: rgba(0, 0, 0, 0.8);
}
.featherlight:before {
    /* position: trick to center content vertically */
    content:'';
    display: inline-block;
    height: 100%;
    vertical-align: middle;
    margin-right: -0.25em;
}

.featherlight .featherlight-content {
    padding: 25px;
    position: relative;
    text-align: center;
    vertical-align: middle;
    display: inline-block;
    min-width: 30%;
    margin-left: 5%;
    margin-right: 5%;
    max-height: 95%;
    background: #fff;
}

.featherlight .featherlight-image {
    max-width:100%;
    max-height:calc(100% - 50px);
    vertical-align: bottom;

    -webkit-animation: render_update 1s linear 0s infinite;
       -moz-animation: render_update 1s linear 0s infinite;
         -o-animation: render_update 1s linear 0s infinite;
            animation: render_update 1s linear 0s infinite;
}

@-webkit-keyframes render_update {  from { padding-bottom: 0.001px; } to { padding-bottom: 0px; }  }
   @-moz-keyframes render_update {  from { padding-bottom: 0.001px; } to { padding-bottom: 0px; }  }
     @-o-keyframes render_update {  from { padding-bottom: 0.001px; } to { padding-bottom: 0px; }  }
        @keyframes render_update {  from { padding-bottom: 0.001px; } to { padding-bottom: 0px; }  }
Higgledypiggledy answered 11/4, 2014 at 5:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.