HTML5, CSS3, jQuery, JSON, Responsive Design...

Hide and show elements with a touch of class!

Michael Brown   June 25 2012 06:50:40 PM
Here's a mini-app on JSFiddle (and I do mean mini here!) that sets up a simple Read Mode vs Edit Mode field; the kind that you might set up in a typical Domino web app, in fact (although this one isn't on Domino).

When you click the Edit Mode button, an editable textarea appears with a row of extra buttons, one of which will put the mini-app back into Read Mode.  (The other two buttons are just there for show: they don't do anything!)  Hit the Read Mode button and the current buttons will disappear and the Edit Mode button reappears. Anything that you typed into the textarea will appear as Read Mode (i.e. non-editable text).

Now you see it....

So far, so what?  Well, it's actually the technique that I'm using to do the hiding and showing of the elements that might interest you.  In years gone by, I might have been tempted to hide and show each element individually via jQuery's .hide() and .show functions, or some variation thereof.  But that's clunky and can quickly become unmanageable as I'd have to keep track of all the elements that I just hid and then remember to unhide each one again when I change modes.  I might cut down on the code by grouping the elements inside divs and then hiding them, but there's limits to that approach: what if the elements I want to hide are in different parts of the page?  I could end up with a lot of divs and I'm back to my original problem of keeping track of all their hide/show states.

A Touch of Class

Then I wised up and started using classes, and the amount of code I needed to write was cut quite dramatically and as a result, is far more easy to maintain.

As you can see, the field and buttons for my mini-app are inside a div called divContainer (its ID) and with a class of container.  Each element within divContainer has one of two classes: editModeDisplay for elements that should be displayed in Edit Mode only and viewModeDisplay for elements that should be displayed in Read Mode only.  The mini-app is in Read Mode when loaded.   Clicking the Edit Mode mode button adds a class called ... wait for it... editMode to the container div.  It also copies the value from the TextArea into a Read mode span tag.  And that's all it does: two lines.  The rest is handled by CSS.

Edit Mode

So, here's the CSS that hides all the Read Mode elements when we're in Edit Mode:
.container.editMode .viewModeDisplay {
 display: none;

The CSS code above instructs as follows: "inside an element that has the container and editMode classes, hide any element that has the viewModeDisplay class".

Read Mode

How about Read Mode though?  Now we could change our Read Mode button to not only remove the editMode class from the container, as it does now, but also add a readMode class to it.  Then our CSS rule for Read Mode would simply check for the presence of the readMode class on the container div, right?  While that will work, it's doing some extra work that we don't actually need to do.  We don't really need a readMode class if we can say that Read Mode is defined by the absence of the editMode class.  But how do to that?

CSS3 to the rescue

CSS3 has a new selector - actually, "pseudo-selector" is the correct term - called :not().  Here's how I use it to hide my Edit Mode elements when we're in Read Mode (i.e. the editMode class is missing from the div container):
.container:not(.editMode) .editModeDisplay {
 display: none;

The CSS code above instructs as follows: "inside an element that has the container class but does not have the editMode class, hide any element that has the editModeDisplay class".

How easy is that!

You know who...

Inevitably, there's a fly in the ointment again.  And you better sit down before you read this next bit because you're going to be utterly shocked when I tell you that the problem is Microsoft Internet Explorer.  The :not() pseudo-operator requires IE version 9 or higher.  Which also means, of course, that you're going to need Windows 7 because IE 9 doesn't run on any earlier versions of Windows - except for Vista, which I'm not counting because... well, who does?

Now the project I'm working on at the moment doesn't require any version of IE to be supported.  Wait a minute!  I liked the sound of that!  So much, in fact, that I'm going to say it again!  The project that I am currently working on does not need to work on the piece of shit known as Internet Explorer!  No not even IE 9, which looks like the first version that actually works half-way decently.

If you're not in this happy position, however, you should be able to implement :not() selector, along with other CSS3 selectors on older versions of IE by use of a JavaScript polyfill (a.k.a. shiv) such as selectivizr.  This is a topic about which  I've blogged previously.

No Comments Found