Shrink menu to photo width

Thanks to a bunch of help from @coothead, when a user is in my photo gallery and clicks on a thumbnail, a modal window appears with an enlarged image.

In Lightroom I sized my photos to have a “long-side” of 800px, but the actual dimensions of photos will vary depending on the original shot, orientation, and if I cropped.

I would like to have a thin menu that sits on the top of the photo, and the menu needs to be the exact width of whatever photo is being viewed at the moment.

Then in that menu, I want “Download” to be in the far left-hand corner and “Close” to be in the far right-hand corner of the menu.

To do that second part, it seems like a Flexbox might be the way to go. But who knows.

More importantly, I can’t figure out how to make my menu width always mimic the width of a given photo.

Suggestions on how to solve this problem?

Here is a mockup of what I am looking for…

The only way I would know how to do this is maybe using an HTML table, but that seems outdated and maybe not very responsive?

Fwiw, I am trying to create the above solution, because currently I have this…


…and if a photo is taller than the screen I’m afraid the user may not scroll down and thus not know how to close the modal window.

Your mock up picture has them both on the right side, which is it?

What you need is a shrink wrapping container, display:table will do that. No need for html tables.

You’ll need to add a div in the li and apply display table to it. Then that div will display on :target and the links will align to the edge of the image regardless of the image size. The display table div will shrink to fit any image.

        <li id="l1">
          <div>
            <a class="downloadRaw" href="/WORKSPACE/sp_modal-window-test_coot_v3/images/2000x2000.jpg" download="/WORKSPACE/sp_modal-window-test_coot_v3/images/2000x2000.jpg">Download</a>
            <a class="closeWindow" href="#containerMast">Close</a>
            <img src="images/800x800.jpg" width="800" height="800" alt="">
          </div>
          <!-- Gallery Image (medium) -->
          <a href="#l1">
            <img src="images/800x800.jpg" width="180" height="180" alt="">
          </a>
        </li>

The attachment below has links aligned on the right like your image shows them.

modal.zip (583.9 KB)

2 Likes

@Ray.H,

Thanks for the response!

I am quickly trying to understand what you did while you are still here…

Sorry, I changed my mind and didn’t update my OP.

Like the mockup, I think it looks better having both choices next to each other and right aligned.

What is the downside of using an HTML table?

I don’t follow how what you did works…

How can you “shrink-wrap” the photo menu to the photo when your DIV does not include the photo itself?

To clarify, I want the menu’s width to always match the photo’s width, understanding that the photo’s width will vary from photo to photo.

I’m pouring over your code now…

Btw, I think you left an < img > in the 1st < div > by accident?

You just answered your own question. :slightly_smiling_face:
It wasn’t a mistake, the img in the div determines the div’s width.
The 800px wide img is in the div.

And I assume your thumbnails will actually be resized to 180px in your final page and not sized down to 180px by the attributes.

The div has text-align: right on it to align the inline-block links to the right.

.flexGallery li div{
  display: none;
  text-align: right;
}

They stay on the right edge of the image regardless of the image’s size. That is the purpose of using a shrink to fit div (display:table)

.flexGallery li:target div{
  display:table; /*shrinkwrap for anchors to right align at top*/
  margin: 1em auto 0;
}

@Ray.H,

This seemingly simple request is actually pretty complex - at least for someone like me that has been away from web development for several years.

Bare with me as I try to process all of this!

So we are loading the _medium photo TWICE?! :eek:

While designing this website, I have tried very hard to be mindful of mobile users and also some users who might have limited bandwidth.

Because of this, I store the original _raw.jpg (i.e. 5-6MB) photos in a given gallery, and then in that gallery I have a “_thumbnails” directory where I have a _small.jpg (i.e. 100-150KB) and then a “_photos” directory where I store _medium.jog (i.e. 300-400KB) photos for the “detailed” view which is now this modal view.

The only time a user’s browser should download the _raw.jpg is by clicking on the “Download” link.

I hope we aren’t loading the _medium.jpg twice…

I thought the approach to take was to create a “shrink-wrap container” by creating a table and then having the _medium.jpg be in one cell, and then the text/menu would be in another cell, and the text/menu would adapt to the width of the photo. (Of course just having “Download | Close” would never be wider than the image!)

Can you help me understand this better, and are we sure this is the least bandwith intensive way to do things?

As mentioned above, I have _thumbnails (100-150KB)(200px wide) phtos for the gallery, and then in the “detailed” (modal) view, I have _medium (300-400KB)(800px long side) photos.

Hmm… How does text-align align DIVs? I figured you would need to use table cells to do that or maybe even Floats?

P.S. Do you know where in MDN I can read up more on CSS tables and Display:Table? When I Googled and searched in MDN all I saw where specs and now How-To’s…

No, once it’s loaded it’s in the browser’s cache. No matter how many times an image appears in the html it only has to load once.

The anchors are inline-blocks thus they behave like inline elements. Inline-blocks also take on vertical margins like blocks (Though I didn’t use margins on them). They can also take dimensions like blocks.

That’s good to know, but I’m still struggling to understand why we need an image nested inside an anchor twice.

On a side note, how does this work…

<a class="closeWindow" href="#containerMast">Close</a>

By the way, there is no ID called #containerMast

When you load the gallery, does this code load the thumbnail…

<a href=#l1">
    <img src="images/800x800.jpg" width="180" height="180" alt="">
</a>

And when you click on the thumbnail, then this code…

<a href=#l1">

…makes this element the target…

<li id="l1">

Right?

Why can’t you do something like this…

<li id="l1">
    <div>
        <a class="downloadRaw" href="images/2000x2000.jpg" download="images/2000x2000.jpg">Download</a>
        <span>|</span>
        <a class="closeWindow" href="#containerMast">Close</a>
        <a href="l1">
            <img src="images/800x800.jpg" alt="" />
        </a>
    </div>
</li>

I realize that I have an issue toggling between the _thumbnail and _medium.

Am working on that…

The div is initially set to display:none; until :target changes it to display:table.
That’s also what hides your links until the large image is viewed

If you nested everything in the div you would loose your thumbnail since we need to hide the links and align them to the top right of a dynamic width image.

Sorry, it’s just what is required to do what you are wanting…

@Ray.H,

Attached is a refactored version of the code you shared.

It cleans things up a bit, and addresses an issue with me not using a thumbnail-sized photo for the gallery.

Based on initial testing it works.

Thoughts?

sp_shrink-wrap-container_rayh_v2.zip (601.4 KB)

Yes, it’s basically the same html structure that I was using. You relocated the thumbnail above the div. But it still keeps all the modal content nested in the div which is what I had said there would be no getting around.

I see you’ve added a span for the pipe divider. That could be a pseudo :before or :after on one of the menu links. But it would keep the cursor on the pipe and you might not like that. Could be cured with cursor:none; on the pseudo pipe.

Which brings up another subject, as it is right now the medium images are not preloaded due to display:none on the div. That may be what you want, I’m not sure. I think you want the user to be able to view the modal image at their discretion, in that case they shouldn’t have to download it until requested.

On the other hand the medium image could be preloaded one of two ways.

  1. Hide the div above the fold with absolute positioning instead of display:none

  2. Go ahead and let the medium image and thumbnail be the same image but just resize the thumbnail with the width/height attributes in the img tag.

If your modal images are all going to be around 800px then they can be optimized and the trade off between file sizes and image requests could very well balance out.

2 Likes

Thanks for the suggestion, but I’ll leave it as-is for now.

I’m sure this is a huge topic in itself, but for now, that was the behavior I expected - you only load the thumbnails and IF a user wants to view a given image, THEN you load that detailed image.

Thanks for all of the help on my photo menu, @Ray.H!! :+1: :+1: :+1:

2 Likes