This issue revolves around the removal of empty
<span></span> elements in TinyMCE when saving a post or switching between between the
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.
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.
<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.
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.
<span> Screen Reader Text
position: absolute !important;
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
<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.
<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
, the soft-hypen character is rendered as though it takes up no space, and shouldn't affect the size of your 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
<strong> are a few other possibilities). See this Stack Overflow question for more regarding the practice of using
<i> for icons.
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.