croraf
croraf

Reputation: 4728

Why do images in a block element not strictly respect height: 0

Check the following component (live example shown in this snippet https://codesandbox.io/s/reverent-mccarthy-r3v93?file=/src/App.tsx):

import * as React from "react";

export default function App() {
  const [indexOfDiagnosis, setIndex] = React.useState(0);

  return (
    <div>
      <button onClick={() => setIndex(indexOfDiagnosis + 1)}>click</button>
      <div>
        {[1, 2, 3, 4, 5, 6, 7].map((_, index) => (
          <img
            key={index}
            alt={"asd"}
            src={
              index % 2
                ? "https://images.unsplash.com/photo-1563630381190-77c336ea545a?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1872&q=80"
                : "https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"
            }
            width="80%"
            height="80%"
            style={{ height: index !== indexOfDiagnosis ? "0px" : undefined }}
          />
        ))}
      </div>
    </div>
  );
}

It shows a list of images, where all but one have height: 0 (these are implicitly hidden).

But, when you click the button to iterate through them, further images are shown with a top offset (as if the previous images still take some space). Why is this happening?

NOTE 1: In devtools the height, padding, border and margin of each "invisible" image is shown as 0.

NOTE 2: Also by setting the parent div to display: flex; flex-direction: column this offset bug does not happen.

Upvotes: 0

Views: 120

Answers (2)

Matthew Dangle
Matthew Dangle

Reputation: 416

How to Fix
Most browser user agents will render img as a display inline-block. White-space will be added in between inline and inline-block elements if space exists between the HTML coding brackets.

To solve your problems the quickest way is to set each img element to display block.

Alternatively, here is how to remove space between inline elements: How do I remove the space between inline/inline-block elements?

img {
  width: 100px;
}
.block {
  display: block;
}
<!-- Defualt -->
<p> Default </p>
<img src="https://images.unsplash.com/photo-1563630381190-77c336ea545a?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1872&q=80"/>
<img src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"/>

<!-- Display Block -->
<p> Display Block </p>
<img class="block" src="https://images.unsplash.com/photo-1563630381190-77c336ea545a?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1872&q=80"/>
<img class="block" src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"/>

<!-- No Whitespace -->
<p> No Whitespace </p>
<img src="https://images.unsplash.com/photo-1563630381190-77c336ea545a?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1872&q=80"/><img src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"/>

Additional Suggestions
Instead of using the height: 0; property to hide an element, might I suggest using display: none; instead? This will truly hide it from the DOM. To unhide it from the DOM, set it to display: block;. About the Display Property

Of course, if you plan on working with animations, I would use the visibility property instead. About the Visibility Property

Another solution is to simply wipe the element off by setting both the width and height to 0 when not being used. Remove the attribute width and height and apply it to the style.

style={
  { 
    width: index !== indexOfDiagnosis ? "0px" : "500px",
    height: index !== indexOfDiagnosis ? "0px" : "200px" 
  }
}

Upvotes: 2

0stone0
0stone0

Reputation: 44162

Setting the height of an image to 0 isn't enough to 'hide' it from the DOM.

The most common way to hide an image is to use display: none as described here.

style={{ display: index === indexOfDiagnosis ? "block" : "none" }}

Updated sandbox


EDIT: Since OP is looking for a solution without display:none, here an example using the provided height: 0px together with an font-size: 0px on the parent element to prevent any space between the blocks.

<div style={{ fontSize: "0px" }}>

How do I remove the space between inline/inline-block elements?

Updated sandbox

Upvotes: 2

Related Questions