skip to Main Content

Using CSS, how can I show an element only when the parent content is overflowing?

(This is known as a "show more" button.)

Answer requirements:

  • The content has a fixed max-height
  • The child content can contain any content (text, images, etc)
  • The solution has to be CSS only.

CSS only is a very strict requirement. CSS only is faster, has no flicker on startup, is more responsive, etc.

Non-working Code

.container {
    max-height: 100px;
    overflow: hidden;
    position: relative;
    margin: 1rem;
}

.big-content {
  background: linear-gradient(to bottom, black, white);
  height: 200px;
}

.small-content {
  background: linear-gradient(to bottom, black, white);
  height: 50px;
}

.overflow-message {
    position: absolute;
    bottom: 0px;
}
<div class="container">
    <div class="big-content"></div>
    <div class="overflow-message">Overflowing (visible)</div>
</div>
<div class="container">
    <div class="small-content"></div>
    <div class="overflow-message">Not overflowing (not visible)</div>
</div>

Research

No similar question is CCS-only.

2

Answers


  1. Chosen as BEST ANSWER

    Yes, we can use CSS max-height and calc which have been supported in Chrome since 2013.

    Hide If Overflowing

    The idea is that we can push the "show more" button down if there is remaining space, but leave it unchanged if there is no remaining space.

    1. calc(MAX-HEIGHT - 100%)
      • Calculate the remaing space using calc and -
    2. calc((MAX-HEIGHT - 100%) * 10000)
      • Multiply by a large number, so 1px remaining results in an a large offset. This prevents the button from being partially visible.
    3. position: absolute; bottom: calc((MAX-HEIGHT - 100%) * 10000);
      • Offset the button from the bottom.
      • If there is any remaining space, bottom will be set to a large negative value, resulting in the button being hidden.

    Overflowing Example

    Putting it together, gives us bottom: calc((100% - 100px) * 10000);, for a container which has a max-height: 100px.

    The linear gradient is overflowing, which can be seen as it cuts off before it finishes the gradient.

    .container {
      overflow: hidden;
      position: relative;
      width: 200px;
      max-height: 100px;
      
      & .content {
        width: 10px;
        height: 200px; /* greater-than container height */
        background: linear-gradient(to bottom, white, black);
      }
      
      & .message {
        position: absolute;
        bottom: calc((100% - 100px) * 10000);
        background: white;
      }
    }
    <div class="container">
        <div class="content"></div>
        <div class="message">
            Overflowing
        </div>
    </div>

    Non-overflowing Example

    The linear gradient does not cut off, so the text is not visible.

    .container {
      overflow: hidden;
      position: relative;
      width: 200px;
      max-height: 100px;
      
      & .content {
        width: 10px;
        height: 99px; /* less-than container height */
        background: linear-gradient(to bottom, white, black);
      }
      
      & .message {
        position: absolute;
        bottom: calc((100% - 100px) * 10000);
        background: white;
      }
    }
    <div class="container">
        <div class="content"></div>
        <div class="message">
            Not overflowing so this text is not visible
        </div>
    </div>


  2. Adding a solution for the future using scroll-driven animations where you don’t need to know the value of max-height or height.

    You can test it using the latest version of chrome

    .container {
      overflow: hidden;
      position: relative;
      max-height: 100px;
      scroll-timeline: --s;
    
      .message {
        position: absolute;
        bottom: 0;
        visibility: hidden;
        animation: show;
        animation-timeline: --s;
      }
    }
    @keyframes show {
      0%,100% {visibility: visible}   
    }
    
    /* irrelevant CSS */
    .container {
      width: 200px;
      margin: 10px;
      border: 1px solid red;
    }
    <div class="container">
        <div class="content" style="height: 90px;"></div>
        <div class="message">
            You don't see me because we don't reach max-height
        </div>
    </div>
    
    <div class="container">
        <div class="content" style="height: 110px"></div>
        <div class="message">
            You see me because we reach max-height
        </div>
    </div>
    
    <div class="container" style="max-height: 200px;">
        <div class="content" style="height: 110px"></div>
        <div class="message">
            You don't see me because we increased the max-height
        </div>
    </div>
    
    <div class="container" style="height: 80px;max-height: auto;">
        <div class="content" style="height: 110px"></div>
        <div class="message">
            It works with height as well
        </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search