Image Gallery

Demo

				
					
<div class="body">
    <div class="image-gallery">
      <div class="image-item">
        <a
          href="https://example.com/link1"
          role="link"
          tabindex="0"
          aria-label="Link Image 1 - Placeholder 300x200"
        >
          <img decoding="async" src="https://placehold.co/300x200" alt="Description 1" />
        </a>
      </div>
      <div class="image-item">
        <a
          href="https://example.com/link2"
          role="link"
          tabindex="0"
          aria-label="Link Image 2 - Placeholder 600x400"
        >
          <img decoding="async" src="https://placehold.co/600x400" alt="Description 2" />
        </a>
      </div>
      <div class="image-item">
        <img decoding="async"
          src="https://placehold.co/1000x300"
          alt="Description"
          aria-label="Plain Image 3 - Placeholder 1000x300"
        />
      </div>
      <div class="image-item">
        <button type="button" aria-label="Button Image 4 - Placeholder 300x400">
          <img decoding="async" src="https://placehold.co/300x400" alt="Description 3" />
        </button>
      </div>
      <div class="image-item">
        <a
          href="https://example.com/link5"
          role="link"
          tabindex="0"
          aria-label="Link Image 5 - Placeholder 300x400"
        >
          <img decoding="async" src="https://placehold.co/300x400" alt="Description 4" />
        </a>
      </div>
      <div class="image-item">
        <img decoding="async"
          src="https://placehold.co/240x380"
          alt="Description"
          aria-label="Plain Image 6 - Placeholder 240x380"
        />
      </div>
      <div class="image-item">
        <button type="button" aria-label="Button Image 7 - Placeholder 500x175">
          <img decoding="async" src="https://placehold.co/500x175" alt="Description 5" />
        </button>
      </div>
      <div class="image-item">
        <a
          href="https://example.com/link8"
          role="link"
          tabindex="0"
          aria-label="Link Image 8 - Placeholder 900x430"
        >
          <img decoding="async" src="https://placehold.co/900x430" alt="Description 6" />
        </a>
      </div>
      <div class="image-item">
        <img decoding="async"
          src="https://placehold.co/875x600"
          alt="Description"
          aria-label="Plain Image 9 - Placeholder 875x600"
        />
      </div>
      <div class="image-item">
        <button
          type="button"
          aria-label="Button Image 10 - Placeholder 300x400"
        >
          <img decoding="async" src="https://placehold.co/300x400" alt="Description 7" />
        </button>
      </div>
      <div class="image-item">
        <a
          href="https://example.com/link11"
          role="link"
          tabindex="0"
          aria-label="Link Image 11 - Placeholder 300x400"
        >
          <img decoding="async" src="https://placehold.co/300x400" alt="Description 8  " />
        </a>
      </div>
      <div class="image-item">
        <img decoding="async"
          src="https://placehold.co/240x380"
          alt="Description"
          aria-label="Plain Image 12 - Placeholder 240x380"
        />
      </div>
      <!-- Add more images as needed -->
    </div>
  </div>
				
			
				
					
/* CSS styles */
.body {
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.image-gallery {
  width: 50%; /* Adjust container width here */
  column-gap: 8px; /* Adjust the gap between columns */
  margin: 0;
  padding: 0;
  columns: auto 4; /* Adjust the number of columns based on the layout */
}

.image-item {
  display: inline-block;
  margin-bottom: 8px; /* Adjust the vertical spacing between images */
  break-inside: avoid; /* Prevent breaking within images */
  transition: transform 0.3s ease-in-out; /* Added transition */
}

.image-item img {
  width: 100%; /* Ensure images take the full width of their container */
  height: auto;
  display: block;
}

.image-item button {
  border: none;
}
				
			
				
					
// Wait for the DOM content to load before executing the script
document.addEventListener("DOMContentLoaded", function () {
  // Select the image gallery container
  const gallery = document.querySelector(".image-gallery");

  // Select all individual image items within the gallery
  const items = gallery.querySelectorAll(".image-item");

  // Iterate over each image item
  items.forEach((item) => {
    // Listen for the "mouseover" event on each image item
    item.addEventListener("mouseover", function (event) {
      // Iterate over all image items again to handle scaling logic
      items.forEach((otherItem) => {
        // Check if the current item being iterated is not the hovered item
        if (otherItem !== item) {
          // Calculate the distance between the hovered item and other items
          const dx = Math.abs(otherItem.offsetLeft - item.offsetLeft);
          const dy = Math.abs(otherItem.offsetTop - item.offsetTop);

          // Check if the other item is within a specific distance from the hovered item
          if (dx <= 350 && dy <= 350) {
            // Apply a scaling effect to nearby items
            otherItem.style.transform = "scale(0.95)";
          } else {
            // Reset the scaling for items outside the specified distance
            otherItem.style.transform = "";
          }
        } else {
          // Apply a scaling effect to the hovered item itself
          item.style.transform = "scale(1.05)";
        }
      });
    });

    // Listen for the "mouseout" event on each image item
    item.addEventListener("mouseout", function () {
      // Reset the scaling for all items when the cursor moves away
      items.forEach((otherItem) => {
        otherItem.style.transform = "";
      });
    });
  });
});
				
			

Why use an image gallery?

An image gallery component in web development serves as a powerful tool for organizing and displaying a collection of visual content, offering users a seamless and engaging browsing experience. It helps in presenting a series of images or multimedia content in a structured and visually appealing manner, fostering better engagement and comprehension. From product showcases to portfolios and storytelling, image galleries enhance the aesthetic appeal of a website while facilitating efficient content consumption. Accessibility-wise, an image gallery, when built with attention to detail, supports various accessibility features like alternative text (alt tags), keyboard navigation, and semantic HTML, ensuring inclusivity by providing access to visual content for users of all abilities and assistive technologies. Thus, employing an image gallery component not only elevates the visual appeal of a website but also contributes significantly to its accessibility and user-friendliness.

What are some accessibility concerns?

  1. Alternative Text (Alt Tags):
    • Concern: Ensure each image has descriptive and concise alt text that conveys its purpose or content.
    • Mitigation: Add descriptive alt text for images: <img src=”example.jpg” alt=”Brief description”>.
  2. Keyboard Navigation:
    • Concern: Enable keyboard focus on interactive elements like buttons or links within the gallery to ensure seamless navigation for users who rely on keyboards or screen readers.
    • Mitigation: Implement tabindex and ARIA roles for keyboard accessibility: tabindex=”0″ and role=”button/link”.
  3. Focus Styles:
    • Concern: Ensure clear and visible focus styles for focused elements, aiding users in understanding which element they’re interacting with.
    • Mitigation: Style focus states for interactive elements: :focus.
  4. Semantic HTML:
    • Concern: Use semantic HTML elements and proper labeling to enhance the structure and clarity of the gallery for screen readers and other assistive technologies.
    • Mitigation: Use semantic HTML tags: <figure>, <figcaption>, <a>, <button>, etc., appropriately.
  5. Color Contrast:
    • Concern: Ensure sufficient color contrast between text, background, and interactive elements to improve readability and usability for users with visual impairments.
    • Mitigation: Check color contrast using tools like WebAIM’s Contrast Checker or browser extensions.
  6. Animations:
    • Concern: Control and provide options to pause or adjust any automatic or looping animations to prevent potential issues for users with vestibular disorders or cognitive sensitivities.
    • Mitigation: Offer controls to pause or adjust animations: “Pause” or “Stop” buttons for slideshows.
  7. Responsive Design:
    • Concern: Ensure responsiveness for different screen sizes and devices, allowing users to access and navigate the gallery comfortably on various devices.
    • Mitigation: Employ responsive design techniques: Use media queries and flexible layouts to adapt to different screens.
Tested using
Chrome
with NVDA
Firefox
with NVDA
  • W3C SVG
    1.1.1
    Non-text Content ( level A ) :
    All non-text content that is presented to the user has a text alternative that serves the equivalent purpose.
  • W3C SVG
    2.4.3
    Focus Order ( level A ) :
    If a Web page can be navigated sequentially and the navigation sequences affect meaning or operation, focusable components receive focus in an order that preserves meaning and operability.
  • W3C SVG
    4.1.2
    Name, Role, Value ( level A ) :
    For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies.