Background
This issue revolves around the removal of empty <span></span>
elements in TinyMCE when saving a post or switching between between the Visual
and Text
editor tabs. The problem is inherent to core functionality (as of trunk version 4.0-alpha-20140602
) and is unchangeable via the standard WordPress APIs, as is mentioned in ticket #26986. The ticket details the reasoning behind the setting and is marked as wont-fix
, meaning that your best bet is one of the "work-arounds" listed below.
Default WordPress/TinyMCE Behavior
By default, WordPress's TinyMCE instance is configured such that a number of empty tags or tags missing certain attributes are removed in an attempt to eliminate markup that does not do anything.
From MDN's <span>
docs:
The HTML element is a generic inline container for phrasing
content, which does not inherently represent anything. It can be used
to group elements for styling purposes (using the class or id
attributes), or because they share attribute values, such as lang. It
should be used only when no other semantic element is appropriate.
As <span>
is intended to group inline elements/content, the WordPress core contributors have decided that the element must be irrelevant when the tag is empty and thus strip it from the content.
Work-Arounds
For the most part, the proper way to modify TinyMCE's configuration is to hook into tiny_mce_before_init
with a filter however span
's empty-removal behavior cannot be modified in this manner. To do so likely requires hacks to core files, and as such I have not provided any such solutions for consideration.
Ideal: Give <span>
Screen Reader Text
Screen readers are pieces of software that attempt to interpret on-screen content in order to aide the visually-impaired. When processing a webpage, most screen readers either disable CSS (and Javascript) entirely or only process a sub-set, such that things normally hidden by CSS will end up getting processed as though it were visible. Web-devs traditionally exploit this behavior in the name of accessibility by creating a CSS class that can be applied to elements that will hide them from everyone who has CSS enabled, something along the lines of:
.screen-reader-text {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
}
With this class available (your theme's stylesheets likely have a similar class), inside of your icon span you can add a second, "screen-reader" span that won't get (or at least appear to be) rendered on-screen but will provide screen readers an accessible alternative to your icon, similar to how the alt
attribute works on an <img>
:
<span class="icon-shield"><span class="screen-reader-text">Security</span></span>
The above will display your icon when CSS is enabled, and screen readers will interpret "Security" in it's place.
Give <span>
Invisible Content
To prevent the <span>
s from getting stripped out, you can add content that isn't explicitly displayed:
Adding a space character between the opening and closing tag will suffice. However, as empty whitespace is stripped you need to add the character via the
HTML entity. This character will be converted to appear to be a normal space once you switch tabs or save, however it will not get stripped out of the markup. Note that this may affect the size of your span, just as it would if you placed a single letter in the element:
<span class="icon-shield"> </span>
Assuming you are working with a UTF-8 character set, you can use a "soft-hyphen" character via the HTML entity ­
. Unlike
, the soft-hypen character is rendered as though it takes up no space, and shouldn't affect the size of your span:
<span class="icon-shield">­</span>
Use an Alternate Element
While WordPress's TinyMCE is configured to strip out empty <span>
elements, there are a number of other tags that are configured by default to allow existing without content. In the comments of ticket #26986, TobiasBg recommends using <i>
(<em>
, <b>
, and <strong>
are a few other possibilities). See this Stack Overflow question for more regarding the practice of using <i>
for icons.
<i class="icon-shield"></i>
Create Your Own TinyMCE Instance
This is probably the most complicated and generally absurd solution available, and as such I won't provide an implementation. Using a plugin, it should be possible to load up a separate instance of the TinyMCE scripts, configure them however you desire (beyond the options that WordPress exposes), and replace the default editor (or hide it and add a replacement metabox). While allowing you to disable the removal of empty spans, the amount of time required to flesh out such an implementation would likely greatly outweigh the benefit.
...
are not valid Javascript, and are frequently used to indicate the omission of content. In this instance, I believe the author of the doc intended for you to supply your own TinyMCE configuration where the ellipsis is present. Furthermore, you've used the default value from the docs which explicitly states it replaces TinyMCE'simg
rule - this does nothing for yourspan
problem. You have a better chance of receiving a valid answer the more research effort you display - please spend some more time with the TinyMCE docs.valid_elements
option documentation should help you figure out what you should be passing to theextended_valid_elements
option. I haven't read the docs, but it will probably look pretty similar to"span[class|id|title|style]"