tags:

views:

39

answers:

2

I am hiding an element using inline css, like so:

<span class="hidden-nojs" style="display:none">Some text</span>

Next I use jQuery to show the element, like so:

$(".hidden-nojs").show();

This works great. As soon as I remove the inline css and put display:none on the external css stylesheet for the hidden-nojs class, it stops working. This is what I wrote in the external stylesheet:

.hidden-nojs {
    display: none;  
}

I'm assuming that the external stylesheet loads after the jQuery has already run? This is somewhat annoying as I would like to hide multiple elements with css and would like to avoid using inline css.

Why will show() only work for fields that are hidden using inline css? How can I fix this problem?

+1  A: 

The problem is you're trying to hide and show an inline element. The jQuery effects only work with block type elements. The jQuery effects manipulate inline element style, which is why that version works and the class version doesn't.

If you think about it block type elements are rectangles. They're easy to animate growing and shrinking because you simply animate their height and/or width.

Inline elements aren't necessarily rectangles, which is why the jQuery effects mostly don't work. To give you an example:

<p>Inside paragraph <span class="foo">This is a test</span> contains text.</p>
<input type="button" id="bar" value="Toggle">

Run:

$(function() {
  $("#bar").click(function() {
    $("span.foo").toggle();
  });
});

The first click will hide it. The second will turn it into a block (as in it will no longer be contained in the paragraph). This is what I mean about jQuery effects not really working with inline elements.

Internally, the jQuery effects work by a combination of animation and toggling in between display: none and display: block. What this means is jQuery effects don't work on table cells either. Why? They're not display: block, they're effectively display: table-cell. Try this yourself and see what happens after you toggle() a table cell a couple of times.

So what's the solution? For inline content the easiest solution is simply to use classes:

hidden { display: none; }

with

$("span.hideme").toggleClass("hidden");

This doesn't have the animation effect. You can add this yourself but I'm not 100% how well animate() will work with inline elements.

Alternatively, if your content can be a block, make it a block and all these problems go away. In your case either use a <div> instead of a <span> or add display: block to the <span>.

cletus
So is the solution I found the only way of doing it? I can't set the span to display:none and to display:block in the external stylesheet.
zeckdude
@zeckdude if you take your approach to its logical conclusion, you'll see it doesn't work either.
cletus
@cletus - is this using animation though?
nickf
A: 

I haven't been able to replicate this problem, but I don't think it's anything much to do with what Cletus is talking about. There's no animation here?

Putting a style inline is nothing to do with the fact that it's an inline element. I've had similar problems in the past when using a homebrew toggle-visibility script and classes. The way that many naive implementations (such as mine) worked is like this:

function toggle(el) {
    el.style.display = (el.style.display == 'none') ? '' : 'none';
}

If it's not hidden, change the inline style to hidden. If it is hidden, remove the inline style. When you remove the inline style, it then reverts to style defined in your stylesheet, which is why it doesn't get shown.

Like I said, I tried replicating your error using jQuery's show() function and couldn't do it. In my tests, jQuery is smart enough to revert to what the display style was before, so I don't know exactly what the problem is, but it sounds a lot like the problem I had before.

As far as a solution goes, just remove the hidden-nojs class.

nickf