Animating the height of a container with unspecified initial and final heights using CSS transformations

I am faced with a challenge in styling a container that dynamically changes its height based on the content it holds. The issue arises when I want to add a transition effect to this dynamic height change. Since the height is determined by the changing text content, I cannot set an initial height for the container. Both the text and the resulting height are unpredictable. As of now, my current code does not include any transitions for the height adjustments of the container. Below is a basic example to illustrate my dilemma.

Take a look at the Component:

import React, { Component } from "react";

export default class Test extends Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "Item 2",
    };
  }

  changeText = () => {
    this.setState({
      text:
        "A much longer text@@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@ @@@@@ @@@@ @@@@@@ @@@@ @@@@@ @@@@@@     @@@@@@@ @@@@@@@@@@ @@@@ @@@@ @@@@@@@@@@@@@@@!",
    });
  };

  render() {
    return (
      <div>
        <div className="text">
          <div className="item1">Item 1</div>
          <div className="item2">{this.state.text}</div>
          <div className="item3">Item 3</div>
        </div>
        <button onClick={this.changeText}>Click</button>
      </div>
    );
  }
}

And here is the corresponding CSS:

.text {
  background-color: yellow;
  max-width: 300px;
  transition: all 3s ease-out;
}

Answer №1

To make the item hidden until needed, you can wrap it in a paragraph element and adjust the div height to 0 while hiding the overflow. Once the text is added, set the div height to match the paragraph's height.

<!DOCTYPE html>
<html>
  <head>
  <title>ok.</title>
  <style>
      div {
        outline: 1px solid black;
        transition-property: height;
        transition-duration: 1s;
        height: 0;
        overflow: hidden;
      }
      p {
        margin:0;
      }
  </style>
  </head>
  <body>
    <div>
      <p>Item 1</p>
    </div>
    <button id="button1">insert short</button>
    <button id="button2">insert long</button>
    <script>
      let div = document.getElementsByTagName("div")[0]
      let para = document.getElementsByTagName("p")[0]
      let button = document.querySelector("#button1")
      button.addEventListener("click", function() {
            para.innerHTML ="oneliner"
            div.style.height = para.scrollHeight +"px"
      })
      let button2 = document.querySelector("#button2")
      button2.addEventListener("click", function() {
            para.innerHTML ="tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, \
            quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo \
            consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse \
            cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non \
            proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
            div.style.height = para.scrollHeight +"px"
      })
    </script>
  </body>
</html>

Answer №2

One technique involves setting the text content first, followed by adjusting the style to have a maximum height equal to the scroll height;

To demonstrate, whenever you click on ADD, additional text is appended to increase its height.

var btn = document.querySelector(".add");

btn.addEventListener("click",function(){
  var _text = document.querySelector(".text");
  _text.innerHTML += "text<BR><BR>adsad<br>sadasd";
  _text.style.maxHeight = _text.scrollHeight + "px";
});
.text {
  background-color: yellow;
  max-width: 300px;
  transition: all 1s ease-out;
  max-height:0;
}
<button type="button" class="add">Add</button>
<div class="text"></div>

Answer №3

Attempted some modifications in hopes of resolving the issue, but unfortunately it still persists...

import React, { Component } from "react";

export default class Solution extends Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "Item 2"
    };
  }

  componentDidMount() {
    const height = this.divElement.clientHeight;
    this.divElement.style.maxHeight = height + "px";
  }

  modifyText = () => {
    this.setState(
      {
        text:
          "A much longer text@@@@@@@ @@@@@@@ @@@@@@ @@@@@@@@ @@@@@ @@@@ @@@@@@ @@@@ @@@@@ @@@@@@ @@@@@@@ @@@@@@@@@@ @@@@ @@@@ @@@@@@@@@@@@@@@!",
      },
      () => {
        this.divElement.style.maxHeight = null;
        const height = this.divElement.clientHeight;

        this.divElement.style.maxHeight = height + "px";
      }
    );
  };

  render() {
    return (
      <div style={{ margin: "200px" }}>
        <div
          ref={(divElement) => {
            this.divElement = divElement;
          }}
          className="text"
        >
          <div className="item1">Item 1</div>
          <div className="item2">{this.state.text}</div>
          <div className="item3">Item 3</div>
        </div>
        <button onClick={this.modifyText}>Click</button>
      </div>
    );
  }
}

Additionally, uncommenting the max-height property in .text leads to undesired outcomes as I intend for the container's height not to be set to 0px;

.text {
  background-color: yellow;
  max-width: 300px;
  transition: all 3s ease-out;
  // max-height: 0;
}

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

How can I retrieve the value of the Material UI pickers in my component?

How can I retrieve the value in a component after selecting a date from the date picker? Demo Link: https://material-ui.com/demos/pickers/ Here is an example: import React from 'react'; import PropTypes from 'prop-types'; import { wi ...

What is the best way to retrieve the most recent CMS posts information within a Gatsby-constructed project?

I created a static website using Gatsby and everything was working well. However, I encountered an issue when updating the titles and content of posts in Contentful CMS - the changes were not reflected when I refreshed the website. How can I ensure that ...

Resize Font Awesome icons dynamically based on screen size changes

Currently working on creating a footer that includes social media icons from Font Awesome. However, I've come across an issue where resizing the desktop size for tablet or mobile screens causes the icons to shrink, which is not ideal. If anyone has a ...

While creating a React app, Docker becomes stuck due to a hangup when checking the core-js dependency

I've hit a roadblock in the build process. I'm working on an M1 Mac Mini and have attempted to build in both arm64 and x86_64 terminals, but the outcome is consistently the same. npm info lifecycle @babel/<a href="/cdn-cgi/l/email-protection" ...

Column division shifting beneath the column division that has the greatest height above

I'm currently using a PHP loop to generate and showcase articles (as 'col' divs) from the MySQL database. However, when I use 3 "col-6" divs, the 3rd one ends up moving below the other two instead of staying right next to the first div. Any ...

Guide on ensuring the client waits for authorization state to load before requesting data

Recently, I discovered the useAuth and useRequireAuth hooks which can be found at . These hooks are extremely valuable for client-side authentication. However, I'm curious about the best approach to wait for authentication data before fetching additio ...

Different ways to display array elements in List Item Text

Recently I started working with React and I'm using ListItemText to display values on the screen. My query is how can I utilize ListItemText to display all the elements of an array in a list. Below is the code snippet where Kpi_Before represents the ...

What could be causing my SVG bezier curves to malfunction in Firefox?

Encountered an issue today where diagrams I have generated are not functioning properly in Firefox when created using the getPointAtLength method. Here is a demonstration of the problem: http://jsfiddle.net/xfpDA/9/ Please take note of the comments at th ...

Is there a way to merge two :not() selectors together?

Attempting to achieve the following: :not(h1) > a, :not(figure) > a { background: #859900; } Encountering an issue as figure>a is matching with :not(h1)>a, and h1>a is matching with :not(figure)>a. How can I merge these selectors? ...

limitations on passing url parameters in react.js

Currently, I am facing an issue with passing URL parameters in my React.js web app. For illustration purposes, here is a snippet of the routes: import React from "react"; import {BrowserRouter, Route, Switch, Redirect} from 'react-router-dom'; ...

The shade of grey on the curve appears instead of the usual red on the iPad. Any ideas on how to fix

I am having trouble creating a curve like the one shown below on my iPad. The color appears to be gray and does not work properly. Is this a bug with ChartJS or is there a solution to fix this issue? This problem occurs when the type value is set to "lin ...

The npm start command is failing to display the page when using node and reactJS

I'm currently working on a simple web page using NPM and react. Here is the code for my index.html file: <html lang="en"> <head> <meta charset="utf-8"> <title> React Page </title> </head> <body> ...

What is the best way to incorporate a PHP variable into my Jquery image slider?

I've been experimenting with a Jquery Image slider and I'm interested in enhancing it further. My goal is to display two divs when the full-size image loads, one containing an image title and the other providing a description of the picture. How ...

Customize HTML styles using Angular Material

I've noticed that my index.html file has a lot of style elements when using Angular Material, and I'm not sure why. Here's an example in the header element where different classes are used for Angular Material components. https://i.sstatic. ...

Displayed in the xmlhttp.responseText are the tags

Why do tags appear when I input xmlhttp.responseText into my textbox? It displays <!DOCTYPE html><html><body></body></html> along with the desired content. Is there a way to prevent the tags from being displayed? Here is the ...

Tips for successfully sending an interface to a generic function

Is there a way to pass an interface as a type to a generic function? I anticipate that the generic function will be expanded in the future. Perhaps the current code is not suitable for my problem? This piece of code is being duplicated across multiple fil ...

Error message: Unable to split path as a function when utilizing React hook forms in conjunction with Material UI

Check out this code snippet: <TextField name="name" required className='my-2 mx-auto' label="Full Name" variant="standard" style={{ "width": "60%" }} value={name} onChange={(event) => { set ...

I am restricted from using history with BrowserRouter in Typescript

Trying out React and decided to experiment with TypeScript. Code: import { BrowserRouter } from 'react-router-dom' import history from './utilities/history' ReactDOM.render( <BrowserRouter history={history}> <App /> ...

Utilizing React.js to call a function from an external file

In my code, I am utilizing an external .js file where all the system libraries and functions are stored. This external file is named sysFunction.js. import React from 'react'; function currYear() { var year = new Date().getFullYear(); return ye ...

Activate the trigger event when the popover is activated remotely

I am facing a unique situation on my website where I have multiple popovers (pop1), (pop2), (pop3) that are triggered in sequence when the "Next" button is clicked. These popovers appear one after the other without direct access to them individually. If y ...