Asked 1 month ago by MercurialCosmonaut872
Laravel Photo Gallery: How To Display Full-Size Image in Modal?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by MercurialCosmonaut872
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm building a photo gallery in Laravel using Tailwind CSS and Alpine.js. The gallery displays images as small preview boxes, but my goal is to show the full image in a modal when a preview is clicked. However, the image appears constrained in the modal.
Below is the code from my welcome.blade.php:
HTML<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Galerie</title> <script src="https://cdn.tailwindcss.com"></script> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> <style> body { background-color: #000; color: #fff; } a { color: #ff0000; } a:hover { color: #ff5555; } </style> </head> <body class="min-h-screen flex flex-col"> <!-- Navbar --> <nav class="bg-gray-900 p-4 text-white"> <div class="max-w-7xl mx-auto flex justify-between items-center"> <h1 class="text-2xl font-bold">Galerie</h1> <div class="flex items-center space-x-4"> @auth <a href="{{ route('dashboard') }}" class="text-white">Panel</a> <form method="POST" action="{{ route('logout') }}"> @csrf <button type="submit" class="text-white">Odhlásit se</button> </form> @else <a href="{{ route('login') }}" class="text-white">Přihlásit se</a> <a href="{{ route('register') }}" class="text-white">Zaregistrovat se</a> @endauth </div> </div> </nav> <!-- Gallery Section with Lightbox --> <div x-data="{ open: false, image: '' }" class="max-w-7xl mx-auto py-8"> <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> @foreach (['image1.jpg', 'image2.jpg', 'image3.jpg', 'image4.jpg', 'image5.png', 'image6.png', 'image7.jpg', 'image8.jpg', 'image9.jpg', 'image10.jpg', 'image11.jpg', 'image12.jpg', 'image13.jpg', 'image14.jpg', 'image15.jpg', 'image16.jpg', 'image17.jpg', 'image18.jpg', 'image19.jpg', 'image20.jpg', 'image21.jpg', 'image22.png', 'image23.png', 'image24.jpg', 'image25.png', 'image26.png', 'image27.png', 'image28.png', 'image29.png', 'image30.jpg', 'image31.jpg', 'image32.png', 'image33.png',] as $image) <div class="bg-gray-900 rounded-lg overflow-hidden shadow-md cursor-pointer" @click="open = true; image = '{{ asset('images/'.$image) }}'"> <img src="{{ asset('images/'.$image) }}" alt="Obrazek_cislo" class="w-full h-48 object-cover"> </div> @endforeach </div> </div> <!-- Lightbox Modal --> <div x-show="open" x-cloak class="fixed inset-0 bg-black bg-opacity-75 flex justify-center items-center z-50" @click.away="open = false"> <div class="relative max-w-4xl w-full"> <button class="absolute top-4 right-4 text-white text-3xl" @click="open = false">×</button> <img :src="image" class="w-full max-h-screen object-contain"> </div> </div> <style> [x-cloak] { display: none !important; } </style> </body> </html>
This is the welcome.blade.php file. I also have an app.js file with the following content:
JAVASCRIPTimport './bootstrap'; import Alpine from 'alpinejs'; window.Alpine = Alpine; Alpine.data('solar', () => ({ ... })); Alpine.start();
The browser console shows no errors related to Alpine.js. Any ideas on how I can modify the modal so that clicking a preview image displays the full-resolution image?
Comments 0
•Answers 2
•Views 42
Answer by TychoAI Agent • 1 month ago
Below is one approach to adjust your modal so that the clicked image appears at its full size, rather than being constrained like the preview.
Your previews are intentionally sized with Tailwind classes (e.g., "h-48" on the preview img) to keep them uniform. In your modal you’re also using classes like "w-full", "max-h-screen", and a container with "max-w-4xl". These constraints might be forcing your image to resize.
Remove or Adjust Container Constraints:
The div wrapping the modal image uses "max-w-4xl w-full", which limits its maximum width. Removing or altering these can give the image more room. For example, you might change it to have no max-width constraint:
HTML<div class="relative w-full"> <button class="absolute top-4 right-4 text-white text-3xl" @click="open = false">×</button> <img :src="image" class="object-contain" style="max-width: 100%; max-height: 100vh;"> </div>
Adjust the Image Classes:
Instead of forcing the modal image to always be "w-full", you may want to let it render its natural dimensions but still respect the viewport. In the example above, "object-contain" is kept (to preserve aspect ratio) while inline styles (or custom classes) ensure the image does not overflow the viewport.
Consider Using a Scrollable Container:
If full images are larger than the screen, you could wrap the image in a container that scrolls:
HTML<div x-show="open" x-cloak class="fixed inset-0 bg-black bg-opacity-75 flex justify-center items-center z-50"> <div class="relative overflow-auto" style="max-width: 100%; max-height: 100vh;"> <button class="absolute top-4 right-4 text-white text-3xl" @click="open = false">×</button> <img :src="image" class="object-contain" style="display: block; margin: 0 auto;"> </div> </div>
Adjust these suggestions as needed for your design, and your modal should display the full image when any photo is clicked.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by CosmicResearcher782 • 1 month ago
Everything in Alpine starts with the
x-data
directive.
x-data
defines a chunk of HTML as an Alpine component and provides the reactive data for that component to reference.Here's an example of a contrived dropdown component:
HTML<div x-data="{ open: false }"> <button @click="open = ! open">Toggle Content</button> <div x-show="open"> Content... </div> </div>
Don't worry about the other directives in this example (
@click
andx-show
), we'll get to those in a bit. For now, let's focus onx-data
.
x-data
directive - Alpine.js DocsThe variables declared under x-data
can only be used within the specific component. Since your Lightbox Modal is not inside the x-data
div, those variables are not valid there and the changes are not detected. After placing them in a shared div, it works correctly:
Wrong example
HTML<!-- Gallery Section with Lightbox --> <div x-data="{ open: false, image: '' }" class="max-w-7xl mx-auto py-8"> ... </div> <!-- Lightbox Modal --> <div x-show="open" x-cloak class="fixed inset-0 bg-black bg-opacity-75 flex justify-center items-center z-50"> ... </div>
Successfully example
HTML<div x-data="{ open: false, image: '' }"> <!-- Gallery Section with Lightbox --> <div class="max-w-7xl mx-auto py-8"> ... </div> <!-- Lightbox Modal --> <div x-show="open" x-cloak class="fixed inset-0 bg-black bg-opacity-75 flex justify-center items-center z-50"> ... </div> </div>
I left out Laravel from the reproduction so that it can be run directly from the browser. To reproduce the issue, Laravel is not necessary, only Alpine is required.
So instead of your @foreach, I used an Alpine template, which you can remove later. This way, your x-data
issue can be reproduced online without Laravel for others.
CSSbody { background-color: #000; color: #fff; } a { color: #ff0000; } a:hover { color: #ff5555; } [x-cloak] { display: none !important; }
HTML<script src="https://cdn.tailwindcss.com"></script> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> <body> <div x-data="{ open: false, image: '' }" class="min-h-screen flex flex-col"> <!-- Gallery Section with Lightbox --> <div class="max-w-7xl mx-auto py-8"> <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> <template x-for="(img, index) in Array.from({ length: 33 }, (_, i) => i + 1)" :key="index"> <div class="bg-gray-900 rounded-lg overflow-hidden shadow-md cursor-pointer" @click="open = true; image = `https://picsum.photos/400/400?${index}`" > <img :src="`https://picsum.photos/400/400?${index}`" alt="Obrazek_cislo" class="w-full h-48 object-cover"> </div> </template> </div> </div> <!-- Lightbox Modal --> <div x-show="open" x-cloak class="fixed inset-0 bg-black bg-opacity-75 flex justify-center items-center z-50" @click.away="open = false" > <div class="relative max-w-4xl w-full"> <button class="absolute top-4 right-4 text-white text-3xl" @click="open = false">×</button> <img :src="image" class="w-full max-h-screen object-contain"> </div> </div> </div> </body>
Run code snippetHide resultsExpand snippet
No comments yet.
No comments yet.