Enigmatic void appears above row upon removal of content from a single item

When I click on an item in my grid, the content of that item is moved to a modal. The modal functions properly, but I noticed that when the content is removed from the item, a space appears above it.

I have found that using flexbox could solve this issue, but I am curious about understanding the underlying cause.

One key detail is that each item has three children - two with position: absolute and one without a specific position.

It seems that setting all children to position: absolute resolves the problem, but I want to know why there is a difference in outcome based on the content being present or not.

You can see the problem in action in this JSFiddle.

HTML Structure:

<div class="context">
    <div class="grid">
        <div class="item">
            <div class="cover">  // has position: absolute
                <h1>Title</h1>
            </div>
            <div class="img-wrapper">  // has position: absolute
                <img/>
            </div>
            <div class="description">  // doesn't have a position defined
                <p>Description...</p>
            </div>
        <div class="item">
            // item content
        </div>
    </div>
</div>

The grid contains 8 items divided into two rows of 4 items each.

CSS Styling:

To achieve this layout, the following CSS rules are applied:

.grid {
  margin-top: 100px;
  font-size: 0; // to get all the items together
  border: 1px solid red;
}

.item {
  width: calc(100% / 4);
  height: 100px;
  position: relative;
  display: inline-flex;
}

.description {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  top: 0;
  bottom: 0;
}

.img-wrapper {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

img {
  height: 100%;
  width: auto;
  display: block;
  margin: auto;
}

.cover {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

Note: Additional CSS styling in the JSFiddle example does not affect the core structure causing the issue.

JavaScript Functionality:

The JavaScript code responsible for moving content to the modal is as follows:

let $itemNode;
let $itemContent;

$().ready(args => {
  let $modal = $('#modal');

  $('.item').click(function() {
    $itemNode = $(this);
    $itemContent = $(this).children();

    $itemNode.css({visibility: 'hidden'});

    $itemContent.appendTo($modal);
  });

});

Answer №1

Solutions

To overcome this issue, one effective solution involves utilizing flexbox...

Indeed, the problem can be resolved by setting the parent of the items as a flex container:

.grid {
  display: flex;     /* new */
  flex-wrap: wrap;   /* new */
  margin-top: 100px;
  font-size: 0;
  border: 1px solid red;
}

See updated fiddle

An important note here is that each item consists of 3 children. By applying position: absolute to two of them and leaving the third with its default position, the issue is resolved.

Similarly, removing the third div from the document's normal flow effectively eliminates the problem.

Explanation

Initially, each item in the grid is artificially positioned before any alterations are made through scripting.

In essence, the contents of the items (the three child divs) cause a shift in each item's position. However, when these child divs are removed by the script, the items move to their correct locations.

The root of the problem lies within the third child div of each grid item (.description).

When you add visibility: hidden to the grid item without removing the child divs, the layout remains intact. But your script not only hides the visibility but also removes the child divs entirely.

The first two divs (.cover and .img-wrapper) do not cause issues as they are already absolutely positioned and out of the regular flow.

On the other hand, the third div (.description) is an inline child.

With two p children inside ("Description for this item X" and "More info"), the removal of either child disrupts the layout.

This disruption occurs because the div suppresses vertical-align: baseline on the inline-level parent element, causing a gap when removed.

It appears that using values other than baseline for vertical-align solves the issue, as pointed out by @Kukkuz in another answer.

Answer №2

Utilize the style rule vertical-align: top for the item class in order to eliminate any unwanted spacing when the content of an item is empty. This issue arises due to the fact that the items within the grid are displayed as inline elements (inline-flex).

Note that the property vertical-align is applicable to all inline-level and table-cell elements, serving to vertically align inline level elements - further details can be found in the documentation here.

By changing the display property from inline-flex to inline-block, you will observe a similar behavior. Experiment with toggling the vertical-align property through the snippet provided below:

.context {
  text-align: center;
  height: 400px;
  border: 1px solid black;
}
#modal {
  display: none
}
.grid {
  margin-top: 100px;
  font-size: 0;
  border: 1px solid red;
}
.item {
  width: calc(100% / 4);
  height: 100px;
  transform-origin: center;
  position: relative;
  display: inline-flex;
  transition: box-shadow .3s, transform .3s;
  font-size: 1em;
  vertical-align: top;
}
.description {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  top: 0;
  bottom: 0;
  z-index: 100;
  opacity: 0;
  background-color: rgba(0, 0, 0, 0.6);
  color: white;
  padding: 20px;
  transition: opacity .3s;
}
.img-wrapper {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: white;
}
img {
  height: 100%;
  width: auto;
  display: block;
  margin: auto;
}
.cover {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
  z-index: 1000;
  cursor: pointer;
  opacity: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: bold;
  text-align: center;
  color: white;
  transition: transform .3s, opacity .3s;
}
.cover-red {
  background-color: #ff9f80;
}
.cover-green {
  background-color: #66cc66;
}
.cover-blue {
  background-color: #809fff;
}
.cover-yellow {
  background-color: #ffff80;
}
.cover-mag {
  background-color: hsl(338, 95%, 70%);
}
.cover-cyan {
  background-color: hsl(214, 100%, 65%);
}
.item:hover {
  box-shadow: 0 0 6px 3px rgba(0, 0, 0, 0.3);
  z-index: 1100;
  transform: scale(1.02);
}
.item:hover .cover {
  opacity: 0
}
<div class="context">
  <div class="grid">
    <div class="item">


    </div>

    <div class="item">
      <div class="cover cover-cyan">
        <h1>Title 2</h1>
      </div>
      <div class="img-wrapper">
        <img src="http://rs415.pbsrc.com/albums/pp236/Keefers_/Keffers%20Animals/funny-cats-a10.jpg~c200">
      </div>
      <div class="description">
        <p>Description for item 2</p>
        <p>More info</p>
      </div>
    </div>

    <div class="item">
      <div class="cover cover-mag">
        <h1>Title 3</h1>
      </div>
      <div class="img-wrapper">
        <img src="http://i1.kym-cdn.com/entries/icons/original/000/007/203/nononocat.jpg">
      </div>
      <div class="description">
        <p>Description for item 3</p>
        <p>More info</p>
      </div>
    </div>

    <div class="item">
      <div class="cover cover-green">
        <h1>Title 4</h1>
      </div>
      <div class="img-wrapper">
        <img src="https://media0.giphy.com/media/3o85xoi6nNqJQJ95Qc/200_s.gif">
      </div>
      <div class="description">
        <p>Description for item 4</p>
        <p>More info</p>
      </div>
    </div>

    <div class="item">
      <div class="cover cover-cyan">
        <h1>Title 5</h1>
      </div>
      <div class="img-wrapper">
        <img src="https://media0.giphy.com/media/o0vwzuFwCGAFO/200_s.gif">
      </div>
      <div class="description">
        <p>Description for item 5</p>
        <p>More info</p>
      </div>
    </div>

    <div class="item">
      <div class="cover cover-green">
        <h1>Title 6</h1>
      </div>
      <div class="img-wrapper">
        <img src="http://cdn.thecatsite.com/3/37/200x200px-ZC-379ffbad_anime-cat-cute-cuteness-overload-kitten-Favim_com-350157_large.jpeg">
      </div>
      <div class="description">
        <p>Description for item 6</p>
        <p>More info</p>
      </div>
    </div>

    <div class="item">
      <div class="cover cover-red">
        <h1>Title 7</h1>
      </div>
      <div class="img-wrapper">
        <img src="http://www.officialstarwarscostumes.com/~/media/products/oc/yoda-costumes/pet-yoda-costumes/9935319-yoda-cat-hood-pet-star-wars-costumes-000.ashx?w=200&h=200&bc=ffffff">
      </div>
      <div class="description">
        <p>Description for item 7</p>
        <p>More info</p>
      </div>
    </div>

    <div class="item">
      <div class="cover cover-mag">
        <h1>Title 8</h1>
      </div>
      <div class="img-wrapper">
        <img src="http://adst.org/wp-content/uploads/2014/02/cat-general-120-3-_tplq-200x200.jpg">
      </div>
      <div class="description">
        <p>Description for item 8</p>
        <p>More info</p>
      </div>
    </div>
  </div>
  <div id="modal">
  </div>
</div>


I have constructed a demonstration utilizing inline-block which showcases the same behavior. This behavior is commonly seen among inline elements - please refer to the example below:

.wrapper {
  border: 1px solid;
}
.wrapper > * {
  display: inline-block;
  border: 1px solid;
  height: 100px;
  width: 100px;
}
<div class="wrapper">
  <div></div>
  <div>
    <h1>kjk</h1>
  </div>
</div>

Answer №3

The reason for this issue is the use of visibility:hidden. While visibility:hidden hides the visibility of an element, it still takes up space on the page. Instead, you should utilize display:none; as it completely removes the element from the layout.

https://example.com/jsfiddle-link

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

animation of leaping to a specific element

I am currently working on a sidebar with links that have a hover effect to add a bullet. However, I want the bullet to smoothly follow the cursor's movement along the y-axis within the sidebar instead of jumping between the links. How can I achieve th ...

Creating a 2D Image Display in three.js

I'm facing a challenge with my threejs project. My goal is to have a 2D image appear on the screen when I press a key. I've done some research but haven't been able to find a solution that works for me. The methods I've tried either don ...

The issues of cross-origin domains arise when utilizing iframes with src links originating from the server side

Encountering a cross-origin domain issue, receiving the following error while working with an iframe: candidateInterviewCtrl.js:39 Uncaught SecurityError: Blocked a frame with origin "http://localhost:9000" from accessing a frame with origin "http://local ...

Sass: Overcoming the challenge of the IE limitation on 4095 selectors per stylesheet

Hey there! Are you working on a Rails project with Sass & Compass? If you're using the Rails Asset Pipeline, check out this question. We're in the process of developing a large application with multiple use cases and various individually styled ...

Go back to the pop-up window if an error occurs

I've implemented a modal window in front of my index page. When the model is valid, I redirect to the index view. However, when the model is not valid, I want it to stay on the modal. How can I achieve this? [HttpPost] [ValidateAntiForgeryToken] publ ...

What could be causing the menu to not align in the center?

Take a look at the HTML code below: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="v ...

Is it possible to dynamically insert a ng-mouseover in AngularJS using Javascript?

It seems like there is an issue with this code: var run_div = document.createElement('div'); run_div.className = 'whatever'; run_div.textContent = 'whatever'; run_div.setAttribute('ng-mouseover', 'console.log(&b ...

Ways to retrieve several parameters from a controller using Ajax Jquery in Codeigniter

I need to retrieve a list of images from a folder based on a specific ID. Currently, I am able to get the file names but I also require the upload path. Is there a way to obtain both sets of data using a single function? Javascript Code: listFilesOnServ ...

Utilizing App Script for Filtering Data with Multiple Criteria

Having trouble transferring data from a data sheet to my report sheet using multiple criteria for matching. I wrote some code that worked, but it's returning all data instead of filtering by criteria. I want the function to search for column criteria ...

Utilize jQuery to alter the presentation in a distinct field

Whenever a checkbox is clicked, it updates a display field. I want to capture the content of this display field and also show it in another display field. Ideally, the second field, which is a total field, would add or subtract the value from the first fie ...

The Markup() function in Flask is used to generate markup content that is not enclosed within

Before I explain my issue, let me go ahead and share the code with you. Using Jinja in HTML <p>{{ item }}</p> 'Flask' item = Markup('<ul><li>list item 1</li><li>list item 2</li></ul>') ...

Dynamic Formatting with Vue JS: Enhancing Phone Number Input

I am working on a form that includes a phone number input field, and I want the formatting of the number to change to a standard telephone number format as the user types. Can someone provide guidance on how this can be achieved using JavaScript and Vue 3? ...

unable to clear form fields after ajax submission issue persisting

After submitting via ajax, I am having trouble clearing form fields. Any help in checking my code and providing suggestions would be greatly appreciated. Here is the code snippet: jQuery(document).on('click', '.um-message-send:not(.disabled ...

initiate an animated sequence upon the initialization of the Angular server

Is there a way to launch a Netflix animation after my server has started without success using setTimeout? I don't want to share the lengthy HTML and CSS code. You can view the code for the animation in question by visiting: https://codepen.io/claudi ...

Should the refresh button be displayed once the animation finishes?

Can anyone provide guidance on how to write jQuery code that will reveal a hidden button after an animation is finished? The button should also be able to refresh the animation for the user to watch again. Check out this fiddle: http://jsfiddle.net/rabela ...

What is the method for altering the date format of a published article?

I am looking to modify the date format of a published post in WordPress. Currently, the date format is <?php the_time('m.d.y'); ?></div>, which appears as "1.20.2018". My goal is to change it to "January 20, 2018". Can anyone guide ...

Setting an interval for a specific function to trigger after a delay of 5 seconds

I'm struggling with setting an interval for the $.get ajax method in my code. Take a look at what I have so far... setInterval(function () { passFunction(jsonData); } ,5); $.get({ url: 'pass.php', success: ...

JQuery Datatables: Struggling to make JQuery function work following AJAX update

Watch this screencast to get a clearer understanding of the issue.... I'm currently working on my first project involving AJAX, and I'm encountering some obstacles. The datatable is loading user details from a JSON output using AJAX. Each row ...

Angular 17 | Angular Material 17.3.1: Problem encountered with Angular Material form field focus and blur event handling

I attempted to apply (blur) and (focus) effects to my mat-form-field input field, but it seems like they are not working properly on my system. Here is a code snippet that resembles what I am using: html file <form class="example-form"> ...

How to retrieve the form ID in jQuery using the input ID?

I have a simple question: How can I retrieve the form id using the input element id? <form id="my_form"> <fieldset> <!--some <div>'s--> <input id="my_input"></div> <!--some <di ...