I try to build "read more/less" functionality with fade in/out text.
Since CSS transitions do not work on height: auto;
, I am forced to hardcode the value in CSS with my approach. Which could be too small or too big. The fade-in text can vary in length from element to element where the JS will be applied on.
I can read the real height of the <p id="txt">
element which includes the transparent text before any css is applied:
document.addEventListener("DOMContentLoaded", function(event) {...});
So I know about the height I need to transform to before the toggle happens but I can't figure out a way to make it work. Is this even possible with my approach?
Changing the height
property right after the toggle with currentText.style.height = realHeight + "px";
does not work since it's too late here.
document.addEventListener("DOMContentLoaded", function(event) {
// Get the height including the transparent text
var realHeight = document.getElementById("txt").scrollHeight;
var heightDisplay = document.getElementById("realHeight");
heightDisplay.innerHTML += realHeight + "px";
});
const btn = document.querySelector(".read-more-btn");
const text = document.querySelector(".read-more");
const wrapper = document.querySelector(".wrapper");
wrapper.addEventListener("click", e => {
const current = e.target;
const isReadMoreBtn = current.className.includes("read-more-btn");
if (!isReadMoreBtn)
return;
const currentText = e.target.parentNode.querySelector(".read-more");
currentText.classList.toggle("read-more_open");
// currentText.style.height = realHeight + "px";
current.textContent = current.textContent.includes("Read More") ? "Read Less" : "Read More";
});
/* toggle classes */
.read-more {
display: block;
opacity: 0;
height: 0;
transition: all 0.5s;
}
.read-more_open {
display: block;
opacity: 1;
height: 5em;
}
/* other styles */
.wrapper {
width: 20rem;
background-color: black;
color: white;
margin: auto;
}
.contents {
padding: 0.25rem;
}
.title {
font-size: 1.7em;
margin-bottom: 1rem;
letter-spacing: 1px;
}
p {
font-size: 0.8rem;
}
.read-more-btn {
display: inline-block;
color: white;
background-color: grey;
padding: 0.6rem 1.5rem;
font-size: 1em;
position: relative;
z-index: 1;
transition: all 0.5s;
cursor: pointer;
}
.read-more-btn:hover {
background-color: #fff;
color: grey;
box-shadow: 0 0 2 rem rgba(0, 0, 0, 0.1);
transform: translateY(-3px);
}
<span id="realHeight">Real height: </span>
<div class="wrapper">
<div class="contents">
<h1 class="title">Some Title</h1>
<p id="txt">
ALWAYS VISIBLE CONTENT
<span class="read-more">
Fade in text with an unknown length which results in the unknown height of the paragraph. Fade in text with an unknown length which results in the unknown height of the paragraph. Fade in text with an unknown length which results in the unknown height of the paragraph. Fade in text with an unknown length which results in the unknown height of the paragraph. Fade in text with an unknown length which results in an unknown height of the paragraph.
</span>
</p>
<p class="read-more-btn">Read More</p>
</div>
</div>
` ?
` element taken ? Is there a reason for working with the wrappers height instead of the `
` ?
– Sep 19 '21 at 14:06