gummybearpaws
gummybearpaws

Reputation: 141

Change text on hover with transition jQuery

Trying to achieve this: I have multiple headers, each with different text. When I hover over one header, the text changes accordingly (all text is different for each header) with a 'slide' animation.

I have gotten up to the point where the hover works fine, but when I try to add a simple transition, the functionality breaks.

HTML code:

<h1 id="mainText1">Header 1.</h1><span class="mainText1">Text 1.</span>
<h1 id="mainText2">Header 2.</h1><span class="mainText2">Text 2.</span>
<h1 id="mainText3">Header 3.</h1><span class="mainText3">Text 3.</span>
<h1 id="mainText4">Header 4.</h1><span class="mainText4">Text 4.</span>

The span is currently set to display: none; in CSS.

JQuery:

$(document).ready(function() {
    $("h1").hover(function(evt) {
        evt.preventDefault();
        var id = $(this).attr('id');
        var toShow = $("." + id);
        $(this).hide();
        $(toShow).show();
    }, function () {
        var id2 = $(this).attr('id');
        var toHide = $("." + id2);
        $(this).show();
        $(toHide).hide();
    });
});

It works fine if the 'slow' in line 7 is removed. I have also tried something like...

$(toShow).show().slideDown('slow');

.. but no luck as well. Am also looking for a cleaner solution rather than the posted one. My jQuery is too basic to figure out if this could be done better in another way. Thanks in advance!

EDIT: I think I did not make myself clear, as I am seeing similar solutions. The h1 must disappear upon hover. I updated the JS code. This code is working as I intend it to be, but it does not contain the 'slide' animation. When I try putting the code for it to slide (like .slideDown('show'), it does not work as intended). Is there a way to do this?

Updated fiddle: http://jsfiddle.net/yvLs5/ Previous fiddle here: http://jsfiddle.net/8rnuE/1/ (where I tried putting 'slow') and functionality breaks.

Upvotes: 1

Views: 558

Answers (4)

Rakesh Kumar
Rakesh Kumar

Reputation: 2853

are you looking for this.

HTML

<div class="topic">
  <h1 id="mainText1">Header 1.</h1>
  <span class="mainText1">Text 1.</span></div>
<div class="topic">
  <h1 id="mainText2">Header 2.</h1>
  <span class="mainText2">Text 1.</span></div>
<div class="topic">
  <h1 id="mainText3">Header 3.</h1>
  <span class="mainText3">Text 1.</span></div>
<div class="topic">
  <h1 id="mainText4">Header 4.</h1>
  <span class="mainText4">Text 1.</span></div>

CSS

span {display:none;}
h1{background:yellow;margin:0;}

Script

$('.topic').mouseenter(function(){
    $('.topic').find('span.'+$(this).find('h1').attr('id')).show();
    $(this).find('h1').hide();
}).mouseleave(function(){
    $('.topic').find('span.'+$(this).find('h1').attr('id')).hide();
    $(this).find('h1').show();
});

Fiddle Demo

Upvotes: 0

Ben Hull
Ben Hull

Reputation: 7673

OK - the reason removing the 'slow' keyword in the call to slideDown works is it makes that transition instant. When you add the slow keyword, it makes the slide take time - however, javascript doesn't wait for the transition before moving on to the next line. So, the 'slideDown' is still in progress while the 'show' is occurring, which makes the layout jump all over the place.

The other issue you have is that your 'hover' event is only on 'h1' - which means that if the user hovers over the text that is revealed by the hover, the hover is canceled, which then hides the text... which pulls the h1 back up under the cursor, so the event fires again, and so on...

Here's a different solution: http://codepen.io/anon/pen/jGDIt

I wouldn't use javascript for this - I would just use CSS. First, you'll need to make a change to the structure of your HTML, so that the h1 and the revealed text are siblings inside a containing element (I've used <div class="toggle-section">, but you might like to use a <section> or some other block element):

<div class="toggle-section">
  <h1>Heading 1</h1>
  <p class="main-text">Main text 1</p>
</div>
<div class="toggle-section">
  <h1>Heading 2</h1>
  <p class="main-text">Main text 2</p>
</div>
<div class="toggle-section">
  <h1>Heading 3</h1>
  <p class="main-text">Main text 3</p>
</div>
<div class="toggle-section">
  <h1>Heading 4</h1>
  <p class="main-text">Main text 4</p>
</div>

Then, set up your CSS so the hover is triggered on the container, like so:

.toggle-section .main-text {
  display: none;
}

.toggle-section:hover h1,
.toggle-section:focus h1 {
  display: none;
}

.toggle-section:hover .main-text,
.toggle-section:focus .main-text {
  display: block;
}

That's the basic show/hide behaviour, without requiring javascript. If you want transitions, you can do that too, so long as you know the height of 'main-text' in advance. If you do, change your CSS to:

.toggle-section h1,
.toggle-section .main-text {
  -moz-transition: height 400ms;
  -o-transition: height 400ms;
  -webkit-transition: height 400ms;
  transition: height 400ms;
  overflow: hidden;
  height: 1.2em;
}
.toggle-section .main-text {
  height: 0;
}

.toggle-section:hover h1, .toggle-section:focus h1 {
  height: 0;
}
.toggle-section:hover .main-text, .toggle-section:focus .main-text {
  height: 1.2em;
}

Then, when you hover/focus the element, the height of main-text will expand to 1.2em over 400ms.

There are a few advantages to doing it this way:

  • It works without javascript - that's especially handy if you're still beginning with javascript/jQuery: if you break something by accident, your toggles still work.

  • It's faster: Your CSS will usually be ready before your Javascript on your pages.

  • It's neater - it doesn't mix display stuff into your Javascript.

One thing to look out for with a set up like this: Hover doesn't work on phones or touch devices (either you're touching the screen or not). You should provide another option for those devices.

Upvotes: 1

Yeray Cabello
Yeray Cabello

Reputation: 421

The main problem comes cause you are hiding the element you hove over. Here is a piece of code to hide the element.

<h1 id="mainText1">
    <span class="mainText1_main">Header 1.</span>
    <span class="mainText1">Text 1.</span>
</h1>

function(evt) {
    evt.preventDefault();
    var id = $(this).attr('id');
    var toHide = $("." + id + "_main");
    var toShow = $("." + id);
    $(toHide).hide();
    $(toShow).show('slow');
}

Upvotes: 0

Ruskin
Ruskin

Reputation: 6171

If you don't hide the H1 it works

http://jsfiddle.net/j5J4F/

$(document).ready(function() {
    $("h1").hover(function(evt) {
        evt.preventDefault();
        var id = $(this).attr('id');
        var toShow = $("." + id);
        $(toShow).show('slow');
    }, function () {
         var id2 = $(this).attr('id');
        var toHide = $("." + id2);
        $(toHide).hide();
    });
});

The browser was getting into a pickle, because on hovering over the H1 it then hid the h1, triggering the mouse-out event that then showed the H1 again and hid the span.

note - the span should really be replaced by a block level element such as a p to be semantically correct.

Upvotes: 0

Related Questions