0

OK here's a challenging one! I really want to see if this can be accomplished with CSS only if possible.

I have a unique layout that requires images to be sized and positioned based on their parent container. If the image exceeds it's parent in height or width I need it to reduce size to fit. At the moment I'm using max-width and max-height together and it's working fine. The image resizes to fit and of course keeps it's aspect ratio.

Now here's the tricky part. I need to add a special shadow to this image that cannot be accomplished with CSS box shadows. The shadow uses PNG image. The shadow needs to be sized and positioned in relation to the image - meaning it falls at the bottom of the image and it equals the width of the image.

Normally I would achieve the shadow with ::after and size and position it relative to it's parent element, which works perfectly Except it's parent is the image and images do not allow ::before or ::after.

So as far as I can tell, the only way to achieve this is to wrap the image in another container so I can use that container as the parent elements and positioning reference for the shadow layer. But I cannot find a way to make that container div behave in the same way as the image in terms of the max-width and max-height sizing while still maintaining it's aspect ratio.

The best methods for maintaining aspect ratios use padding top, which works brilliantly when the width is the only important factor. But the padding-top technique doesn't allow for the container to have a max-height.

So I'm looking for a CSS technique that will allow a block element to maintain its aspect ratio, and have max-width and max-height at the same time. Similar to how an image would behave in this situation.

I've scoured the internets for a solution and haven't seen anyone describe this exact situation. Would be extremely grateful to anyone who can assist.

Added 1 Sept 2017:

I should mention that it's more than just the shadow I need to position relative to the image. There are some other elements as well that need to be positioned in this way, and those other elements are not simple background images. So while Lightbender's solution is great for the shadow, it doesn't solve the bigger issue at hand. I need a container around the image that I can use as reference to position other child elements.

Benek Lisefski
  • 159
  • 1
  • 3
  • 13

2 Answers2

1

While before and after won't work (easily) but you can still use padding and a background image and it will work exactly the way your current setup works.

img.fancyshadow {
    height: auto;
    width: auto;
    max-width: 100%;
    max-height: 100%;
    padding: 0 10px 10px 0; /* adjust as needed */
    background: url('path/to/your/shadow');
    box-sizing: border-box;
}

I don't have a Mac handy, so I've only tested this in Firefox, Chrome, and IE, can anyone confirm Safari as well?

LightBender
  • 4,046
  • 1
  • 15
  • 31
  • Simple solution which I hadn't thought of yet. I will give this a try as soon as I'm able to and confirm if it works in my case. – Benek Lisefski Aug 30 '17 at 22:59
  • This looks like it will be a good solution for the shadow. Although I'm realising now that I need this solution for more than just the shadow. On some pages, there are other elements that need to be positioned relative to the image (e.g. absolutely positioned as if the image was the relative parent element). So in order to get those to work, I really do need a solution that wraps a container around that image so I can use the container for positioning of these other elements too. So I applaud this solution for its simplicity for the shadow, but unfortunately it doesn't solve the whole problem. – Benek Lisefski Aug 31 '17 at 20:49
  • I don't think you'll be able to do this in pure css in the way you're imagining because max-height will not affect the height of a containing image. Instead the image will respect the width and overflow. I've never tried this, but it might provide you with a viable approach. https://stackoverflow.com/a/10804311/8533154 I'm sorry my solution didn't solve your entire problem, best of luck :) – LightBender Aug 31 '17 at 21:22
  • I've decided to accept this as best answer. I does solve the shadow problem in a simple elegant way. And I will find a way to deal with the other elements that need positioning using a combination of this for shadow and maybe javascript to position the others. Thanks for the answer. – Benek Lisefski Sep 07 '17 at 03:57
0

So I would like to see a simple example of what you are attempting as a starting point but you mentioned that the images need to be sized/positioned based upon the size of their container.

Here is an starting example of something like that. Not sure if it can be modified to suit your issue. Let me know and I can tweak.

When needing to have responsive images, I never use IMG tags. Setting the background image in CSS provides much more control on responsive sites/apps.

Documentation on background-size:

cover Scale the background image to be as large as possible so that the background area is completely covered by the background image. Some parts of the background image may not be in view within the background positioning area

contain Scale the image to the largest size such that both its width and its height can fit inside the content area

$(function() {
  $('.banner').resizable();
});
.banner {
  background-image: url('https://s-media-cache-ak0.pinimg.com/originals/15/ae/a6/15aea601612443d5bddd0df945af6ffd.jpg');
  background-size: cover; 
  background-position: center;
  height: 175px;
  width: 100%;
}

p {
  color: #666;
}

.ui-resizable-se {
  box-shadow: -1px -3px 10px 3px white;
}
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>

<h1>Resize the image using the black triangle at bottom right of image</h1>
<p>Note how the image fills the container and the position is always centered (you can control where the position is, doesn't have to be in the center)</p>

<div class="banner">
</div>
flyer
  • 1,414
  • 12
  • 13
  • Thanks for the reply but I'm trying for a CSS-only solution here. Will use Javascript only as a very last resort. – Benek Lisefski Aug 30 '17 at 22:56
  • Oh I only used the javascript here to demonstrate the container getting big and small. The thing I'm trying to highlight is the use of background-image and background-position and background-size in the CSS. You get far more control with images in this way than you ever could with an IMG tag. – flyer Aug 31 '17 at 01:56
  • I've updated the demo to have a resize handle - again this is only to demonstrate the responsive nature of images when you set them via CSS. – flyer Aug 31 '17 at 02:11