2

So I have a navigation menu that is generated by my CMS:

enter image description here

The menu's HTML is straightforward (edited for clarity):

 <ul>
     <li><a href="...">Journal</a></li>
     <li><a href="...">Art</a></li>
     <li><a href="...">Work</a></li>
   </ul>

I want the items to show up as hand-written text, in keeping with the general theme of the site, using separate PNG files for each menu item.

To do that, I used the CSS content property like so:

#headerNav .nav li a[href="/_site/en/journal/"]  
 { content: url(/path/to/image.png); }

And it worked great! The HTML text of each item was replaced by the correct image:

enter image description here

However, alas, then I learned not every browser supports the content property on selectors other than :before and :after! Chrome and Safari do it, but Firefox doesn. However when I use :before, the HTML node isn't replaced, but the image is added:

enter image description here

How do I work around this?

What didn't work:

  • Making the <a> element display: none removed the :before part as well.
  • Making the <a> element position: absolute and moving it elsewhere won't work either.
  • Making the <a> element width: 0px screws up the layout because the images added through content aren't in the document flow.

What I don't want to do:

  • Of course I can output the images by hand but I want to work with the HTML the CMS is giving me, which is <li>s with text in them.

  • Any solution involving background-image would require me to specify each item's width and height in the style sheet, which I would like to avoid for the purposes of this question.

  • Turning the handwriting into a font is not an option.

  • Using JavaScript to replace the items on the fly is not an option. This needs to work using pure HTML and CSS.

17
  • 1
    CSS image replacement is a well-documented technique. Commented Jan 17, 2014 at 15:32
  • @Blazemonger none of the examples have all green Commented Jan 17, 2014 at 15:33
  • @Blazemonger to use any of them, I'd have to specify a width and height for each item manually in the style sheet, which I'd like to avoid - that's why I used content in the first place. (It's a fair compromise, though, if nothing else comes up, thanks for the reminder.) Commented Jan 17, 2014 at 15:34
  • @mplungjan That page is years old, too. Modern browsers weren't at the time. The last example here was used in HTML5Boilerplate until December 2012. Commented Jan 17, 2014 at 15:34
  • I don't think there's any way to do CSS image replacement without specifying dimensions, except possibly using :before or :after. Commented Jan 17, 2014 at 15:35

3 Answers 3

6

Since you are doing this into a navigation bar you should have a fixed height making the next method possible to work:

  • First insert the image as content on the :before element and make it display:block to push the actual text of the a tag below.

    li a:before {
       content:url(http://design.jchar.com/font/h_1.gif);
       display:block;
    }
    
  • Then hide that text with a fixed height on your a tag:

    li a{
       height:50px;
       overflow:hidden;
    }
    

The Working Demo

Sign up to request clarification or add additional context in comments.

Comments

2

Answer was answered before OP added the line

Any solution involving background-image would require me to specify each item's width and height in the style sheet, which I would like to avoid for the purposes of this question.

So if anyone interested in background-image solution can refer this, else can simply skip.


Am not sure how optimum solution I am suggesting is, but surely you can use background-image for each a element, using nth- pseudo, and set the fonts color to transparent, or use text-indent property with overflow: hidden;

So it will be something like

nav ul li {
   display: inline-block;
}

nav ul li:nth-of-type(1) a {
   background-image: url(#);
   display: block;
   width: /* Whatever */ ;
   color: transparent;
   text-indent: -9999px; /* Optional */
   overflow: hidden;
   font-size: 0; /* Optional, some people are really sarcastic for this */

   /* Below properties will be applicable if you are going for sprite methods */
   background-position: /* Depends */ ;
   background-size: /* If required */ ;
}

The reason why I would suggest you is :-

Advantages :

  • Cross browser compatible
  • Can you sprite methods to cut down http requests to request image for each tab
  • Also, you are not losing the text which is between the a tags, which is really good as far as screen readers are concerned.

Disadvantages :

  • Set custom width for each

Note: If you are going for a sprite solution, than background-position is anyways a must property to be used, so be sure you check out the support table first, before opting the sprite method.

enter image description here

Credits - For support table

7 Comments

I edited, making it clearer why I would like to avoid that. It's a fair way out, though, if no other way comes up.
Fair points all, and I didn't think about spriting. I'm going to accept this unless anything else comes up in the next day.
@Pekka웃 Sure, take your time, but what you are trying here, is I feel lil cheesy, stick with standard methods... :)
I think the method is pretty good for this specific kind of problem - if just it were supported by all browsers...
I will go with this solution too if the need and is possible to manage Sprite Images
|
0

I would put PNG images into img tag and then set alt attribute.

<ul>
<li><a href="..." title="Journal"><img src="journal.png" alt="Journal"/></a></li>
<li><a href="..." title="Art"><img src="art.png" alt="Art"/></a></li>
<li><a href="..." title="Work"><img src="work.png" alt="Work"/></a></li>
</ul>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.