Skip to main content
April 1, 2026Dan Rodney/13 min read

Hiding & Showing: Display, Visibility, & Opacity

Master CSS visibility techniques for better web accessibility

CSS Visibility Methods Overview

Display: None

Completely removes elements from document flow. Not accessible to screen readers but useful for complete removal.

Visibility: Hidden

Hides elements visually but maintains space in layout. Screen reader accessible and preserves document flow.

Opacity: 0

Makes elements transparent while keeping them interactive. Best for transitions and maintains full accessibility.

Topics Covered in This HTML & CSS Tutorial:

Removing an Element from the Normal Document Flow with Display: None, Hiding/showing Elements with Visibility, Hiding/showing Elements with Opacity, How Display, Visibility, & Opacity Differ

Exercise Preview

preview hiding showing

Exercise Overview

In this comprehensive exercise, we'll explore three distinct methods for hiding and showing elements: the display property set to none, visibility hidden, and opacity manipulation. While all three approaches render content invisible to sighted users, they have fundamentally different effects on element rendering, document flow, and—critically—accessibility for users with visual impairments.

Understanding these differences isn't just academic—it directly impacts user experience and compliance with modern web accessibility standards. Screen readers, assistive technologies, and SEO crawlers interpret each method differently, making your choice a crucial design decision that extends far beyond visual presentation.

Getting Started

  1. We'll be switching to a new folder of prepared files for this exercise. In your code editor, close all open files to avoid confusion and maintain a clean workspace.
  2. For this exercise we'll be working with the Hiding and Showing Elements folder located in Desktop > Class Files > Advanced HTML CSS Class. Open that folder in your code editor if it allows you to (like Visual Studio Code does).
  3. Open index.html from the Hiding and Showing Elements folder.
  4. Preview index.html in Chrome (we'll be leveraging its powerful DevTools for testing and debugging).

    Our objective is to create dynamic overlays on top of each of the four large featured art images. Each photograph represents a different artistic category (Oil, Watercolor, Mixed Media, and Installation), and we want to display this categorical information through elegant text overlays. We'll start by implementing the Oil overlay as our foundational example.

  5. Leave the page open in Chrome so we can seamlessly switch between editing and testing.

Project Setup Steps

1

Close All Files

Close all open files in your code editor to avoid confusion with multiple projects

2

Open Project Folder

Navigate to Desktop > Class Files > Advanced HTML CSS Class and open the Hiding and Showing Elements folder

3

Launch Preview

Open index.html in your code editor and preview it in Chrome for DevTools access

Styling & Positioning the Overlay

Before diving into hiding and showing techniques, we need to establish the visual foundation for our overlay system. This involves both semantic markup and precise CSS positioning.

  1. Switch back to index.html in your code editor.

  2. In the first <div class=category> tag, add the following markup structure:

    <div class=category>
       <a href="#">
          <img src="img/oil.jpg" ALT="">
          <div class="description">Oil</div>
       </a>
    </div>
  3. Save the file and observe the current state—our overlay exists but lacks proper styling and positioning.
  4. Open main.css from the css folder (in the Hiding and Showing Elements folder).
  5. Below the .category a rule (in the general styles, not the media query), create the foundational overlay styling:

    .category.description {
       text-align: center;
       text-transform: uppercase;
       font-family: Oswald, sans-serif;
       font-size: 2rem;
       line-height: 4rem;
       color: #fff;
       background: rgba(0,0,0,.4);
    }
  6. Save the file, then reload the page in Chrome. You'll notice we have the visual styling, but the overlay isn't positioned correctly over the image—this requires strategic use of CSS positioning.
  7. Switch back to main.css in your code editor.
  8. The anchor tag inside our category div serves as the container for both image and overlay, making it our ideal positioning context. In the .category a rule, establish the positioning context:

    .category a {
       box-shadow: 0 12px 18px rgba(0,0,0,.3);
       margin: 30px 0;
       display: block;
       text-decoration: none;
       position: relative;
    }

    NOTE: Remember that anchor elements are inherently inline, which creates positioning limitations. Notice we've already set display: block to create the proper container—inline-block would also achieve this positioning foundation.

  9. Now position our description overlay absolutely within this relative container:

    .category.description {
       text-align: center;
       text-transform: uppercase;
       font-family: Oswald, sans-serif;
       font-size: 2rem;
       line-height: 4rem;
       color: #fff;
       background: rgba(0,0,0,.4);
       position: absolute;
    }
  10. Save the file, then reload the page in Chrome. The overlay now has absolute positioning, but it has collapsed without explicit dimensions—let's define its boundaries.
  11. Switch back to main.css in your code editor.
  12. To make the overlay stretch to fill the entire anchor container, add precise positioning coordinates to .category.description:

    .category.description {

    Code Omitted To Save Space

    position: absolute;
       top: 0;
       right: 0;
       bottom: 0;
       left: 0;
    }
  13. Save the file, then reload the page in Chrome. Perfect—the overlay now fills its container completely, but we need to center the text vertically for optimal visual balance.
  14. Test the responsive behavior by resizing your browser window. Notice how the image containers scale proportionally while maintaining their aspect ratio. This responsive nature means we can't rely on fixed pixel values for vertical centering.
  15. Switch back to main.css in your code editor.

    The vertical-align property won't solve our centering challenge here—it only applies to inline or table elements, and we need our div to maintain block display to preserve the full overlay coverage.

  16. We'll use a calculated padding approach that leverages CSS calc() to achieve perfect vertical centering. Add this to the .category.description rule:

    .category.description {

    Code Omitted To Save Space

    left: 0;
       padding-top: calc(33.33%—4rem/2);
    }
    Absolute Positioning Setup

    Remember that anchors are inline elements by default. Set display: block or inline-block on the parent anchor to make it work as a proper relative positioning container for absolutely positioned children.

Understanding the Calculation

This mathematical approach accounts for both our image's aspect ratio and text dimensions. Since our text has a 4rem line-height and percentage padding is calculated from container width (not height), we can use the image's aspect ratio to achieve precise centering. Here's the breakdown:

  • (image height / image width) / 2 - line height / 2
  • Our calculation: (560px / 840px) / 2 = 0.3333 (33.33%)
  • This positions text at the vertical center, accounting for the text's own height

This technique ensures consistent centering across all responsive breakpoints—a crucial consideration for modern web development.

  • Save the file, then reload the page in Chrome.
  • Test the responsive behavior again by resizing your browser window. The Oil text should remain perfectly centered regardless of viewport size—this is the hallmark of robust, scalable CSS.

  • Removing an Element from the Normal Document Flow with Display: None

    Now we'll implement the interactive behavior: hiding the overlay initially and revealing it on hover. This is where understanding the nuances between different hiding methods becomes critical for both functionality and accessibility.

    Let's begin with display: none, which completely removes elements from the document flow—essentially making the browser behave as if the element doesn't exist at all.

    1. Switch back to main.css in your code editor.
    2. Add the display property to initially hide our overlay:

      .category.description {

      Code Omitted To Save Space

      padding-top: calc(33.33%—4rem/2);
         display: none;
      }
    3. Save the file, then reload the page in Chrome.

      Notice the Oil text overlay has vanished completely. This isn't just visual hiding—display: none removes the element from the document's render tree entirely, making it undetectable to both visual users and assistive technologies.

    4. Now we'll implement the hover state to reveal the overlay. Switch back to main.css in your code editor.

      Since the description element is hidden from the document flow, we can't hover over it directly. Instead, we'll target the always-visible anchor tag and use CSS specificity to show the nested description.

    5. Below the .category.description rule, add this hover-triggered display rule:

      .category a:hover.description {
         display: block;
      }

      NOTE: Reading CSS selectors from right to left clarifies the targeting: we're selecting .description divs, but only when they're nested inside anchor tags that are being hovered, and only within .category containers. This specificity ensures our hover behavior is precisely controlled.

    6. Save the file, then reload the page in Chrome and test the interaction:

      • The overlay should be completely invisible initially
      • Hover over the oil painting image to see the overlay appear instantly

      The functionality works, but there's a significant accessibility concern we need to address.

    Display: None Analysis

    Pros
    Completely removes element from document flow
    No space is reserved for hidden elements
    Clean layout without gaps
    Reduces DOM rendering overhead
    Cons
    Not accessible to screen readers
    Cannot be transitioned with CSS
    Completely removes element from interaction
    Poor accessibility for disabled users

    Hiding/Showing Elements with Visibility

    The display: none approach creates a serious accessibility barrier. Screen readers and other assistive technologies treat these elements as non-existent, potentially leaving visually impaired users without crucial content—even when they successfully navigate to and hover over the interactive element.

    Modern web development demands inclusive design practices. Let's explore the visibility property, which hides elements visually while preserving their presence in the accessibility tree.

    1. Switch back to main.css in your code editor.
    2. We'll temporarily disable the display properties to test our visibility approach. Comment out both display declarations:

      .category.description {

      Code Omitted To Save Space

      padding-top: calc(33.33%—4rem/2);
         /* display: none;*/
      }
      
      .category a:hover.description {
         /* display: block;*/
      }

      TIP: Visual Studio Code users can efficiently toggle comments using Cmd–/ (Mac) or Ctrl–/ (Windows).

    3. Now implement the visibility-based hiding approach. The visibility property offers a more nuanced solution—hidden from sighted users but still present in the document structure:

      .category.description {

      Code Omitted To Save Space

      padding-top: calc(33.33%—4rem/2);
         /* display: none; */
         visibility: hidden;
      }
      
      .category a:hover.description {
         /* display: block; */
         visibility: visible;
      }
    4. Save the file, then reload the page in Chrome and test the interaction:

      • Hover over the oil painting image to see the overlay appear
      • Visually, the behavior appears identical to the display: none approach
      • However, screen readers can now access the hidden content, making this a more inclusive solution

      This approach maintains the element's space in the document flow while hiding it visually, creating a bridge between visual design and accessibility requirements.

    Accessibility Improvement

    Using visibility: hidden instead of display: none makes content accessible to screen readers while still hiding it visually. This follows web accessibility best practices for inclusive design.

    Hiding/Showing Elements with Opacity

    The third approach uses the opacity property, offering the most flexibility for modern web interactions. Unlike the binary nature of display and visibility, opacity provides granular control with values from 0 (fully transparent) to 1 (fully opaque), enabling sophisticated visual effects and smooth transitions.

    1. Switch back to main.css in your code editor.
    2. Comment out the visibility properties in both rules to disable them temporarily.
    3. Let's first experiment with partial transparency to understand opacity's flexibility:

      .category.description {

      Code Omitted To Save Space

      /* display: none; */
         /* visibility: hidden; */
         opacity: .5;
      }
    4. Save the file, then reload the page in Chrome. Notice how the description is semi-transparent—demonstrating opacity's nuanced control that neither display nor visibility can provide.
    5. Switch back to main.css in your code editor.
    6. Now implement the complete hide-and-reveal pattern using full transparency and opacity:

      .category.description {

      Code Omitted To Save Space

      /* visibility: hidden; */
         opacity: 0;
      }
      
      .category a:hover.description {
         /* display: block; */
         /* visibility: visible; */
         opacity: 1;
      }
    7. Save the file, then reload the page in Chrome. Test the hover interaction—visually, it appears identical to our previous solutions, but the underlying behavior is significantly different and more accessibility-friendly.

    Implementing Opacity Controls

    1

    Set Initial Transparency

    Use opacity: 0 to make elements fully transparent while maintaining their position in document flow

    2

    Configure Hover State

    Set opacity: 1 on hover to reveal the element with full opacity

    3

    Test Interaction

    Verify that transparent elements remain interactive and accessible to screen readers

    How Display, Visibility, & Opacity Differ

    Understanding the fundamental differences between these three approaches is crucial for making informed development decisions. Each method affects document flow, user interaction, and accessibility in distinct ways. Let's conduct a systematic comparison using Chrome DevTools to see these differences in action.

    1. Switch back to main.css in your code editor.
    2. We'll use the blockquote elements as test subjects for our comparison. Add testing properties to the blockquote rule, commenting them out initially for individual testing:

      blockquote {
         border-left: solid 3px #17a99c;
         border-right: solid 3px #17a99c;
         color: #505050;
         margin: 20px;
         padding: 20px;
         cursor: pointer;
         /* display: none; */
         /* visibility: hidden; */
         /* opacity: 0; */
      }

      NOTE: The cursor: pointer property will help us test user interaction capabilities. Each hiding property is commented separately so we can enable and disable them individually through DevTools checkboxes—this provides clear, comparative testing.

    3. Save the file, then reload the page in Chrome.
    4. Locate the blockquote below the top two images that begins with "Art should bring us closer…" and hover over it to confirm the pointer cursor appears. This establishes our baseline for interaction testing.
    5. Ctrl–click (Mac) or Right–click (Windows) on the blockquote and select Inspect to open DevTools.
    6. Ensure the <blockquote> element is selected in the Elements panel.
    7. In the Styles panel, locate the blockquote rule containing our test properties. You may need to scroll down to find it.
    8. Enable display: none; by checking its box and observe the dramatic effects:

      • All blockquote elements disappear completely from the page
      • The elements are removed from the normal document flow—other content shifts to fill the space
      • Hover over the now-empty areas where blockquotes existed—no pointer cursor appears
      • The elements are completely non-interactive and invisible to all users and technologies
    9. Uncheck display: none; to restore the elements, then enable visibility: hidden; and note the key differences:
    10. Check visibility: hidden; to enable it:

      • Blockquote content disappears, but notice the white space gaps that remain
      • These gaps prove the elements still occupy their original space in the document flow
      • Hover over the gaps—no pointer cursor appears, indicating the elements are non-interactive
      • However, screen readers can still access this content, making it more accessible than display: none
    11. Uncheck visibility: hidden; to restore normal visibility.
    12. Finally, enable opacity: 0 and observe the most nuanced behavior:

      • Again, gaps appear where content was—confirming elements remain in the document flow
      • Hover over the gaps and notice the pointer cursor appears
      • This reveals a crucial difference: opacity: 0 elements remain fully interactive
      • Users can click, hover, and otherwise interact with completely transparent elements
      • Screen readers also have full access to this content

    CSS Visibility Methods Comparison

    FeatureDisplay: NoneVisibility: HiddenOpacity: 0
    Document FlowRemovedMaintainedMaintained
    Screen Reader AccessNoYesYes
    User InteractionNoNoYes
    CSS TransitionsNoNoYes
    Space ReservedNoYesYes
    Recommended: Use opacity for the best combination of accessibility, interactivity, and animation support

    Finishing Up

    Based on our comprehensive testing, which approach best serves our project's needs? We need code that's fully accessible, eliminating display: none from consideration. For our upcoming CSS transitions work, we need smooth animations between states—visibility: hidden can't transition smoothly since it's binary (hidden/visible), while opacity's numeric values (0 to 1) create perfect transition foundations.

    The opacity approach provides the ideal combination of accessibility, interactivity, and animation compatibility for modern web development.

    1. Switch back to main.css in your code editor.
    2. Clean up the blockquote rule by removing our test properties:

      blockquote {
         border-left: solid 3px #17a99c;
         border-right: solid 3px #17a99c;
         color: #505050;
         margin: 20px;
         padding: 20px;
      }
    3. Streamline the .category.description rule to use only opacity:

      .category.description {

      Code Omitted To Save Space

      padding-top: calc(33.33%—4rem/2);
         opacity: 0;
      }
    4. Similarly, clean up the hover rule:

      .category a:hover.description {
         opacity: 1;
      }
    5. Save main.css and reload the page in Chrome.
    6. Perform a final test of the hover interaction to confirm everything works as expected. The overlay should be invisible initially and appear smoothly on hover—setting the foundation for advanced CSS transitions in future exercises.

    Why Opacity Wins

    Opacity is chosen as the best solution because it maintains accessibility, supports CSS transitions for smooth animations, and keeps elements interactive. This makes it ideal for modern web development practices.

    Optional Bonus: Adding the Three Remaining Overlays

    To complete our gallery interface, let's implement the remaining overlays. This repetition will reinforce the techniques we've learned while creating a fully functional image gallery with consistent interactive behavior.

    1. Switch to index.html in your code editor.
    2. Add the overlay markup for the watercolor category:

      <a href="#">
         <img src="img/watercolor.jpg" ALT="">
         <div class="description">Watercolor</div>
      </a>
    3. Add the overlay for mixed-media:

      <a href="#">
         <img src="img/mixed-media.jpg" ALT="">
         <div class="description">Mixed Media</div>
      </a>
    4. Complete the series with the installation overlay:

      <a href="#">
         <img src="img/installation.jpg" ALT="">
         <div class="description">Installation</div>
      </a>
    5. Save the file, then reload the page in Chrome for comprehensive testing.
    6. Systematically test each image overlay by hovering over all four images. Verify that:

      • Each overlay appears smoothly on hover
      • Category labels are accurate and properly centered
      • The interaction feels consistent across all elements
      • Responsive behavior works at different viewport sizes

      You now have a complete, accessible image gallery with professional-grade hover interactions—and a deep understanding of how different CSS hiding techniques impact both user experience and accessibility.

    Complete the Gallery

    0/4

    Key Takeaways

    1Display: none completely removes elements from document flow and screen readers, making it inaccessible
    2Visibility: hidden maintains document flow and screen reader access while hiding visual content
    3Opacity: 0 provides the most flexibility with accessibility, interactivity, and CSS transition support
    4Absolute positioning requires a relative positioned parent - use display: block on inline elements like anchors
    5Responsive vertical centering can be achieved using calc() with percentage-based padding calculations
    6Screen reader accessibility should be a primary consideration when choosing visibility methods
    7Opacity values are numeric and work seamlessly with CSS transitions for smooth animations
    8Interactive elements remain clickable even when opacity is set to 0, unlike other hiding methods

    RELATED ARTICLES