21
1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks http://css-tricks.com/swapping-out-text-five-different-ways/ 1/21 It's a common need in web apps: you click something and the text of the thing you just clicked changes. Perhaps something simple like a "Show" button that swaps to "Hide", or "Expand Description" to "Collapse Description." This is a fairly simple thing to do, but there are various considerations to make. Let's cover a bunch of ways. jQuery Way (Less Markup / More JavaScript) You need to store the "swap" text somewhere. I'd say in most cases it is a design/view concern so storing it in the markup is a good idea. We'll use the example of a button who's text swaps between "Hide" and "Show". A data-* attribute is a perfectly good place to store the swap text. So that becomes: It's easy to swap out the text, like: But, if we did that we'd lose the orignal text forever. We need to store the original text first. Another data-* attribute will do. To do that on a click event, you'd do: <button data-text-swap=" Show "> Hide </button> HTML var button = $ ( "button" ); button . text ( button . data ( "text-swap" )); jQuery var button = $ ( "button" ); button . data ( "text-original" , button . text ()); button . text ( button . data ( "text-swap" )); jQuery var button = $ ( "button" ); button . on ( "click" , function () { button . data ( "text-original" , button . text ()); jQuery

Swapping Out Text, Five Different Ways

Embed Size (px)

DESCRIPTION

Swapping Out Text, Five Different WaysThis is a simple explaination for the best understanding.

Citation preview

Page 1: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 1/21

It's a common need in web apps: you click something and the text of the thing you just clicked changes. Perhaps

something simple like a "Show" button that swaps to "Hide", or "Expand Description" to "Collapse Description." This is

a fairly simple thing to do, but there are various considerations to make. Let's cover a bunch of ways.

jQuery Way (Less Markup / More JavaScript)

You need to store the "swap" text somewhere. I'd say in most cases it is a design/view concern so storing it in the

markup is a good idea. We'll use the example of a button who's text swaps between "Hide" and "Show". A data-*

attribute is a perfectly good place to store the swap text. So that becomes:

It's easy to swap out the text, like:

But, if we did that we'd lose the orignal text forever. We need to store the original text first. Another data-* attribute will

do.

To do that on a click event, you'd do:

<button data-text-swap="Show">Hide</button>

HTML

var button = $("button");

button.text(button.data("text-swap"));

jQuery

var button = $("button");

button.data("text-original", button.text());

button.text(button.data("text-swap"));

jQuery

var button = $("button");

button.on("click", function() {

button.data("text-original", button.text());

jQuery

Page 2: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 2/21

But that only goes one direction. To complete the "swap", we'll need to compare the current text value of the button to

see if it matches the swap text or not. If it does, change it back to the original. If not, to the swap text. This is what it

looks like all done:

jQuery Way (More Markup / Less JavaScript)

If we're willing to set that value in the original markup, we can simplify the JavaScript a bit.

We can use a single ternary operator to check if the swap matches the orignal and perform the right action based on

the truthiness.

Vanilla JavaScript Way

I'm guilty of using too much jQuery around here for things that can be done without it. This is what the first "less

markup" version would look like in "raw" JavaScript:

button.text(button.data("text-swap"));

});

$("button").on("click", function() {

var el = $(this);

if (el.text() == el.data("text-swap")) {

el.text(el.data("text-original"));

} else {

el.data("text-original", el.text());

el.text(el.data("text-swap"));

}

});

jQuery

data-text-original

$("button").on("click", function() {

var el = $(this);

el.text() == el.data("text-swap")

? el.text(el.data("text-original"))

: el.text(el.data("text-swap"));

});

jQuery

var button = document.querySelectorAll("button")[0];

button.addEventListener('click', function() {

if (button.getAttribute("data-text-swap") == button.innerHTML) {

button.innerHTML = button.getAttribute("data-text-original");

} else {

JavaScript

Page 3: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 3/21

CSS Way (with jQuery changing class names)

Since this is a view concern and could be considered a "state," a popular idea is to use JavaScript only to change

classes which represent states and let CSS define what the visual change actually is.

We could use the class "on" to represent the swap state. Then that class would apply a pseudo element covering the old

word and replacing it with the swap word. I don't think actual button elements with default browser styling take well to

pseudo element so let's use an anchor here.

This is a bit funky, to be fair. I think this is almost worse that putting the swap word in the JavaScript. CSS isn't really

meant for this kind of thing and likely has some accessibility concerns.

This also happens to work because the word "Hide" is smaller than "Show" a little bit. If the swap word was bigger, the

original would stick out underneath the white cover. You might be able to get around that by inline-blocking the

original, hiding the overflow, and kicking the original out of the box with text-indent. But the fact that the replacement

word is absolutely positioned removes it from the flow, which could be an issue, not to mention real world design isn't

always a simple as flat-color-on-flat-color.

CSS-Only Way

But hey as long as we're getting funky, we could use The Checkbox Hack here to make the text swap entirely CSS. The

replacement happens the exact same way, it just happens when an invisible checkbox right before the word is either

or not. This means the word needs to be in a label as well, which is able to toggle that checkbox's state

through the for attribute.

button.setAttribute("data-text-original", button.innerHTML);

button.innerHTML = button.getAttribute("data-text-swap");

}

}, false);

a {

position: relative;

}

a.on:after {

content: "Hide";

position: absolute;

top: 0;

left: 0;

right: 0;

bottom: 0;

background: white;

}

CSS

:checked

Page 4: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 4/21

Demo of All Five Ways

<input id="example-checkbox" type="checkbox">

<label for="example" id="example">Show</label>

HTML

#example {

position: relative;

}

#example-checkbox {

display: none;

}

#example-checkbox:checked + #example:after {

content: "Hide";

position: absolute;

top: 0;

left: 0;

right: 0;

bottom: 0;

background: white;

}

CSS

Page 5: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 5/21

More?

How have you done this kind of thing in the past? We didn't cover just putting the swap word right in the JavaScript...

how do you feel about that?

SHARE ON

Twitter Facebook Google+

Related Posts

Add (+/-) Button Number Incrementers

CSS :target for Off-Screen Designs

So You Need To Fill a Dropdown Dynamically

HTML CSS JS Result Edit on

Text Swapping

jQuery Way (more markup / less js)

Hide

jQuery Way (less markup / more js)

Hide

Vanilla JS Way

Hide

CSS Way w/ jQuery class change

CSS Only Way

Show

Show

Page 6: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 6/21

Page 7: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 7/21

Comments

Matt Litherland# J UL Y 2 , 2 0 1 3

Nice article Chris, i’m using this right now on a CodePen :-)

Subash# J UL Y 2 , 2 0 1 3

What about using in css to get data from html instead of hard coding that.

attr()

<input id="example-checkbox" type="checkbox">

<label for="example" id="example" data-text="Hide">Show</label>

#example {

position: relative;

}

#example-checkbox {

display: none;

}

#example-checkbox:checked + #example:after {

content: attr(data-text);

position: absolute;

top: 0;

left: 0;

right: 0;

bottom: 0;

background: white;

}

Rhys L# J UL Y 2 4 , 2 0 1 3

Not bad Subash, not bad.

Page 8: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 8/21

Litek# J UL Y 2 , 2 0 1 3

Whenever I swap things – even single word – I use js only to switch classes:

and css:

More markup, less js but feels better:)

<span class="btn show-default">

<span "text-default">show</span>

<span "text-altered">hide</span>

</span>

.show-default > .text-altered { display:none; }

.show-altered > .text-default { display:none; }

Chris Coyier# J UL Y 2 , 2 0 1 3

Yah with I guess it’s not even an accessibility concern really eh?display: none;

Jeff Carlsen# J UL Y 2 , 2 0 1 3

This is how I prefer to do it (usually wrapped in an anchor instead of a span). This way a keyboard user

can select it, and the screen reader will always read what it currently says. Change the class, and the

screen reader now reads the new text when returning to the link.

Andy F# J UL Y 2 , 2 0 1 3

The data-* attributes on elements can also be accessed via element.dataset, so you could also write your

‘raw’ JavaScript example like this:

Page 9: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 9/21

Of course, that won’t work in IE < 11, but we can dream :(

var button = document.querySelectorAll("button")[0];

button.addEventListener('click', function() {

if (button.dataset.textSwap === button.textContent) {

button.textContent = button.dataset.textOriginal;

} else {

button.dataset.textOriginal = button.textContent;

button.textContent = button.dataset.textSwap;

}

}, false);

Peter Foti# J UL Y 2 , 2 0 1 3

Rather than storing both the original text and the text to swap in their own data attributes and using if/else

logic to choose which one to show, you could just use a single data attribute to store whichever text is not

currently being shown, and then just swap the values. Less markup required.

$("button").on("click", function() {

var el = $(this),

tmp = el.text();

el.text(el.data("text-swap"));

el.data("text-swap", tmp);

});

Geoff Bourne# J UL Y 2 , 2 0 1 3

Peter, you confirmed what I was just now wondering. I vote for modified Way #1 then :)

Chris Coyier# J UL Y 2 , 2 0 1 3

Definitely better. Except I guess that it supposes that the event always swaps the text no matter what,

without testing the state. But this is so abstract anyway if we’re considering “what ifs” we’d need to get

way more complicated.

Page 10: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 10/21

Peter Foti# J UL Y 2 , 2 0 1 3

@Chris, right. I was only addressing the swapping out text task, since your original example didn’t

include any particular conditions on swapping it. That logic could be added still, but ideally you would

probably want a separate variable to identify the “state”. If you key off of the text of the button, you

add complexity if you ever need to use localized text.

Check out this Pen!

MaxArt# J UL Y 2 , 2 0 1 3

I used to do this with vanilla Javascript.

@Chris Well that’s no different than the other ways, and the CSS-only method, while lovely, can’t even

do any better than that: on/off, that’s all.

klaus# J UL Y 4 , 2 0 1 3

Thank you, Peter! I was thinking the same all the time while reading the article. This should be the

default way to toggle something.

Nevertheless an interesting subject. I have often wondering if there is something simpler than doing it

by jquery and the answer seems still be no when i’m looking at the css solutions. There is no point of

which I would say: yeah, thats much cleaner and simpler than doing it by js. :(

A bit strange in my opinion – we have so much fancy new elements like video and special input fields,

but still no simple toggle element.

welovewebdesign# J UL Y 6 , 2 0 1 3

Here is the vanilla version :

var button = document.querySelectorAll("button")[0];

button.addEventListener('click', function() {

var text = this.textContent

this.textContent = this.dataset.textSwap

this.dataset.textSwap = text

}, false);

Page 11: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 11/21

Ravindran# J UL Y 2 , 2 0 1 3

I was thinking same solution Peter Foti suggested. Here is my fiddle.

http://jsfiddle.net/rnavaneethan/Fax7D/1/embedded/result/

Austin M. Matherne# J UL Y 2 , 2 0 1 3

It would be overkill for just this rather basic example, but since it’s part of a larger web application, chances

are you should already be using one of the many client side MV* frameworks available. Regardless of if you

are manually wiring it up with a view yourself in backbone, or using a framework that binds them together

for you (such as Ember or Angular), it’s cleaner to store state in a model.

Benjamin C.# J UL Y 2 , 2 0 1 3

Just wanted to say that the first two javascripts snippets miss a closing parenthesis :

button.text(button.data("text-swap");

// should be

button.text(button.data("text-swap"));

Kellen Green# J UL Y 2 , 2 0 1 3

Love your work Chris. One possible shortcut for the JavaScript.

var button = document.querySelectorAll("button")[0];

// could be simplified with

var button = document.querySelector("button");

Page 12: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 12/21

MaxArt# J UL Y 2 , 2 0 1 3

I guess he originally used getElementsByTagName and later changed it for some reason, but that’s

hardly the point.

I think we can read that line as “use the method that fits better for you to get that dang button

element!”

Sylvain# J UL Y 2 , 2 0 1 3

CSS second way (french touch)

input[type=checkbox].on-off{

appearance:none;

-webkit-appearance:none;

-moz-appearance:none;

}

input[type=checkbox].on-off:after{content:attr(data-unchecked);}

input[type=checkbox].on-off:checked:after{content:attr(data-checked);}

MaxArt# J UL Y 2 , 2 0 1 3

Nice, but what’s the French bit?

Also, if you feel confident to use :checked and appearance, you should also go for ::after (pseudo-

element) rather than :after (pseudo-class), as the only reason we still use that syntax is IE8…

Mahdi# J UL Y 3 , 2 0 1 3

This is the best way, no need for js with all css, also no HTML code in the css.

they only thing I will add is display: none for the checkbox because appearance is not supported in all

browsers.

also I would not put the input inside of the label, other than that this is great.

Page 13: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 13/21

Sylvain# J UL Y 2 , 2 0 1 3

<label><input class=”on-off” type=”checkbox” data-checked=”oui” data-unchecked=”non” /></label>

Mike# J UL Y 2 , 2 0 1 3

Maybe i’m just weird but normally i set the text initially inside whatever HTML tag i’m using, then when

needed use jQuery to replace the content of that text with whatever new text. Like so:

$(“p”).text(“Hide”);

and then set it back to show when necessary

Is there a reason why this isn’t a good idea?

MaxArt# J UL Y 2 , 2 0 1 3

It isn’t because you should keep the content in the DOM rather than your code. To keep things clean

and separated, you know.

Your way – the traditional way – is definitely simpler, faster and uses less memory (but if you’re

concerned about these things for a task like this you shouldn’t even use jQuery). On the other hand,

when the project becomes larger, and you end up changing something, you may regret your decision.

Imagine you have two toggle buttons, but in the other one the words you must show are, for example,

“Start” and “Stop”: you have to write the code again for essentially the same task.

Repeat this ad libitum and you’ll get the idea.

Page 14: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 14/21

Bradley# J UL Y 2 , 2 0 1 3

@Mike,

Reusability and separation of concerns. Let’s say you have two buttons that toggle text values, and one

toggles between Show/Hide and the second between Forward/Backward. Doing it your way, you have to

write two sets of JS for each, and associate the View code (i.e., the text displayed) in the code that manages

state (on/off).

Using data attributes or something similar, your JS doesn’t need to know what the text is – only the state,

and to toggle that on or off.

Surjith SM# J UL Y 2 , 2 0 1 3

I’m trying out the last CSS only version in my Dreamweaver. But its not working[chrome,firefox]. When I did

the same in codepen, its working find. What did I missed?

CSS

HTML

< input id=”example-checkbox” type=”checkbox”>

< label for=”example” id=”example”>Show < /label >

#example {

position: relative;

}

#example-checkbox {

display: none;

}

#example-checkbox:checked + #example:after {

content: "Hide";

position: absolute;

top: 0;

left: 0;

right: 0;

bottom: 0;

background: white;

}

zet# J UL Y 3 , 2 0 1 3

@Surjith

Page 15: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 15/21

for attribute corrected

< label for=”example-checkbox” id=”example”>Show < /label >

Surjith SM# J UL Y 3 , 2 0 1 3

Thanks Zet.

It worked.

Given in the post is also mistakken.

Hristo Chakarov# J UL Y 3 , 2 0 1 3

http://jsfiddle.net/vmJ5h/

Mahdi# J UL Y 3 , 2 0 1 3

I Like the way you used the array to do two things for you :), Smart

Xavi# J UL Y 4 , 2 0 1 3

Can you explain me the array part of the code: [ el.text(), el.text( el.data(‘swap’) ) ][0]

Hristo Chakarov# J UL Y 4 , 2 0 1 3

The whole approach does not have any if-else statements as well as does not use a variable to store the

current text value. I’m using array with length=2 for that purpose. The first element of the array is the

Page 16: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 16/21

current text value. Second element actually swaps the text value, using the new value from the data

attribute. As we already stored the initial value as first element in the array, we immediately access it via

[0]. And we use it to set the new value of the data attribute.

No “if”s, no variables, just 2 lines of code. Clean & simple.

Avi# J UL Y 3 , 2 0 1 3

Hi, Thanks for the sharing. I’m using the CSS only way in a new project I’m currently working on.

Btw I love your articles and tutos. :)

Paul# J UL Y 4 , 2 0 1 3

Have used jQuery, but mostly just use simplistic Vanilla…

Following can be applied to any number of elements directly.

<button onclick=”elementStateChange(this, [“Show”,”Hide”])”>Show</button>

function elementStateChange(which, display){

if (which.innerText == display[0]){

which.innerText =display[1] ;

}else{

which.innerText =display[0] ;

}

}

Show

Paul# J UL Y 4 , 2 0 1 3

Oops should have come out…

<script>

Page 17: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 17/21

function elementStateChange(which, display){

if (which.innerText == display[0]){

}

</script>

<button onclick=’elementStateChange(this, [“Show”,”Hide”])’>Show</button>

which.innerText =display[1] ;

}else{

which.innerText =display[0] ;

}

Ramesh Chowdarapally# J UL Y 4 , 2 0 1 3

Useful info chris.

jsc42# J UL Y 4 , 2 0 1 3

@Paul

Even more compactly:

which.innerText = display[which.innerText == display[0] ? 1 : 0];

jsc42# J UL Y 4 , 2 0 1 3

The old way (works from MS-IE4 / NN4 to current day) is:

<input type=button value=Hide onclick="this.value = this.value == 'Hide' ?

'Show' : 'Hide';">

Page 18: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 18/21

Karl# J UL Y 4 , 2 0 1 3

@Chris, @Peter

State can be seen by what is listed in the button. But I would’t really recommend this as you are binding the

view to state.

David Gilbertson# J UL Y 4 , 2 0 1 3

I’ve got a voice in the back of my head saying this is a bad idea, but another approach is to have two buttons.

This HTML:

This CSS:

..and the following jQuery:

Thoughts?

Hide

Show

#btn-show { display: none; }

$('.btn-show-or-hide').on( 'click', function () {

$('.btn-show-or-hide').toggle();

});

David Gilbertson# J UL Y 4 , 2 0 1 3

Fiddle for above: http://jsfiddle.net/davidg707/JNB2F/

Anthony# J UL Y 4 , 2 0 1 3

Regarding the CSS Way (with jQuery changing class names), you could use text-indent and not have to use a

background-color and overlay the text on top like that..

Page 19: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 19/21

jason# J UL Y 7 , 2 0 1 3

Why not just toggle classes? There is often some HTML involved. Data attr isn’t enough always.

Ron# J UL Y 1 0 , 2 0 1 3

I noticed something cool with CSS Generated Content in Opera (before Chromium). The

property actually works on real elements, not just the pseudo before and after elements. Of course, this

doesn’t work in any other browser else, and I’m not even sure that the specification calls for this.

Just seeing your :after usage made me remember, is all. :)

content

Jon# AUG UST 2 1 , 2 0 1 3

I’ve just done this with a mixture of both jQuery and Vanilla by creating a function that passes both the

target to check state (as per most text swaps are built for) and the text to swap:

changeDisplayText = function(targetId, displayText){

Result

Edit on

Anonymous Pens can't be embedded.

Edit on CodePen

Page 20: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 20/21

and then call it like this:

and

Thoughts?

return displayText = targetId.is(":visible") ? displayText.replace("Hide","Show") : displayText.replace("Show","Hide");

}

$(this).attr('title', changeDisplayText($(this.hash), $(this).attr('title')));

$(this).html(changeDisplayText($(this.hash), $(this).html()));

Даниил# NO V E M B E R 1 1 , 2 0 1 3

We need to store data into variables before swap it.

I suggest to use an element without text in HTML:

And this JS to make it live:

I created a pen for it: cdpn.io/yEJdw

button.toggle(data-swap="close", data-text="open")

var button = $(".toggle");

button.html(button.data("text"));

button.click(function(){

var el = $(this);

var swap = el.data("swap");

var text = el.data("text");

el.data("text", swap);

el.data("swap", text);

el.html(swap);

});

eadly# M AR C H 2 9 , 2 0 1 4

nice ways i like css way but Sometimes we are forced to use other ways

Page 21: Swapping Out Text, Five Different Ways

1/14/2015 Swapping Out Text, Five Different Ways | CSS-Tricks

http://css-tricks.com/swapping-out-text-five-different-ways/ 21/21

*May or may not contain any actual "CSS" or "Tricks".

Carol Jenkins# AP R I L 2 4 , 2 0 1 4

How do you get the data attribute to persist on page refresh?

This comment thread is closed. If you have important information to share, you can always contact me.