最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ReactCSS - Animate button width resize after content changes when width is auto - Stack Overflow

programmeradmin2浏览0评论

I have a react ponent representing a button which changes the content and color depending on some props. If a form ponent includes this button and gets submitted the button changes it's content and color. This works well.

Now I want an animation (CSS transition) for the changing with when the content of the button changes. Setting an explicit width for different states is NOT an option because the application is multilingual. When using max-width the animation only works when the button extends but not when it decreases.

Here is a snippet with a button ponent which changes the state every second. Like in the real ponent this one uses the bootstrap btn classes:

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {status: 0};
  }

  ponentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  tick() {
    let status = this.state.status;
    status++;
    if(status >= 2) {
      status = 0;
    }
    this.setState({
      status: status
    });
  }

  render() {
    const btnClass = this.state.status ? 'primary' : 'secondary';
    
    return (
      <button className={`btn btn-${btnClass}`} type='button'>
        {this.state.status ? this.props.large : this.props.short}
      </button>
    );
  }
}

// Render it
ReactDOM.render(
  <Button large='This is a long button you can click on!' short='short'/>,
  document.getElementById('react')
);
.btn {
    -webkit-transition: width 1s; /* Safari */
    transition: max-width 1s;
    width: auto;
}

.btn-primary {
  max-width: 300px;
}

.btn-secondary {
  max-width: 50px;
}
<div id="react"></div>
<script src=".1.0/react.min.js"></script>
<script src=".1.0/react-dom.min.js"></script>
<link rel="stylesheet" href=".3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

I have a react ponent representing a button which changes the content and color depending on some props. If a form ponent includes this button and gets submitted the button changes it's content and color. This works well.

Now I want an animation (CSS transition) for the changing with when the content of the button changes. Setting an explicit width for different states is NOT an option because the application is multilingual. When using max-width the animation only works when the button extends but not when it decreases.

Here is a snippet with a button ponent which changes the state every second. Like in the real ponent this one uses the bootstrap btn classes:

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {status: 0};
  }

  ponentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  tick() {
    let status = this.state.status;
    status++;
    if(status >= 2) {
      status = 0;
    }
    this.setState({
      status: status
    });
  }

  render() {
    const btnClass = this.state.status ? 'primary' : 'secondary';
    
    return (
      <button className={`btn btn-${btnClass}`} type='button'>
        {this.state.status ? this.props.large : this.props.short}
      </button>
    );
  }
}

// Render it
ReactDOM.render(
  <Button large='This is a long button you can click on!' short='short'/>,
  document.getElementById('react')
);
.btn {
    -webkit-transition: width 1s; /* Safari */
    transition: max-width 1s;
    width: auto;
}

.btn-primary {
  max-width: 300px;
}

.btn-secondary {
  max-width: 50px;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

How can i get an animation for the changing width (when the button gets smaller again)?

Please consider that an answer doesn't have to be just CSS related. I thought about that the react ponent calculates it's width and then sets it inside the ponentWillMount function but that didn't work either...

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Aug 17, 2018 at 10:54 goulashsoupgoulashsoup 3,1282 gold badges41 silver badges65 bronze badges 1
  • 1 To make animation of max-width possible simply change the transition: width ... statement to either transition: max-width... or remove a specified property to transition all of them. Still, animating max-width can be jerky since you dont really know exaclty how wide the button is depending on language/screen sizes. – Erik Svedin Commented Aug 17, 2018 at 11:00
Add a ment  | 

2 Answers 2

Reset to default 3 +50

Try setting width: 100% to .btn class. There is nothing wrong with animating max-width property. The issue arises when the text is changing from a small text to a larger one and the browser will have to recalculate what auto means as a value for the width property. It seems that 100% does not work the same way.

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {status: 0};
  }

  ponentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  tick() {
    let status = this.state.status;
    status++;
    if(status >= 2) {
      status = 0;
    }
    this.setState({
      status: status
    });
  }

  render() {
    const btnClass = this.state.status ? 'primary' : 'secondary';
    
    return (
      <button className={`btn btn-${btnClass}`} type='button'>
        {this.state.status ? this.props.large : this.props.short}
      </button>
    );
  }
}

// Render it
ReactDOM.render(
  <Button large='This is a long button you can click on!' short='short'/>,
  document.getElementById('react')
);
.btn {
    -webkit-transition: width 1s; /* Safari */
    transition: max-width 1s;
    width: 100%;
}

.btn-primary {
  max-width: 300px;
}

.btn-secondary {
  max-width: 50px;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

I have a solution. Add min-width to your css classes and transition as below.

Animate on the way up. Animate on the way down.

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {status: 0};
  }

  ponentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  tick() {
    let status = this.state.status;
    status++;
    if(status >= 2) {
      status = 0;
    }
    this.setState({
      status: status
    });
  }

  render() {
    const btnClass = this.state.status ? 'primary' : 'secondary';
    
    return (
      <button className={`btn btn-${btnClass}`} type='button'>
        {this.state.status ? this.props.large : this.props.short}
      </button>
    );
  }
}

// Render it
ReactDOM.render(
  <Button large='This is a long button you can click on!' short='short'/>,
  document.getElementById('react')
);
.btn {
    -webkit-transition: width 1s; /* Safari */
     transition: max-width 1s, min-width 1s;
     width: auto;
}

.btn-primary {
  max-width: 330px;
  min-width: 230px;
}

.btn-secondary {
  max-width: 60px;
  min-width: 40px;
  text-align: left;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

发布评论

评论列表(0)

  1. 暂无评论