0

I'm attempting to allow our CMS editors the ability to swap out the text used for a page title using only a css override.

<header data-alternate="An Alternate Title">
    This Page's Default Title
</header>

Using the :before or :after tag, one could use one of many available alternate titles.

header:before {
content: attr(data-alternate);
display: inline-block;
}

If only we could also say,

header:text {
    display: none;
    }

Unfortunately, as far as I can tell, there is no good way to hide "This Page's Default Title" in order to replace it with "An Alternate Title". If this were a Sprite, we could use one of the well-worn image replacement techniques like Phark or otherwise. Not so much with text replacement generated by :before, because the :before is also affected by the CSS devices used to hide the default text so that, with Phark, for example, the :before content is also at -9999px.

There are solutions I'm trying to avoid.

  1. Using the Phark method or somesuch to hide the default text and then using absolute positioning on the :before content to put it back at left: 0, top: 0. I want/need to preserve flow if possible.
  2. Wrapping the "Page's Default Title" in a span and just setting it to display: none in the CSS when an alternate title is being used.

i.e.

<header data-alternate="An Alternate Title">
    <span class="default">This Page's Default Title</span>
</header>

This works, but a span nested in a header is displeasing.

Is there a way to target a tag's text without also targeting its generated :before/:after content? Is there another way to do this?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356

1 Answers1

1

I'm not sure if this is exactly what you want, but you could try something like this:

p {
    visibility: hidden;
}
p:before {
    content: attr(data-alternate);
    display: inline-block;
    visibility: visible;
}

http://jsfiddle.net/yJKEZ/

You can set the visibility of the p element to be hidden, and then set the visibility of the :before pseudo-element to be visible within it's parent (the p) despite it's setting.

If that doesn't quite work as expected, there isn't really anything tremendously wrong with adding an extra span in, to help the process. It might not be as clean, but it could work better.

I do, however, want to raise the question of why you might need to do this, and point out some concerns with an approach like this...

For starters, pseudo elements are not part of the DOM, so that alternate text can't be selected, and isn't as accessible to the browser (or the user). Screen readers or search engines will see the default text, and not pay any attention to the alternate text, but that's what your user will see... This could lead to some confusion.

While your question specifies that you want to be able to do this with CSS, and while it may be possible, it really isn't the best solution for doing something like this. Especially if your website is being viewed in an older browser which does not support pseudo elements (Now the user sees nothing at all!).

I would more recommend something like this for swapping an image out for alt text in a print stylesheet, or swapping a hyperlink's text for the full address that it links too (again, mainly for a print stylesheet). Changing important content like a heading in this fashion can cause a lot of other issues, especially in terms of accessibility.

Just something for you to consider along with my answer... I hope I've helped you with your problem!

Blake Mann
  • 5,440
  • 23
  • 37
  • Good thoughts, Blake. I agree that introducing a discrepancy between the markup and what is seen in the headers is not ideal and has some screen reading and SEO liabilities. Using visibility:hidden versus display:none is another good thought, but fails in my case because, for design reasons, I can't use overflow:hidden nor whitespace:nowrap to force the invisible but space-occupying default title to drop out. Wish I had enough cred to give you an up vote, but thanks. – Nate Jacobson Apr 03 '14 at 17:40