25

Assume I have an "images" folder directory under the root of my application. How can I, from within a .css file, reference an image in this directory using an ASP.NET app relative path.

Example:

When in development, the path of ~/Images/Test.gif might resolve to /MyApp/Images/Test.gif while, in production, it might resolve to /Images/Test.gif (depending on the virtual directory for the application). I, obviously, want to avoid having to modify the .css file between environments.

I know you can use Page.ResolveClientUrl to inject a url into a control's Style collection dynamically at render time. I would like to avoid doing this.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
user10834
  • 271
  • 1
  • 4
  • 5

8 Answers8

11

Unfortunately Firefox has a stupid bug here... the paths are relative to the path of the page, instead of being relative to the position of the CSS file. Which means if you have pages in different positions in the tree (like having Default.aspx in the root and Information.aspx in the View folder) there's no way to have working relative paths. (IE will correctly solve the paths relative to the location of the CSS file.)

The only thing I could find is this comment on http://www.west-wind.com/weblog/posts/269.aspx but, to be honest, I haven't managed to make it work yet. If I do I'll edit this comment:

re: Making sense of ASP.Net Paths by Russ Brooks February 25, 2006 @ 8:43 am

No one fully answered Brant's question about the image paths inside the CSS file itself. I've got the answer. The question was, "How do we use application-relative image paths INSIDE the CSS file?" I have long been frustrated by this very problem too, so I just spent the last 3 hours working out a solution.

The solution is to run your CSS files through the ASPX page handler, then use a small bit of server-side code in each of the paths to output the root application path. Ready?

  1. Add to web.config:
 <compilation debug="true">
 <!-- Run CSS files through the ASPX handler so we can write code in them. -->
 <buildProviders>
 <add extension=".css" type="System.Web.Compilation.PageBuildProvider" />
 </buildProviders>
 </compilation>

 <httpHandlers>
 <add path="*.css" verb="GET" type="System.Web.UI.PageHandlerFactory" validate="true" />
 </httpHandlers>
  1. Inside your CSS, use the Request.ApplicationPath property wherever a path exists, like this:

    #content { background: url(<%= Request.ApplicationPath %>/images/bg_content.gif) repeat-y; }

  2. .NET serves up ASPX pages with a MIME type of "text/html" by default, consequently, your new server-side CSS pages are served up with this MIME type which causes non-IE browsers to not read the CSS file correctly. We need to override this to be "text/css". Simply add this line as the first line of your CSS file:

    <%@ ContentType="text/css" %>
    
tomfanning
  • 9,552
  • 4
  • 50
  • 78
Marcel Popescu
  • 3,146
  • 3
  • 35
  • 42
  • 3
    This is false. Firefox never interpreted CSS paths relative to the path of the page. – Graham Jul 12 '11 at 19:46
  • 5
    This answer is wrong. Please see http://stackoverflow.com/questions/940451/using-relative-url-in-css-file-what-location-is-it-relative-to/940475#940475 – justis Sep 09 '11 at 21:17
  • I am pretty sure it was right at the time (I remember fighting that bug for a few hours before I figured it out). It might be wrong now :) – Marcel Popescu Sep 10 '11 at 08:10
  • I just edited your answer to make the crucial last line about the MIME type visible. Also, I found that if you surround it with CSS comment marks, it stops Visual Studio from complaining about invalid CSS. `/*<%@ ContentType="text/css" %>*/` – tomfanning Dec 16 '11 at 09:17
8

In case you didn't know you could do this...

If you give a relative path to a resource in a CSS it's relative to the CSS file, not file including the CSS.

background-image: url(../images/test.gif);

So this might work for you.

Allain Lalonde
  • 91,574
  • 70
  • 187
  • 238
  • 4
    not the case. it is relative to the containing page's url. this is the problem. – pstanton May 27 '10 at 06:38
  • 1
    I'm actively working with this in many browsers using the "incorrect" assumption above. – Allain Lalonde May 29 '10 at 03:46
  • See http://haacked.com/archive/2006/01/12/CSSURLReferencesAndURLRewriting.aspx and http://htmlhelp.com/reference/css/units.html ("Partial URLs are interpreted relative to the style sheet source, not to the HTML source.") – Sander Rijken Feb 08 '11 at 11:09
6

Make you life easy, just put images used in your CSS in the /css/ folder alongside /css/style.css. Then when you reference your images, use relative paths (e.g. url(images/image.jpg)).

I still keep images that are displayed with a <img> in an /images/ folder. Photos for example are content, they are not part of the website's skin/theme. Thus, they do not belong in the /css/ folder.

frank hadder
  • 4,384
  • 1
  • 31
  • 30
JohnB
  • 18,046
  • 16
  • 98
  • 110
  • 1
    This doesn't help when the site also has to work in a virtual directory – Sander Rijken Feb 08 '11 at 11:03
  • 2
    You can also use relative paths to go down a directory. If you have /images/image.jpg and /css/style.css then `url(../images/image.jpg)` will correctly target it. – frank hadder Jul 01 '11 at 15:30
  • How is this easier than just prefixing image paths with ../? This option has the added benefit of matching generally followed development standards. – Dan Oct 02 '12 at 22:33
3

Marcel Popescu's solution is using Request.ApplicationPath in the css file.

Never use Request.ApplicationPath - it is evil! Returns different results depending on the path!

Use the following instead.

background-image: url(<%= Page.ResolveUrl("~/images/bg_content.gif") %>);
Snarf
  • 31
  • 1
3

Put your dynamic CSS in a user control in an .ascx file and then you do not need to run all your css files through the asp.net page processer.

<%@ Control %>
<style type="text/css>
div.content
{
background-image:(url(<%= Page.ResolveUrl("~/images/image.png") %>);
}
</style>

But the easiest way to solve the ~ problem is to not use a ~ at all. In Visual Studio, in Solution Explorer, right click your application, select Properties Window and change the Virtual Path to /.

McGarnagle
  • 101,349
  • 31
  • 229
  • 260
1

On Windows 7, IIS 7.5:

Not only do you have to do the steps mentionned by Marcel Popescu.

You also need to add a handler mapping in IIS 7.5 handler mappings. So that IIS knows that *.css must be used with the System.Web.UI.PageHandlerFactory

It's not enough to just set the stuff in the web.config file.

TchiYuan
  • 4,258
  • 5
  • 28
  • 35
-3

Inside of the .css file you can use relative paths; so in your example, say you put your css file in ~/Styles/mystyles.css. You can use url(../Images/Test.gif) as an example.

Chris Shaffer
  • 32,199
  • 5
  • 49
  • 61
-4

I was having difficulty in getting background images to display for content containers and have tried many solutions similar to other posted here. I had set the relative path in the CSS file, set it as a style on the aspx page I wanted the background to display - nothing worked. I tried Marcel Popescu's solution and it still didn't work.

I did end up getting it to work following a combination of Marcel's solution and trial and error. I inserted the code into the web.config, inserted the text/css line into my CSS file but I removed the background property in the CSS file altogether and set it as a style on the content container in the aspx page I wanted the background to display.

It does mean that for each or any other pages that I want to display the background I will need to set the style background property but it works beautifully.