By now, one would think there would be an easier way to transition between the visibility of an object on a page with all of the CSS and SASS tricks at the ready. Unfortunately, it is a bit frustrating to navigate this area. Between visibility
and display
, there is not one perfect way to transition an element smoothly without JavaScript. When and where the element is able to simply fade out a container to show another below can be tricky especially if elements should no longer be truly displayed for screen readers, selecting elements, and accidental invisible button clicks. First I will walk us through the three ways to hide content and finish with an example utilizing JavaScript to transition an element’s visibility and then truly disable the display.
Visibility
Adding visibility: hidden;
to a container’s style will definitely hide it from the end user. It also works very well with CSS transitions. Unfortunately, it retains the width and height of the container while also blocking any other objects underneath. The container’s children are still selectable and viewable by screen readers.
Display
The JavaScript-friendly style attribute is display: none;
which fully hides the container. While visibility
means that the contents of the element will be invisible, but the element stays in its original position and size. Display hides the element — including all of it’s contents — from screen readers as well as removing width and height from the container.
Content Visibility
Another approach is rendering the contents of a container with a newer CSS feature, content-visibility: hidden;
. It allows the frontend develoepr to omit large swaths of layout rendering and load on the DOM until it is visible. It enables the user agent to skip an element's rendering work (including layout and painting) until it is needed — which makes the initial page load much faster.
Timeout Transition
For this to function in React, typically there will be a handler on a select
onChange event and the variable event would be passed into the function so we can call upon e.target.value
, the value of the current select
field. Our main component is the function chooseFilter
which applies both visibility
and opacity
styles to our objects. The setTimeout
function is transitioning our styles and applying position: absolute
before revealing the selected option. This allows us to truly hide the elements and gives space for the visible cards to wrap since we are not using display
for this example. You can also see the full CSS where transition: 0.2s 0s all ease-in-out;
was added to each card
within the entire cardBlock
container.
chooseFilter(e) {
let cards = document.querySelectorAll('#cardBlock .card')
cards.forEach(card => {
card.classList.add('filtered')
setTimeout(() => {
card.classList.add('absolute')
}, 300)
})
cards.forEach(card => {
if (!card.getAttribute('data-type').includes(e.target.value)) {
card.classList.add('filtered')
setTimeout(() => {
card.classList.add('absolute')
}, 300)
} else {
setTimeout(() => {
card.classList.remove('filtered')
card.classList.remove('absolute')
}, 300)
}
})
}
Here you can see the full function in action with basic HTML/CSS and JavaScript.