Skip to content

Instantly share code, notes, and snippets.

@richardscarrott
Last active December 30, 2023 00:37
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save richardscarrott/6457438 to your computer and use it in GitHub Desktop.
Save richardscarrott/6457438 to your computer and use it in GitHub Desktop.
Fading an element in from display: none; with CSS transitions.
.box {
display: block;
background: red;
width: 200px;
height: 200px;
opacity: 1;
}
.box-hidden {
display: none;
}
/* ensure box is displayed block during the transition */
.box-transition.box-hidden {
display: block;
opacity: 0;
}
.box-transition {
transition: opacity 1s ease;
}
<div class="box">
</div>
<button class="button">Toggle Box</button>
document.addEventListener('DOMContentLoaded', function() {
var box = document.getElementsByClassName('box')[0],
button = document.getElementsByClassName('button')[0];
button.addEventListener('click', function(e) {
if (box.classList.contains('box-hidden')) {
// show
box.classList.add('box-transition');
box.clientWidth; // force layout to ensure the now display: block and opacity: 0 values are taken into account when the CSS transition starts.
box.classList.remove('box-hidden');
} else {
// hide
box.classList.add('box-transition');
box.classList.add('box-hidden');
}
}, false);
box.addEventListener('transitionend', function() {
box.classList.remove('box-transition');
}, false);
});
@patcaulfield
Copy link

Thanks for your tip.
I have a question about this source.
I want to use opacity when I load first time. In this source display block is not work. How can I fix?

@bryanbraun
Copy link

This worked so much better than my janky setTimeout solution. Thank you!

@labbots
Copy link

labbots commented Jul 21, 2020

@richardscarrott I am trying to adopt your idea into my project to display a hidden div but the div is supposed to be hidden on page load and then displayed on toggle. I want to make the box display to none on page load and then transition to view on toggle button. I cannot add box-hidden class on page load as it interferes with the media query. I am trying to do something like this

.box-two {
  display: none;
  background: red;
  width: 200px;
  height: 200px;
  opacity: 0;
}

.box-active {
  display: block;
  opacity: 1;
}

/* ensure box is displayed block during the transition  */
.box-transition.box-active {
  display: block;
  opacity: 0;
}

.box-transition {
  transition: opacity 1s ease;
}
document.addEventListener('DOMContentLoaded', function() {
	var box = document.getElementsByClassName('box-two')[0],
	    button = document.getElementsByClassName('button2')[0];

	button.addEventListener('click', function(e) {
		if (box.classList.contains('box-active')) {
                  // hide
                    box.classList.remove('box-active');
		    box.classList.remove('box-transition');
		} else {
                  // show
                  box.classList.add('box-active');
                  box.clientWidth;
                  box.classList.add('box-transition');
		}
	}, false);

	box.addEventListener('transitionend', function() {
        console.log("transition 2")
		box.classList.remove('box-transition');
	}, false);
});

But I cant seam to workout how to get this functional. Could you please provide some pointers on where my mistake is.

@labbots
Copy link

labbots commented Jul 22, 2020

I finally managed to change the script so that the box is hidden at start and then displayed on click of the toggle button.

HTML

<div class="box">
</div>
<button class="button">Toggle Box</button>

CSS

.box {
  display: none;
  background: red;
  width: 200px;
  height: 200px;
  opacity: 0;
}

.box-visible {
  display: block;
}
.box-active {
  display: block;
  opacity: 1;
}
.box-transition.box-visible {
  display: block;
  opacity: 1;
}
.box-transition {
  transition: opacity 0.5s ease;
}
.box-hidden {
  display: block;
  opacity: 0;
}

JavaScript

document.addEventListener("DOMContentLoaded", function () {
    var box = document.querySelector(".box"),
    button = document.querySelector(".button");

  button.addEventListener(
    "click",
    function (e) {
      if (box.classList.contains("box-active")) {
        // hide
        box.classList.remove("box-active");
        box.classList.add("box-transition");
        box.classList.add("box-hidden");
      } else {
        // show
        box.classList.add("box-visible");
        box.clientWidth;
        box.classList.add("box-transition");
        box.classList.add("box-active");
      }
    },
    false
  );

  box.addEventListener(
    "transitionend",
    function () {
      box.classList.remove("box-transition");
      box.classList.remove("box-visible");
      box.classList.remove("box-hidden");
    },
    false
  );
});

Not sure whether this is efficient way to do it but it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment