2

I have a div where I want to show the name of a person.

I want to only show the person's first name in the normal state. When you hover, the last name should appear on the right of the first name, with its width expanding from 0 to normal width. All this text is aligned to the right.

If I apply the transition to the last name span it doesn't even show it.
I also tried with max-width (as a guy does here: http://jsfiddle.net/qP5fW/87/ ) but it doesn't work. So I made a wrapper div, used width instead of max-width and now it works, only it doesn't show the transition at all.

I suspect the problem is with the "auto" property but if anyone knows how to make the transition work, I would be very grateful.

Here's my fiddle: https://jsfiddle.net/drywrsy6/

HTML:

<div class="name">
  <span class="first">John</span>
  <div class="last-wrapper">
    <span class="last">Doe</span>
  </div>
</div>

CSS:

.name {
  border: 1px solid lightgrey;
  margin: 10px auto 0px auto;
  padding: 5px;
  width: 300px;
  font-size: 2em;
  text-align: right;
  overflow: hidden;
  white-space: nowrap;
}

.first {
  font-style: italic;
}

.last-wrapper {
  display: inline-block;
  vertical-align: bottom;
  overflow: hidden;
  width: 0;
  transition: all 1s;
}

.last {
  color: red;
}

.name:hover .last-wrapper {
  width: auto;
}
Julian
  • 4,176
  • 19
  • 40
jeanmarc
  • 57
  • 2
  • 8

1 Answers1

5

You can use max-width, as it won't work with width: auto.

Just make sure the max-width value is big enough to accommodate the widest text, or you need a script calculating this on load.

As the max-width will be somewhat wider than some content, one can have a transition duration with shorter time on reverse, to make it look better on less wide text.

.name {
  border: 1px solid lightgrey;
  margin: 10px auto 0px auto;
  padding: 5px;
  width: 300px;
  font-size: 2em;
  text-align: right;
  overflow: hidden;
  white-space: nowrap;
}

.first {
  font-style: italic;
}

.last-wrapper {
  display: inline-block;
  vertical-align: bottom;
  overflow: hidden;
  max-width: 0;
  transition: all 0.3s;
}

.last {
  color: red;
}

.name:hover .last-wrapper {
  max-width: 100px;
  transition: all 0.7s;
}
<div class="name">
  <span class="first">John</span>
  <div class="last-wrapper">
    <span class="last">Doe</span>
  </div>
</div>

Updated based on a comment

Do note, and as SimoAmi wrote, "...when shrinking, reversing the animation, if your text is 100px and you specify max-width of 1000px, much of the animation time is spent shrinking the blank 900px difference"

One way to deal with that is to elaborate with its transition's timing function, where a custom cubic-bezier curve could be one option.

Asons
  • 84,923
  • 12
  • 110
  • 165
  • Well thanks a lot, it worked! I knew I was close, and as I suspected the auto property was the culprit. But it's the first time I've heard that you can't transition to auto... – jeanmarc Aug 01 '16 at 20:09
  • @jeanmarc You're welcome, and I made a small update, explaining how to make the transition look better – Asons Aug 01 '16 at 20:15
  • There's a problem with this approach: Not knowing the right width and specifying one that's way too big for the text would introduce a delay when shrinking, reversing the animation. if your text is 100px and you specify max-width of 1000px, much of the animation time is spent shrinking the blank 900px difference (the cause of the delay). – SimoAmi Jun 30 '18 at 04:15
  • @SimoAmi That is true, but there is no other way when the width is unknown, and using CSS alone (which was asked for). It is all explained in the answer, where I also explicit wrote that to overcome it, a script is needed to calculate the real width. – Asons Jun 30 '18 at 08:16
  • @SimoAmi I updated my answer with a note/link to your comment + added a note how to make that part better. Is there something more that you think I should add to clarify the issue with this approach? ... If not, and the edit is of value, please consider give the answer an upvote. – Asons Jun 30 '18 at 08:32
  • @LGSon This solution is also discussed in https://stackoverflow.com/a/8331169/2117996. From the comments, people think of it as a workaround rather than a solution. I gave you an upvote considering there's no cleaner way to do this in CSS. – SimoAmi Jun 30 '18 at 14:11
  • @SimoAmi Thanks, and yes, it is a workaround, as the proper way would be that CSS itself calculated a value of `auto` to an animateable number. You will also find posts here were users ask how to animate `display: none`, and the same issue there, not being animateable, and `max-width/height` comes to rescue as a CSS only workaround. – Asons Jun 30 '18 at 14:17
  • @SimoAmi Hopefully we will see an upcoming update of CSS, where this is taken care of, either using CSS `calc()` or some other, built-in method. – Asons Jun 30 '18 at 14:19
  • Very helpful for me. Thank you. – atom Aug 24 '20 at 13:24