What steps should I take to prevent any unwanted white space underneath my footer when collapsing an accordion that is located at the bottom of my webpage?

I have a web page with extensive content that requires scrolling to view, like a standard web page layout. The bottom section of the page features an accordion containing citation details specific to that page. Initially, this accordion is collapsed, displaying only up to 3 lines of content and a "View All Sources" button. Clicking on this button expands the accordion to reveal all the citation information.

Upon loading the page, when the accordion is collapsed, there is no extra space below the footer.

In cases where there are numerous sources displayed within the expanded accordion, it may extend beyond the screen height, necessitating vertical scrolling to access all content. When contracting the accordion by clicking the button again, it retracts, sometimes pulling up the footer due to the amount of content displayed previously, resulting in excess white space beneath the footer. This issue needs addressing for the design's seamless flow.

A live demo showcasing the problem can be viewed on Github Pages here:

The screenshots below illustrate the problem:

Footer appearance before expansion

Footer appearance after expansion

Footer appearance after contraction

I attempted moving the source block to the top of the page to avoid the issue entirely. However, putting the sources at the top isn't feasible for this project as they are required at the bottom. I also tried dynamically adjusting the overflow property of the HTML and Body tags based on the accordion status but observed no impact on resolving the issue.

The described issues differ from typical instances involving excessive whitespace caused by short pages, which wasn't helpful in addressing the current situation where abundant content pushes the footer out of sight, necessitating manual scrolling to reach it.

I'm running out of options on troubleshooting steps to take next. Is there possibly a browser-related bug causing this behavior? If so, what solutions or workarounds can prevent it from affecting the layout?

Answer №1

When you call the viewLessLink.click() function, it sets

sourceList.css('overflow', 'visible');
on the ol. However, since the content is hidden on click, the correct setting should be overflow: hidden. To fix this, update the click listener to use
sourceList.css('overflow', 'hidden');

/**
 * Source block functionality
 */
(function($) {

  let viewAllLink = $('.viewall-link');
  let viewLessLink = $('.viewless-link');
  let sourceList = $('.sources-block ol');

  if (!viewAllLink.length ||
    !sourceList.length ||
    !viewLessLink.length
  ) {
    return;
  }

  /**
   * Clicking on View All Sources link...
   */
  viewAllLink.click(function() {
    sourceList.css('height', 'unset');
    sourceList.css('overflow', 'visible');
    sourceList.css('-webkit-mask-image', 'none');
    sourceList.css('mask-image', 'none');
    viewAllLink.css('display', 'none');
    viewLessLink.css('display', 'block');
  });

  /**
   * Clicking on the Hide Sources link...
   */
  viewLessLink.click(function() {

    let height = '80px';

    if (window.matchMedia("(max-width: 767px)").matches) {

      if (countSourceLines(sourceList) > 6) {
        height = '144px';
      }
    } else {

      if (countSourceLines(sourceList) > 3) {

      }
    }

    sourceList.css('height', height);
    sourceList.css('overflow', 'hidden'); // this is the only value that needed to be updated
    sourceList.css('-webkit-mask-image', 'linear-gradient(180deg, #000 70%, transparent)');
    sourceList.css('mask-image', 'mask-image: linear-gradient(180deg, #000 70%, transparent);');
    viewAllLink.css('display', 'block');
    viewLessLink.css('display', 'none');
  });

  /**
   * Set initial state of Sources block and if we need to display the View All link or not.
   */

  if (window.matchMedia("(max-width: 767px)").matches) {

    if (countSourceLines(sourceList) > 6) {
      sourceList.css('height', '144px');
      sourceList.css('overflow', 'hidden');
      viewAllLink.css('display', 'block');
    } else {
      sourceList.css('-webkit-mask-image', 'none');
      sourceList.css('mask-image', 'none');
      viewAllLink.css('display', 'none');
    }
  } else {

    console.log(countSourceLines(sourceList));

    if (countSourceLines(sourceList) > 3) {
      sourceList.css('height', '80px');
      sourceList.css('overflow', 'hidden');
      viewAllLink.css('display', 'block');
    } else {
      sourceList.css('-webkit-mask-image', 'none');
      sourceList.css('mask-image', 'none');
      viewAllLink.css('display', 'none');
    }
  }

  /**
   *
   * @param el
   * @returns {number}
   */
  function countSourceLines(el) {
    let olElement = $(el);
    let olHeight = olElement.outerHeight();
    let lineHeight = parseInt(olElement.css("line-height").replace("px", ""));

    return olHeight / lineHeight;
  }
})(jQuery);
html {
  scroll-behavior: smooth !important;
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Museo Sans', sans-serif;
  font-size: 18px;
  line-height: 28px;
  font-weight: 300;
  color: #222;
  margin: 0;
  padding: 0;
}

#content-wrap {
  padding: 50px;
}

#footer {
  text-align: center;
  background: #222;
  color: #FFF;
  padding: 50px;
}

.sources-block {
  background: #F0F0F0;
  padding: 8px;
  margin: 48px 0;
}

.sources-block h4 {
  font-weight: 600;
  margin: 0;
  padding: 8px;
}

.sources-block p {
  margin-bottom: 0;
}

.sources-block ol {
  padding-left: 32px;
  -webkit-mask-image: linear-gradient(180deg, #000 70%, transparent);
  mask-image: linear-gradient(180deg, #000 70%, transparent);
  margin-bottom: 5px;
}

.sources-block li {
  word-break: break-word;
  margin-bottom: 0;
}

.sources-block .viewall-link,
.sources-block .viewless-link {
  font-weight: 600;
  font-size: 16px;
  line-height: 24px;
  text-align: center;
  color: #298FC2;
  cursor: pointer;
  border-top: 1px solid #298fc2;
  padding: 8px 0 0;
}

.sources-block .viewless-link {
  display: none;
}

.sources-block i {
  padding-left: 5px;
}
<!DOCTYPE html>
<html>
<head>
  <title>Footer Whitespace Demo</title>
</head>
<body>
  <div id="content-wrap">
    <h1>Example Page</h1>
   
    
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et felis in magna dignissim finibus. Fusce neque ante, mattis condimentum metus id, rhoncus fermentum neque. Nulla vel aliquam eros. Proin convallis imperdiet mauris id dignissim. Duis
      tortor magna, molestie sit amet tortor egestas, aliquet sollicitudin tortor. Curabitur volutpat convallis nisl, ut vehicula massa convallis eu. Aliquam erat volutpat. Pellentesque sit amet lacus sem. Nam lacus erat, viverra eget tincidunt non, ullamcorper
      non justo. Sed ultricies diam eu lacus luctus eleifend.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et felis in magna dignissim finibus. Fusce neque ante, mattis condimentum metus id, rhoncus fermentum neque. Nulla vel aliquam eros. Proin convallis imperdiet mauris id dignissim. Duis
      tortor magna, molestie sit amet tortor egestas, aliquet sollicitudin tortor. Curabitur volutpat convallis nisl, ut vehicula massa convallis eu. Aliquam erat volutpat. Pellentesque sit amet lacus sem. Nam lacus erat, viverra eget tincidunt non, ullamcorper
      non justo. Sed ultricies diam eu lacus luctus eleifend.</p>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et felis in magna dignissim finibus. Fusce neque ante, mattis condimentum metus id, rhoncus fermentum neque. Nulla vel aliquam eros. Proin convallis imperdiet mauris id dignissim. Duis
      tortor magna, molestie sit amet tortor egestas, aliquet sollicitudin tortor. Curabitur volutpat convallis nisl, ut vehicula massa convallis eu. Aliquam erat volutpat. Pellentesque sit amet lacus sem. Nam lacus erat, viverra eget tincidunt non, ...

    <div class="sources-block">
      <h4>Sources</h4>
      <ol>
        <li>Source Blah Blah Blah</li>
        
      
      </ol>
      <div class="viewall-link">View All Sources <i class="fa fa-chevron-down"></i></div>
      <div class="viewless-link">Hide Sources <i class="fa fa-chevron-up"></i></div>
    </div>
  </div>
  <div id="footer">
    Footer Here
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js" integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</body>
</html>

Answer №2

I stripped away most of the CSS and only added what was necessary for this example - I made notes where some CSS is purely for visual purposes.

Keep in mind that I modified the HTML to stack the containers, which is best achieved with

grid-template-rows: auto 1fr auto;
. The "container" classes here are more like placeholders than anything else, except for a few visual elements.

I eliminated all the JavaScript (jQuery is included but not essential here).

All I do is toggle the dataset value toggle, and the CSS handles the rest. You could even introduce a "middle" value by setting a middle height; for instance, 5em, add a button and a value for that, and adjust the CSS accordingly.

(function($) {

  const toggleValues = {
    small: "little",
    large: "big"
  };
  $('.viewall-link')
    .add('.viewless-link')
    .on('click', function(event) {
      let things = $(this).closest('.sources-block').find('.things-list').get(0);
      let collapseValue = things.dataset.toggle;
      things.dataset.toggle = collapseValue == toggleValues.small ? toggleValues.large : toggleValues.small;
    });
})(jQuery);
body {
  margin: 0;
  padding: 0;
}

.parent {
  /* stack the containers */
  display: grid;
  grid-template-rows: auto 1fr auto;
}

.sources-block {
  display: grid;
}

.things-list {
  display: flex;
  flex-direction: column;
}

.things-list[data-toggle="little"] {
  height: 4em;
  overflow: hidden;
}

.things-list[data-toggle="big"] {
  /* just to show it applied - do whatever here */
  background-color: #ddddff44;
}


/* below is mostly for better presentation */

.parent {
  border: 1px solid lime;
}

.content-container {
  border: solid magenta 1px;
  margin: 0.25rem;
}

.content-parts {
  border: solid cyan 1px;
  display: grid;
  place-items: center;
  margin: 0.25rem;
}

.sources-block {
  background-color: #F0F0F0;
  padding: 0.5rem;
  border: solid 3px red;
  place-items: center;
}

.things-list {
  border: solid blue 1px;
}

.links-container {
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.toggle-link {
  border: solid 2px #888888;
  padding: 0.5rem;
  border-radius: 0.5rem;
}

#footer {
  text-align: center;
  background: #222;
  color: #FFF;
  padding: 4rem;
}
<body>
  <div class="parent">
    <div class="content-container">
      <div id="content-wrap" class="content-parts">
        <h1>Example Page</h1>
        <p>Lorem ipsum dolor sit amet... [truncated for brevity]

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Submit Form using Ajax - Update text in HTML element upon click

As I am working on developing a message system, I encountered an issue where the message content is not opening correctly in my template when clicking the "See" button. My intention is to implement an Ajax call that will replace the content with jQuery .te ...

PHP's json_encode function does not escape the single quote character

I am currently facing an issue with parsing a JSON encoded object in JavaScript. When I use JSON.parse(word_array);, it throws an error saying Uncaught SyntaxError: Unexpected identifier. Upon investigating, I discovered that the object word_array is miss ...

Installing assets automatically in Netbeans for Symfony2

Whenever I test my application, I find myself having to run the following command in Netbeans: assets:install Repeating tasks gets quite tedious... Symfony2 requires running this command to ensure that modified files are placed in the correct location. ...

Assigning the value of a variable to the name of another variable in JavaScript and Vue.js

I am dealing with 2 JSON arrays "feeds":[ { "created_at":"2021-11-28T00:11:38Z", "entry_id":17901, "field1":"16.40000", "field2":"45.50000", "fi ...

Safari: Height of 100% not functioning as expected

Currently, I have a div with the class of "signup-login-forms" that is set to have a height of 40vh and span 100% of the browser width. Inside this div are two forms positioned next to each other. The goal is to have both forms fill the entire height of th ...

send a message to all clients using socket.io

I am having trouble figuring out how to broadcast a message from the client or another NodeJS file to all clients. While I was able to send messages to the server successfully, I am not able to reach every other client. Server code: var io = require(&ap ...

What steps can be taken to enlarge the select button within a <select> field?

Is there a way to enlarge the size of the downward-pointing arrow button within a <select> element? Here is an example of what my code looks like: <select> <option>Select City</option> <option>City1</option> <o ...

Problem occurring with Bulma CDN version 0.8.0 failing to identify the spacing helper

Recently revisited an older project I had started some time ago using the Bulma framework. However, for some reason, the 0.8.0 CDN is not being imported or recognized correctly by the spacing classes. Here's the code snippet I had initially: <link ...

Why is Google Chrome cutting off parts of my website?

Has anyone encountered the strange rendering issue in Google Chrome? Check out this bug here http://community.mediabrowser.tv/uploads/site_1/126/annoying_rendering_bug.jpg I sometimes experience it when I visit What is causing this issue? Is there a way ...

Issue with React application failing to transmit files to PHP server using Ajax

I recently set up a react app on my Apache server and decided to use the react-images-upload npm package for handling user images in conjunction with Axios to post to my PHP server. However, I encountered an issue where the $_FILES array in the PHP respons ...

Steps to improve the appearance of the Header on a dataTable during Dragging

I am working on creating a table that can be reordered using mat-table and MatTableDataSource. However, I would like the column to have a white background color instead of being transparent when dragged. Is there a way to achieve this? <table mat-tab ...

JavaScript has issues with undefined array elements

Even though there is data in bindInfo, the array elements in Bind are showing as undefined. Any recommendations? let bindinfo = { clientid: 1, clientname: 'Web Client', nowutc: now_utc, bindlist: Bindings(this.props.bindDetails) ...

Storing information in a session within a callback function using Node.js Express

Within the following code snippet, my goal is to retrieve user information from the database and store it in a session. However, I am encountering an issue where the data is not being properly saved into the session variable as expected. Could this be du ...

Creating a form with multiple checkboxes using Material-UI components where only a single checkbox can be selected

Creating a simple form using Material-UI with checkboxes to select one option and push data to the backend on submit is the goal. The Form component structure includes: multiple options represented by checkboxes only one checkbox can be selected at a time ...

Show the table header at all times, even when the rows are hidden from view

Whenever the number of rows in my dynamic table changes due to user events, all tr elements that do not have the class .selected are set to display:none;. This means that at times, none of the table rows have the class selected. The problem arises when I h ...

Selenium on Sauce Labs does not successfully load the page in Firefox after clicking

An issue has arisen where a test that functions properly with selenium webdriver locally is timing out when executed remotely on saucelabs.com. Notably, the test runs smoothly for Chrome in both local and remote scenarios. The problem seems to lie in the ...

Bootstrap SideBar (Template): I desire for the sidebar to expand in the content area without the need for lengthy paragraphs below

After following an online tutorial to create a visually appealing sidebar, I made some adjustments to the code using Bootstrap 4 instead of the tutorial's Bootstrap 3. However, I encountered an issue where the navbar does not stretch to the right as e ...

Strategies for Resolving CORS Issues in React and Node/Express

Previously, my project was working fine with React in the frontend and a node/express server in the backend. However, I am now encountering a CORS error. The error message states: Access to fetch at 'https://dry-reef-22080.herokuapp.com/imageUrl&apos ...

Generate dynamic concentric rings with either CSS, Canvas, or SVG for a fluid and scalable design

Looking to create a graph similar to these examples: http://bl.ocks.org/cmdoptesc/6228457 or like this Wanting the graph to be able to scale based on browser width without using javascript if possible. Ideally, looking for a CSS-only solution, but open ...

Adjusting the width of columns in a flex layout using Bootstrap 4

On mobile, I am attempting to rearrange some elements in a different order. Currently, this is what I have: https://i.stack.imgur.com/fY3PQ.png Below is the HTML code: <main> <div data-color="yellow"></div> <div class="wrapper"& ...